diff --git a/flow-server/src/test/java/ClassInDefaultPackage.java b/flow-server/src/test/java/ClassInDefaultPackage.java deleted file mode 100644 index 838fab9f9a4..00000000000 --- a/flow-server/src/test/java/ClassInDefaultPackage.java +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -import org.junit.Ignore; - -/** - * - * This class is test data. Don't delete it. - * - * @author Vaadin Ltd - * @since 1.0 - */ -@Ignore -public class ClassInDefaultPackage { - -} diff --git a/flow-server/src/test/java/com/vaadin/AssertionTest.java b/flow-server/src/test/java/com/vaadin/AssertionTest.java deleted file mode 100644 index ace73922c80..00000000000 --- a/flow-server/src/test/java/com/vaadin/AssertionTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Test that tests are run with assertions activated - */ -public class AssertionTest { - - @Test - public void testAssertionsAreEnabled() { - boolean assertOn = false; - // *assigns* true if assertions are on. - assert assertOn = true; - - Assert.assertTrue("Assertions are turned off for the server package", - assertOn); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/experimental/FeatureFlagsTest.java b/flow-server/src/test/java/com/vaadin/experimental/FeatureFlagsTest.java deleted file mode 100644 index ad04fbb17ef..00000000000 --- a/flow-server/src/test/java/com/vaadin/experimental/FeatureFlagsTest.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.experimental; - -import net.jcip.annotations.NotThreadSafe; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.internal.UsageStatistics; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.startup.ApplicationConfiguration; - -import static com.vaadin.experimental.FeatureFlags.PROPERTIES_FILENAME; - -@NotThreadSafe -public class FeatureFlagsTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private VaadinContext context; - private FeatureFlags featureFlags; - private File propertiesDir; - private ApplicationConfiguration configuration; - private File featureFlagsFile; - - @Before - public void before() throws IOException { - propertiesDir = temporaryFolder.newFolder(); - - context = new MockVaadinContext(); - configuration = Mockito.mock(ApplicationConfiguration.class); - Mockito.when(configuration.isProductionMode()).thenReturn(false); - - context.setAttribute(ApplicationConfiguration.class, configuration); - - featureFlags = FeatureFlags.get(context); - featureFlags.setPropertiesLocation(propertiesDir); - - mockResourcesLocation(); - - featureFlagsFile = new File(propertiesDir, PROPERTIES_FILENAME); - Files.deleteIfExists(featureFlagsFile.toPath()); - } - - @Test - public void propertiesLoaded() throws IOException { - Assert.assertFalse("Feature should be initially disabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - - // This is done automatically but from a static block which we cannot - // mock - featureFlags.loadProperties(); - - Assert.assertTrue("Feature should have been enabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - } - - @Test - public void setPropertiesLocation() throws Exception { - // Set location and ensure flags are loaded from there - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - Assert.assertFalse("Feature should be initially disabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - featureFlags.setPropertiesLocation(propertiesDir); - Assert.assertTrue("Feature should have been enabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - } - - @Test - public void setPropertiesLocationWithNoFileDisablesFeatures() - throws Exception { - // given an enabled feature - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - featureFlags.setPropertiesLocation(propertiesDir); - - // when a directory containing no vaadin-featureflags.properties is set - File emptyFolder = Files.createTempDirectory("test-folder").toFile(); - emptyFolder.deleteOnExit(); - featureFlags.setPropertiesLocation(emptyFolder); - - // then the feature should be disabled - Assert.assertFalse("Feature should have been disabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - } - - @Test - public void enableDisableFeature() throws IOException { - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=false\n"); - featureFlags.loadProperties(); - Assert.assertFalse( - "Feature should be disabled after reading the properties", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - featureFlags.setEnabled(FeatureFlags.EXAMPLE.getId(), true); - Assert.assertTrue("Feature should have been enabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - Assert.assertEquals( - "# Example feature. Will be removed once the first real feature flag is added\ncom.vaadin.experimental.exampleFeatureFlag=true\n", - FileUtils.readFileToString(featureFlagsFile, - StandardCharsets.UTF_8)); - - featureFlags.setEnabled(FeatureFlags.EXAMPLE.getId(), false); - Assert.assertFalse("Feature should have been disabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - Assert.assertEquals( - "Feature flags file should be empty when no features are enabled", - "", FileUtils.readFileToString(featureFlagsFile, - StandardCharsets.UTF_8)); - } - - @Test(expected = IllegalStateException.class) - public void setEnabledOnlyInDevelopmentMode() throws IOException { - Mockito.when(configuration.isProductionMode()).thenReturn(true); - - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - ApplicationConfiguration conf = ApplicationConfiguration - .get(VaadinService.getCurrent().getContext()); - Mockito.when(conf.isProductionMode()).thenReturn(true); - featureFlags.setEnabled(FeatureFlags.EXAMPLE.getId(), true); - } - - @Test - public void disabledFeatureFlagsNotMarkedInStatsWhenLoading() - throws IOException { - UsageStatistics.resetEntries(); - createFeatureFlagsFile(""); - featureFlags.loadProperties(); - Assert.assertFalse( - hasUsageStatsEntry("flow/featureflags/exampleFeatureFlag")); - } - - @Test - public void enabledFeatureFlagsMarkedInStatsWhenLoading() - throws IOException { - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - featureFlags.loadProperties(); - Assert.assertTrue( - hasUsageStatsEntry("flow/featureflags/exampleFeatureFlag")); - } - - @Test - public void disabledFeatureFlagsNotMarkedInStatsWhenToggled() - throws IOException { - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - UsageStatistics.resetEntries(); - featureFlags.setEnabled(FeatureFlags.EXAMPLE.getId(), false); - Assert.assertFalse( - hasUsageStatsEntry("flow/featureflags/exampleFeatureFlag")); - } - - @Test - public void enabledFeatureFlagsMarkedInStatsWhenToggled() - throws IOException { - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=false\n"); - UsageStatistics.resetEntries(); - featureFlags.setEnabled(FeatureFlags.EXAMPLE.getId(), true); - Assert.assertTrue( - hasUsageStatsEntry("flow/featureflags/exampleFeatureFlag")); - } - - @Test - public void featureFlagShouldBeOverridableWithSystemProperty() - throws IOException { - var feature = "exampleFeatureFlag"; - var propertyName = FeatureFlags.SYSTEM_PROPERTY_PREFIX + feature; - var previousValue = System.getProperty(propertyName); - - try { - System.setProperty(propertyName, "true"); - String fileContents = String - .format("com.vaadin.experimental.%s=false\n", feature); - createFeatureFlagsFile(fileContents); - featureFlags.loadProperties(); - Assert.assertTrue(featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - Assert.assertEquals( - "Feature flags file should not be overwritten by system property value", - fileContents, FileUtils.readFileToString(featureFlagsFile, - StandardCharsets.UTF_8)); - } finally { - if (previousValue == null) { - System.clearProperty(propertyName); - } else { - System.setProperty(propertyName, previousValue); - } - } - } - - @Test - public void featureFlagLoadedByResourceProviderShouldBeOverridableWithSystemProperty() - throws IOException { - var feature = "exampleFeatureFlag"; - var propertyName = FeatureFlags.SYSTEM_PROPERTY_PREFIX + feature; - var previousValue = System.getProperty(propertyName); - - File flagsFile = new File(propertiesDir, - "another-" + PROPERTIES_FILENAME); - - ResourceProvider resourceProvider = Mockito - .mock(ResourceProvider.class); - Mockito.when( - resourceProvider.getApplicationResource(PROPERTIES_FILENAME)) - .thenReturn(flagsFile.toURI().toURL()); - Lookup lookup = context.getAttribute(Lookup.class); - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(resourceProvider); - - try { - String fileContents = String - .format("com.vaadin.experimental.%s=false\n", feature); - FileUtils.write(flagsFile, fileContents, StandardCharsets.UTF_8); - - System.setProperty(propertyName, "true"); - featureFlags.loadProperties(); - Assert.assertTrue(featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - Assert.assertFalse( - "Setting feature flag by system properties should not create feature flag file", - featureFlagsFile.exists()); - } finally { - if (previousValue == null) { - System.clearProperty(propertyName); - } else { - System.setProperty(propertyName, previousValue); - } - } - } - - @Test - public void noFeatureFlagFile_systemPropertyProvided_featureEnabled() - throws IOException { - var feature = "exampleFeatureFlag"; - var propertyName = FeatureFlags.SYSTEM_PROPERTY_PREFIX + feature; - var previousValue = System.getProperty(propertyName); - - try { - System.setProperty(propertyName, "true"); - featureFlags.loadProperties(); - Assert.assertTrue( - "Feature set with system property should be enabled", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - Assert.assertFalse( - "Setting feature flag by system properties should not create feature flag file", - featureFlagsFile.exists()); - } finally { - if (previousValue == null) { - System.clearProperty(propertyName); - } else { - System.setProperty(propertyName, previousValue); - } - } - } - - @Test - public void noFeatureFlagFile_noSystemPropertyProvided_allFeatureDisabled() - throws IOException { - var feature = "exampleFeatureFlag"; - var propertyName = FeatureFlags.SYSTEM_PROPERTY_PREFIX + feature; - var previousValue = System.getProperty(propertyName); - - try { - if (previousValue != null) { - System.clearProperty(propertyName); - } - featureFlags.loadProperties(); - Assert.assertFalse( - "Feature not set with system property should be disabled by default", - featureFlags.isEnabled(FeatureFlags.EXAMPLE)); - } finally { - if (previousValue != null) { - System.setProperty(propertyName, previousValue); - } - } - } - - private boolean hasUsageStatsEntry(String name) { - return UsageStatistics.getEntries() - .filter(entry -> entry.getName().equals(name)).findFirst() - .isPresent(); - } - - private void mockResourcesLocation() { - VaadinService service = Mockito.mock(VaadinService.class); - VaadinService.setCurrent(service); - VaadinContext vaadinContext = Mockito.mock(VaadinContext.class); - Mockito.when(service.getContext()).thenReturn(vaadinContext); - - ApplicationConfiguration applicationConfiguration = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(vaadinContext.getAttribute( - Mockito.eq(ApplicationConfiguration.class), Mockito.any())) - .thenReturn(applicationConfiguration); - Mockito.when(applicationConfiguration.getJavaResourceFolder()) - .thenReturn(propertiesDir); - - } - - private void createFeatureFlagsFile(String data) throws IOException { - FileUtils.write(featureFlagsFile, data, StandardCharsets.UTF_8); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/NotifierTest.java b/flow-server/src/test/java/com/vaadin/flow/NotifierTest.java deleted file mode 100644 index dc32ac5701a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/NotifierTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow; - -import org.junit.Test; - -import com.vaadin.flow.component.BlurNotifier; -import com.vaadin.flow.component.ClickNotifier; -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.CompositionNotifier; -import com.vaadin.flow.component.FocusNotifier; -import com.vaadin.flow.component.InputNotifier; -import com.vaadin.flow.component.KeyNotifier; -import com.vaadin.flow.component.Tag; - -public class NotifierTest { - @Tag("div") - public static class NotifierComponent extends Component - implements BlurNotifier, - ClickNotifier, CompositionNotifier, - FocusNotifier, InputNotifier, KeyNotifier { - } - - @Test - public void addNotifiers() { - // Just testing that adding notifiers actually compiles and doesn't - // throw. Test is on purpose outside com.vaadin.flow.component to - // uncover visibility problems. - NotifierComponent component = new NotifierComponent(); - component.addBlurListener(event -> ignore()); - component.addClickListener(event -> ignore()); - component.addCompositionStartListener(event -> ignore()); - component.addCompositionEndListener(event -> ignore()); - component.addCompositionUpdateListener(event -> ignore()); - component.addInputListener(event -> ignore()); - component.addKeyDownListener(event -> ignore()); - component.addKeyUpListener(event -> ignore()); - component.addKeyPressListener(event -> ignore()); - } - - private static void ignore() { - // This method is here to avoid line breaks from {} lambas - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/WarURLStreamHandlerFactory.java b/flow-server/src/test/java/com/vaadin/flow/WarURLStreamHandlerFactory.java deleted file mode 100644 index 7f96975a1c2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/WarURLStreamHandlerFactory.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.vaadin.flow; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; -import java.security.Permission; - -public class WarURLStreamHandlerFactory implements URLStreamHandlerFactory { - - private static final String WAR_PROTOCOL = "war"; - - // Singleton instance - private static volatile WarURLStreamHandlerFactory instance = null; - - private final boolean registered; - - /** - * Obtain a reference to the singleton instance. It is recommended that - * callers check the value of {@link #isRegistered()} before using the - * returned instance. - * - * @return A reference to the singleton instance - */ - public static WarURLStreamHandlerFactory getInstance() { - getInstanceInternal(true); - return instance; - } - - private static WarURLStreamHandlerFactory getInstanceInternal( - boolean register) { - // Double checked locking. OK because instance is volatile. - if (instance == null) { - synchronized (WarURLStreamHandlerFactory.class) { - if (instance == null) { - instance = new WarURLStreamHandlerFactory(register); - } - } - } - return instance; - } - - private WarURLStreamHandlerFactory(boolean register) { - // Hide default constructor - // Singleton pattern to ensure there is only one instance of this - // factory - this.registered = register; - if (register) { - URL.setURLStreamHandlerFactory(this); - } - } - - public boolean isRegistered() { - return registered; - } - - /** - * Register this factory with the JVM. May be called more than once. The - * implementation ensures that registration only occurs once. - * - * @return true if the factory is already registered with the - * JVM or was successfully registered as a result of this call. - * false if the factory was disabled prior to this - * call. - */ - public static boolean register() { - return getInstanceInternal(true).isRegistered(); - } - - /** - * Prevent this this factory from registering with the JVM. May be called - * more than once. - * - * @return true if the factory is already disabled or was - * successfully disabled as a result of this call. - * false if the factory was already registered prior to - * this call. - */ - public static boolean disable() { - return !getInstanceInternal(false).isRegistered(); - } - - @Override - public URLStreamHandler createURLStreamHandler(String protocol) { - - // Tomcat's handler always takes priority so applications can't override - // it. - if (WAR_PROTOCOL.equals(protocol)) { - return new WarHandler(); - } - - // Unknown protocol - return null; - } - - public static class WarHandler extends URLStreamHandler { - - @Override - protected URLConnection openConnection(URL u) throws IOException { - return new WarURLConnection(u); - } - - @Override - protected void setURL(URL u, String protocol, String host, int port, - String authority, String userInfo, String path, String query, - String ref) { - if (path.startsWith("file:") && !path.startsWith("file:/")) { - // Work around a problem with the URLs in the security policy - // file. - // On Windows, the use of ${catalina.[home|base]} in the policy - // file - // results in codebase URLs of the form file:C:/... when they - // should - // be file:/C:/... - // For file: and jar: URLs, the JRE compensates for this. It - // does not - // compensate for this for war:file:... URLs. Therefore, we do - // that - // here - path = "file:/" + path.substring(5); - } - super.setURL(u, protocol, host, port, authority, userInfo, path, - query, ref); - } - - } - - public static class WarURLConnection extends URLConnection { - - private final URLConnection wrappedJarUrlConnection; - private boolean connected; - - protected WarURLConnection(URL url) throws IOException { - super(url); - URL innerJarUrl = warToJar(url); - wrappedJarUrlConnection = innerJarUrl.openConnection(); - } - - @Override - public void connect() throws IOException { - if (!connected) { - wrappedJarUrlConnection.connect(); - connected = true; - } - } - - @Override - public InputStream getInputStream() throws IOException { - connect(); - return wrappedJarUrlConnection.getInputStream(); - } - - @Override - public Permission getPermission() throws IOException { - return wrappedJarUrlConnection.getPermission(); - } - - @Override - public long getLastModified() { - return wrappedJarUrlConnection.getLastModified(); - } - - @Override - public int getContentLength() { - return wrappedJarUrlConnection.getContentLength(); - } - - @Override - public long getContentLengthLong() { - return wrappedJarUrlConnection.getContentLengthLong(); - } - - public static URL warToJar(URL warUrl) throws MalformedURLException { - // Assumes that the spec is absolute and starts war:file:/... - String file = warUrl.getFile(); - if (file.contains("*/")) { - file = file.replaceFirst("\\*/", "!/"); - } else if (file.contains("^/")) { - file = file.replaceFirst("\\^/", "!/"); - } - - return new URL("jar", warUrl.getHost(), warUrl.getPort(), file); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/AbstractCompositeFieldTest.java b/flow-server/src/test/java/com/vaadin/flow/component/AbstractCompositeFieldTest.java deleted file mode 100644 index 7bc0bf41c66..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/AbstractCompositeFieldTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.AbstractSinglePropertyFieldTest.StringField; -import com.vaadin.flow.component.ComponentTest.TestDiv; - -public class AbstractCompositeFieldTest { - - private static class ReverseCaseField extends - AbstractCompositeField { - public ReverseCaseField() { - super(""); - - getContent().addValueChangeListener(event -> { - setModelValue(reverseCase(event.getValue()), - event.isFromClient()); - }); - } - - @Override - protected void setPresentationValue(String newPresentationValue) { - getContent().setValue(reverseCase(newPresentationValue)); - } - - @Override - protected boolean valueEquals(String value1, String value2) { - if (value1 != null && value2 != null) { - return value1.trim().equals(value2.trim()); - } else { - return value1 == value2; - } - } - - private static String reverseCase(String input) { - int[] reversedCodePoints = input.codePoints().map(c -> { - if (Character.isUpperCase(c)) { - return Character.toLowerCase(c); - } else if (Character.isLowerCase(c)) { - return Character.toUpperCase(c); - } else { - return c; - } - }).toArray(); - - return new String(reversedCodePoints, 0, reversedCodePoints.length); - } - } - - @Test - public void reverseCaseField() { - ReverseCaseField outerField = new ReverseCaseField(); - StringField innerField = outerField.getContent(); - - outerField.setValue("Hello"); - Assert.assertEquals("hELLO", innerField.getValue()); - - innerField.setValue("wORLD"); - Assert.assertEquals("World", outerField.getValue()); - } - - @Test - public void emptyValueEquals() { - ReverseCaseField field = new ReverseCaseField(); - - Assert.assertTrue(field.isEmpty()); - - field.setValue("a"); - Assert.assertFalse(field.isEmpty()); - - field.setValue(" "); - Assert.assertTrue(field.isEmpty()); - } - - private static class MultipleFieldsField extends - AbstractCompositeField { - private StringField start = new StringField(); - private StringField rest = new StringField(); - - public MultipleFieldsField() { - super(null); - - getContent().getElement().appendChild(start.getElement(), - rest.getElement()); - - start.addValueChangeListener( - event -> updateValue(event.isFromClient())); - rest.addValueChangeListener( - event -> updateValue(event.isFromClient())); - } - - private void updateValue(boolean fromClient) { - String value = start.getValue(); - - String restValue = rest.getValue(); - if (!restValue.isEmpty()) { - value += " " + restValue; - } - - setModelValue(value, fromClient); - } - - @Override - protected void setPresentationValue(String newPresentationValue) { - String[] parts = newPresentationValue.split(" ", 2); - start.setValue(parts[0]); - - if (parts.length > 1) { - rest.setValue(parts[1]); - } else { - rest.setValue(""); - } - } - } - - @Test - public void multipleFieldsField() { - MultipleFieldsField field = new MultipleFieldsField(); - - field.setValue("Hello Cool World"); - Assert.assertEquals("Hello", field.start.getValue()); - Assert.assertEquals("Cool World", field.rest.getValue()); - - field.rest.setValue(""); - Assert.assertEquals("Hello", field.getValue()); - - field.rest.setValue("Vaadin"); - Assert.assertEquals("Hello Vaadin", field.getValue()); - } - - @Test - public void serializable() { - ReverseCaseField field = new ReverseCaseField(); - field.addValueChangeListener(ignore -> { - }); - field.setValue("foo"); - - ReverseCaseField anotherField = SerializationUtils.roundtrip(field); - Assert.assertEquals("foo", anotherField.getValue()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/AbstractFieldTest.java b/flow-server/src/test/java/com/vaadin/flow/component/AbstractFieldTest.java deleted file mode 100644 index 202fd00515a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/AbstractFieldTest.java +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.HasValue.ValueChangeEvent; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.SerializableBiPredicate; -import com.vaadin.flow.function.SerializableConsumer; -import com.vaadin.flow.function.SerializableSupplier; -import com.vaadin.tests.PublicApiAnalyzer; - -public class AbstractFieldTest { - // This isn't a test in itself, but it shows that no more than one method - // needs to be overridden - private static class SimpleAbstractField - extends AbstractField, T> { - - public SimpleAbstractField() { - super(null); - } - - @Override - protected void setPresentationValue(T value) { - } - } - - @Tag("tag") - private static class TestAbstractField - extends AbstractField, T> { - - public TestAbstractField() { - this(null); - } - - public TestAbstractField(T defaultValue) { - super(defaultValue); - } - - T presentationValue; - - SerializableConsumer setPresentationValue = value -> presentationValue = value; - - SerializableBiPredicate valueEquals; - SerializableSupplier emptyValue; - - @Override - protected void setPresentationValue(T value) { - setPresentationValue.accept(value); - } - - @Override - protected boolean valueEquals(T value1, T value2) { - if (valueEquals != null) { - return valueEquals.test(value1, value2); - } else { - return super.valueEquals(value1, value2); - } - } - - @Override - public T getEmptyValue() { - if (emptyValue != null) { - return emptyValue.get(); - } else { - return super.getEmptyValue(); - } - } - - public void updatePresentationValue(T value, boolean fromClient) { - this.presentationValue = value; - setModelValue(value, fromClient); - } - - @Override - public void setModelValue(T value, boolean fromClient) { - super.setModelValue(value, fromClient); - } - - public void valueUpdatedFromClient(boolean fromClient) { - super.setModelValue(presentationValue, fromClient); - } - } - - private static void assertNoEvents(HasValue observable) { - observable.addValueChangeListener( - event -> Assert.fail("Got unexpected event: " + event)); - } - - @Test - public void initialValue_used() { - TestAbstractField field = new TestAbstractField<>("foo"); - - Assert.assertEquals("foo", field.getValue()); - } - - @Test - public void emptyValue_sameAsInitial() { - TestAbstractField field = new TestAbstractField<>("foo"); - - Assert.assertEquals("foo", field.getEmptyValue()); - - field.setValue("bar"); - - Assert.assertEquals( - "Empty value shouldn't change when value is changed", "foo", - field.getEmptyValue()); - } - - @Test - public void initialValue_defaultNull() { - TestAbstractField field = new TestAbstractField<>(); - - Assert.assertNull(field.getValue()); - Assert.assertNull(field.getEmptyValue()); - } - - @Test - public void setValue_differentValue_firesOneEvent() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setValue("Foo"); - - eventMonitor.assertEvent(false, null, "Foo"); - Assert.assertEquals("Foo", field.presentationValue); - } - - @Test - public void setValue_sameValue_firesNoEvent() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setValue(field.getValue()); - - eventMonitor.assertNoEvent(); - } - - @Test - public void clear_firesIfNotEmpty() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.clear(); - eventMonitor.assertNoEvent(); - - field.setValue("foo"); - eventMonitor.discard(); - Assert.assertFalse(field.isEmpty()); - - field.clear(); - eventMonitor.assertEvent(false, "foo", null); - Assert.assertTrue(field.isEmpty()); - - field.clear(); - eventMonitor.assertNoEvent(); - } - - @Test - public void clear_customEmptyValue_emptyValueUsed() { - TestAbstractField field = new TestAbstractField<>(); - field.emptyValue = () -> ""; - - Assert.assertFalse(field.isEmpty()); - - field.clear(); - Assert.assertTrue(field.isEmpty()); - Assert.assertEquals("", field.getValue()); - } - - @Test - public void updateFromClient_differentValue_updatesAndFires() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.updatePresentationValue("foo", true); - eventMonitor.assertEvent(true, null, "foo"); - - field.updatePresentationValue("foo", true); - eventMonitor.assertNoEvent(); - } - - @Test - public void customEquals() { - TestAbstractField field = new TestAbstractField<>(); - field.valueEquals = (value1, value2) -> value1 == value2; - - Integer value1 = new Integer(0); - Integer value2 = new Integer(0); - - field.setValue(value1); - - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setValue(value1); - eventMonitor.assertNoEvent(); - - field.setValue(value2); - eventMonitor.assertEvent(false, value1, value2); - - field.updatePresentationValue(value2, true); - eventMonitor.assertNoEvent(); - - field.updatePresentationValue(value1, true); - eventMonitor.assertEvent(true, value2, value1); - } - - @Test - public void customEquals_isEmpty() { - Integer value1 = new Integer(0); - Integer value2 = new Integer(0); - - TestAbstractField field = new TestAbstractField<>(value1); - field.valueEquals = (v1, v2) -> v1 == v2; - - Assert.assertTrue(field.isEmpty()); - Assert.assertFalse(field.getOptionalValue().isPresent()); - - field.setValue(value2); - Assert.assertFalse(field.isEmpty()); - Assert.assertTrue(field.getOptionalValue().isPresent()); - - field.clear(); - Assert.assertTrue(field.isEmpty()); - Assert.assertFalse(field.getOptionalValue().isPresent()); - } - - @Test - public void getValue_changesAfterUpdatedFromClient() { - TestAbstractField field = new TestAbstractField<>(); - Assert.assertNull(field.getValue()); - - field.presentationValue = "foo"; - Assert.assertNull(field.getValue()); - - field.valueUpdatedFromClient(false); - Assert.assertEquals("foo", field.getValue()); - } - - @Test - public void setPresentation_setSameValue_notRunAgain() { - TestAbstractField field = new TestAbstractField<>(); - AtomicReference lastWriteValue = new AtomicReference<>(); - field.setPresentationValue = value -> { - Assert.assertNull("Unexpected update", - lastWriteValue.getAndSet(value)); - field.presentationValue = value; - }; - - field.setValue("foo"); - Assert.assertEquals("foo", lastWriteValue.get()); - - lastWriteValue.set(null); - - field.setValue("foo"); - Assert.assertNull(lastWriteValue.get()); - } - - @Test - public void updatePresentation_doesntCallSetPresentation() { - TestAbstractField field = new TestAbstractField<>(); - field.setPresentationValue = value -> Assert - .fail("setPresentationValue should not run"); - - field.updatePresentationValue("foo", true); - Assert.assertEquals("foo", field.getValue()); - } - - @Test - public void setPresentation_throws_sameException_valuePreserved() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setPresentationValue = value -> { - throw new IllegalStateException(value); - }; - - try { - field.setValue("foo"); - Assert.fail("Exception should have been thrown"); - } catch (IllegalStateException e) { - Assert.assertEquals("foo", e.getMessage()); - } - - eventMonitor.assertNoEvent(); - Assert.assertNull(field.getValue()); - } - - @Test - public void setPresentation_partialUpdates_onlyOneEvent() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setPresentationValue = value -> { - /* - * Emulate a situation where multiple element properties are - * modified, each firing its own value change event - */ - field.updatePresentationValue("temp value", true); - field.updatePresentationValue(value, true); - }; - - field.setValue("foo"); - eventMonitor.assertEvent(false, null, "foo"); - Assert.assertEquals("foo", field.getValue()); - } - - @Test - public void setPresentation_changesValue_onlyOneEvent() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setPresentationValue = value -> { - field.setPresentationValue = value2 -> Assert - .fail("setPresentationValue should not be called again"); - - field.updatePresentationValue(value.toUpperCase(Locale.ROOT), - false); - }; - - field.setValue("foo"); - eventMonitor.assertEvent(false, null, "FOO"); - Assert.assertEquals("FOO", field.getValue()); - } - - @Test - public void setPresentation_revertsValue_noEvent() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - - field.setPresentationValue = value -> { - field.setPresentationValue = value2 -> Assert - .fail("setPresentationValue should not be called again"); - field.valueUpdatedFromClient(false); - }; - - field.setValue("foo"); - eventMonitor.assertNoEvent(); - - Assert.assertNull(field.getValue()); - } - - @Test - public void setValueInEventHandler() { - TestAbstractField field = new TestAbstractField<>(); - - List> beforeEvents = new ArrayList<>(); - List> afterEvents = new ArrayList<>(); - - field.addValueChangeListener(beforeEvents::add); - field.addValueChangeListener(event -> { - event.getSource().setValue("bar"); - }); - field.addValueChangeListener(afterEvents::add); - - field.setValue("foo"); - - Assert.assertEquals(2, beforeEvents.size()); - ValueChangeMonitor.assertEventValues(beforeEvents.get(0), null, "foo"); - ValueChangeMonitor.assertEventValues(beforeEvents.get(1), "foo", "bar"); - - // Does not make sense, but still testing so we know how it works - // Also, this is how Vaadin 8 works, and nobody has been too upset - Assert.assertEquals(2, afterEvents.size()); - ValueChangeMonitor.assertEventValues(afterEvents.get(0), "foo", "bar"); - ValueChangeMonitor.assertEventValues(afterEvents.get(1), null, "foo"); - } - - @Test - public void requiredIndicator_writtenToElement() { - TestAbstractField field = new TestAbstractField<>(); - Element element = field.getElement(); - - Assert.assertFalse(element.getProperty("required", false)); - - field.setRequiredIndicatorVisible(true); - Assert.assertTrue(element.getProperty("required", false)); - - field.setRequiredIndicatorVisible(false); - Assert.assertFalse(element.getProperty("required", false)); - } - - @Test - public void requiredIndicator_readFromElement() { - TestAbstractField field = new TestAbstractField<>(); - Element element = field.getElement(); - - Assert.assertFalse(field.isRequiredIndicatorVisible()); - - element.setProperty("required", true); - Assert.assertTrue(field.isRequiredIndicatorVisible()); - - element.setProperty("required", false); - Assert.assertFalse(field.isRequiredIndicatorVisible()); - } - - @Test - public void readonly_writtenToElement() { - TestAbstractField field = new TestAbstractField<>(); - Element element = field.getElement(); - - Assert.assertFalse(element.getProperty("readonly", false)); - - field.setReadOnly(true); - Assert.assertTrue(element.getProperty("readonly", false)); - - field.setReadOnly(false); - Assert.assertFalse(element.getProperty("readonly", false)); - } - - @Test - public void readonly_readFromElement() { - TestAbstractField field = new TestAbstractField<>(); - Element element = field.getElement(); - - Assert.assertFalse(field.isReadOnly()); - - element.setProperty("readonly", true); - Assert.assertTrue(field.isReadOnly()); - - element.setProperty("readonly", false); - Assert.assertFalse(field.isReadOnly()); - } - - @Test - public void readonly_setValue_accepted() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - field.setReadOnly(true); - - field.setValue("foo"); - - eventMonitor.discard(); - Assert.assertEquals("foo", field.presentationValue); - Assert.assertEquals("foo", field.getValue()); - } - - @Test - public void readonly_presentationFromClient_reverted() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - field.setReadOnly(true); - - field.updatePresentationValue("foo", true); - - eventMonitor.assertNoEvent(); - Assert.assertEquals(null, field.getValue()); - Assert.assertEquals(null, field.presentationValue); - } - - @Test - public void readonly_presentationFromServer_accepted() { - TestAbstractField field = new TestAbstractField<>(); - ValueChangeMonitor eventMonitor = new ValueChangeMonitor<>( - field); - field.setReadOnly(true); - - field.updatePresentationValue("foo", false); - - eventMonitor.discard(); - Assert.assertEquals("foo", field.presentationValue); - Assert.assertEquals("foo", field.getValue()); - } - - @Test - public void noOwnPublicApi() { - List newPublicMethods = PublicApiAnalyzer - .findNewPublicMethods(AbstractField.class) - .collect(Collectors.toList()); - Assert.assertEquals(Collections.emptyList(), newPublicMethods); - } - - @Test - public void serializable() { - TestAbstractField field = new TestAbstractField<>(); - field.addValueChangeListener(ignore -> { - }); - field.setValue("foo"); - - TestAbstractField anotherField = SerializationUtils - .roundtrip(field); - Assert.assertEquals("foo", anotherField.getValue()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/AbstractSinglePropertyFieldTest.java b/flow-server/src/test/java/com/vaadin/flow/component/AbstractSinglePropertyFieldTest.java deleted file mode 100644 index 8d6b337b50e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/AbstractSinglePropertyFieldTest.java +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.lang.reflect.Method; -import java.time.LocalDate; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.dom.DomListenerRegistration; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.SerializableRunnable; -import com.vaadin.flow.internal.JsonUtils; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.tests.PublicApiAnalyzer; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonType; -import elemental.json.JsonValue; - -public class AbstractSinglePropertyFieldTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Tag("tag") - public static class StringField - extends AbstractSinglePropertyField { - - public StringField(String synchronizedPropertyName) { - super(synchronizedPropertyName, "", false); - } - - public StringField() { - this("property"); - } - - // Exposed as public for testing purposes - @Override - public void setSynchronizedEvent(String synchronizedEventName) { - super.setSynchronizedEvent(synchronizedEventName); - } - - } - - @Test - public void stringField_basicCases() { - StringField field = new StringField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals("", field.getValue()); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertNoEvent(); - - field.setValue("foo"); - Assert.assertEquals("foo", field.getElement().getProperty("property")); - monitor.assertEvent(false, "", "foo"); - - field.getElement().setProperty("property", "bar"); - Assert.assertEquals("bar", field.getValue()); - monitor.assertEvent(false, "foo", "bar"); - - // Cannot do removeProperty because - // https://github.com/vaadin/flow/issues/3994 - field.getElement().setProperty("property", null); - Assert.assertEquals("", field.getValue()); - monitor.assertEvent(false, "bar", ""); - } - - @Test - public void stringField_setValueNull_exceptionAndNoEvent() { - StringField field = new StringField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - try { - thrown.expect(NullPointerException.class); - field.setValue(null); - } finally { - monitor.assertNoEvent(); - } - } - - @Test - public void stringField_initProperty_noEvent() { - StringField field = new StringField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - field.getElement().setProperty("property", ""); - - monitor.assertNoEvent(); - } - - @Test - public void synchronizedEvent_default() { - StringField stringField = new StringField(); - - Assert.assertEquals("property-changed", - stringField.getSynchronizationRegistration().getEventType()); - } - - @Test - public void synchronizedEvent_redefined() { - StringField stringField = new StringField(); - DomListenerRegistration origReg = stringField - .getSynchronizationRegistration(); - SerializableRunnable unregisterListener = Mockito - .mock(SerializableRunnable.class); - origReg.onUnregister(unregisterListener); - - stringField.setSynchronizedEvent("blur"); - DomListenerRegistration recentReg = stringField - .getSynchronizationRegistration(); - Mockito.verify(unregisterListener).run(); - Assert.assertNotSame(origReg, recentReg); - Assert.assertEquals("blur", recentReg.getEventType()); - } - - @Test - public void synchronizedEvent_null_noSynchronization() { - StringField stringField = new StringField(); - SerializableRunnable unregisterListener = Mockito - .mock(SerializableRunnable.class); - stringField.getSynchronizationRegistration() - .onUnregister(unregisterListener); - - stringField.setSynchronizedEvent(null); - Assert.assertNull(stringField.getSynchronizationRegistration()); - Mockito.verify(unregisterListener).run(); - } - - @Test - public void synchronizedEvent_camelCaseProperty_dashCaseEvent() { - StringField stringField = new StringField("immediateValue"); - - Assert.assertEquals("immediate-value-changed", - stringField.getSynchronizationRegistration().getEventType()); - } - - @Tag("tag") - private static class StringNullField - extends AbstractSinglePropertyField { - public StringNullField() { - super("property", null, true); - } - } - - @Test - public void stringNullField_basicCases() { - StringNullField field = new StringNullField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals(null, field.getValue()); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertNoEvent(); - - field.getElement().setProperty("property", ""); - Assert.assertEquals("", field.getValue()); - monitor.assertEvent(false, null, ""); - - field.setValue(null); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertEvent(false, "", null); - } - - @Tag("tag") - private static class DoubleField - extends AbstractSinglePropertyField { - public DoubleField() { - super("property", Double.valueOf(0), false); - } - } - - @Test - public void doubleField_basicCases() { - DoubleField field = new DoubleField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals(0.0, field.getValue(), 0); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertNoEvent(); - - field.setValue(10.1); - Assert.assertEquals(10.1, - field.getElement().getProperty("property", 0.0), 0); - monitor.assertEvent(false, 0.0, 10.1); - - field.getElement().setProperty("property", 1.1); - Assert.assertEquals(1.1, field.getValue(), 0); - monitor.assertEvent(false, 10.1, 1.1); - - // Cannot do removeProperty because - // https://github.com/vaadin/flow/issues/3994 - field.getElement().setProperty("property", null); - Assert.assertEquals(0.0, field.getValue(), 0); - monitor.assertEvent(false, 1.1, 0.0); - } - - @Tag("tag") - private static class IntegerField - extends AbstractSinglePropertyField { - public IntegerField() { - super("property", Integer.valueOf(42), false); - } - } - - @Test - public void integerField_basicCases() { - IntegerField field = new IntegerField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals(42, field.getValue().intValue()); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertNoEvent(); - - field.setValue(0); - Assert.assertEquals(0, field.getElement().getProperty("property", -1)); - monitor.assertEvent(false, 42, 0); - - field.getElement().setProperty("property", 1); - Assert.assertEquals(1, field.getValue().intValue()); - monitor.assertEvent(false, 0, 1); - - // Cannot do removeProperty because - // https://github.com/vaadin/flow/issues/3994 - field.getElement().setProperty("property", null); - Assert.assertEquals(42, field.getValue().intValue()); - monitor.assertEvent(false, 1, 42); - } - - @Tag("tag") - private static class BooleanField - extends AbstractSinglePropertyField { - public BooleanField() { - super("property", Boolean.FALSE, false); - } - } - - @Test - public void booleanField_basicCases() { - BooleanField field = new BooleanField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertFalse(field.getValue()); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertNoEvent(); - - field.setValue(true); - Assert.assertTrue(field.getElement().getProperty("property", false)); - monitor.assertEvent(false, false, true); - - field.getElement().setProperty("property", false); - Assert.assertFalse(field.getValue()); - monitor.assertEvent(false, true, false); - - // Set value to true again so we can test that null -> false - field.setValue(true); - monitor.discard(); - - // Cannot do removeProperty because - // https://github.com/vaadin/flow/issues/3994 - field.getElement().setProperty("property", null); - Assert.assertFalse(field.getValue()); - monitor.assertEvent(false, true, false); - } - - @Tag("tag") - // Broken since AbstractSinglePropertyField cannot know how to store - // LocalDate instances in an element property - private static class SimpleDateField - extends AbstractSinglePropertyField { - public SimpleDateField() { - super("property", null, true); - } - } - - @Test(expected = IllegalArgumentException.class) - public void simpleDateField_constructor_throws() { - new SimpleDateField(); - } - - @Tag("tag") - private static class DateField - extends AbstractSinglePropertyField { - public DateField() { - super("property", null, String.class, LocalDate::parse, - LocalDate::toString); - } - } - - @Test - public void dateField_basicCases() { - DateField field = new DateField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals(null, field.getValue()); - Assert.assertFalse(field.getElement().hasProperty("property")); - monitor.assertNoEvent(); - - field.setValue(LocalDate.of(2018, 4, 25)); - Assert.assertEquals("2018-04-25", - field.getElement().getProperty("property")); - monitor.assertEvent(false, null, LocalDate.of(2018, 4, 25)); - - field.getElement().setProperty("property", "2017-03-24"); - Assert.assertEquals(LocalDate.of(2017, 3, 24), field.getValue()); - monitor.assertEvent(false, LocalDate.of(2018, 4, 25), - LocalDate.of(2017, 3, 24)); - - // Cannot do removeProperty because - // https://github.com/vaadin/flow/issues/3994 - field.getElement().setProperty("property", null); - Assert.assertEquals(null, field.getValue()); - monitor.assertEvent(false, LocalDate.of(2017, 3, 24), null); - } - - @Tag("tag") - private static class IntegerToStringField - extends AbstractSinglePropertyField { - public IntegerToStringField() { - super("property", null, String.class, Integer::new, - String::valueOf); - } - - @Override - protected boolean hasValidValue() { - return getElement().getProperty("property", "").matches("[0-9]*"); - } - } - - @Test - public void integerToString_basicCases() { - IntegerToStringField field = new IntegerToStringField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - Assert.assertNull(field.getValue()); - - // Verify base cases - field.getElement().setProperty("property", "10"); - Assert.assertEquals(10, field.getValue().intValue()); - monitor.assertEvent(false, null, 10); - - // Verify base cases - field.getElement().setProperty("property", null); - Assert.assertNull(field.getValue()); - monitor.assertEvent(false, 10, null); - - field.setValue(20); - Assert.assertEquals("20", field.getElement().getProperty("property")); - monitor.assertEvent(false, null, 20); - } - - @Test - public void integerToString_nonIntegerInput_ignore() { - IntegerToStringField field = new IntegerToStringField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - field.getElement().setProperty("property", "Not a number"); - monitor.assertNoEvent(); - Assert.assertNull(field.getValue()); - Assert.assertEquals("Unparseable should not affect property", - "Not a number", field.getElement().getProperty("property")); - - field.setValue(10); - monitor.assertEvent(false, null, 10); - Assert.assertEquals("setValue should override unparseable property", - "10", field.getElement().getProperty("property")); - } - - @Tag("tag") - private static class RadixField - extends AbstractSinglePropertyField { - - private int radix = 10; - - public RadixField() { - super("property", Integer.valueOf(0), String.class, - (instance, value) -> instance.presentationToModel(value), - (instance, value) -> instance.modelToPresentation(value)); - } - - private Integer presentationToModel(String presentationValue) { - return Integer.valueOf(Integer.parseInt(presentationValue, radix)); - } - - private String modelToPresentation(Integer integer) { - return Integer.toString(integer.intValue(), radix); - } - - public void setRadix(int radix) { - this.radix = radix; - - setPresentationValue(getValue()); - } - } - - @Test - public void radixField() { - RadixField field = new RadixField(); - ValueChangeMonitor changeMonitor = new ValueChangeMonitor<>( - field); - - field.setValue(20); - changeMonitor.discard(); - Assert.assertEquals("20", field.getElement().getProperty("property")); - - field.setRadix(16); - changeMonitor.assertNoEvent(); - Assert.assertEquals("14", field.getElement().getProperty("property")); - - field.getElement().setProperty("property", "f"); - changeMonitor.discard(); - Assert.assertEquals(15, field.getValue().intValue()); - } - - @Tag("tag") - private static class JsonField - extends AbstractSinglePropertyField { - public JsonField() { - super("property", Json.createNull(), false); - } - } - - @Tag("tag") - private static class JsonArrayField - extends AbstractSinglePropertyField { - public JsonArrayField() { - super("property", Json.createArray(), false); - } - } - - @Test - public void jsonField() { - JsonField field = new JsonField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals(JsonType.NULL, field.getValue().getType()); - monitor.assertNoEvent(); - - field.setValue( - JsonUtils.createArray(Json.create("foo"), Json.create(42))); - monitor.discard(); - Assert.assertEquals("[\"foo\",42]", - ((JsonArray) field.getElement().getPropertyRaw("property")) - .toJson()); - - field.getElement().setPropertyJson("property", Json.createObject()); - monitor.discard(); - Assert.assertEquals("{}", field.getValue().toJson()); - - field.getElement().setProperty("property", "text"); - monitor.discard(); - Assert.assertEquals("\"text\"", field.getValue().toJson()); - } - - @Test - public void jsonArrayField() { - JsonArrayField field = new JsonArrayField(); - ValueChangeMonitor monitor = new ValueChangeMonitor<>(field); - - Assert.assertEquals(JsonType.ARRAY, field.getValue().getType()); - Assert.assertEquals(0, field.getValue().length()); - monitor.assertNoEvent(); - - field.setValue( - JsonUtils.createArray(Json.create("foo"), Json.create(42))); - monitor.discard(); - Assert.assertEquals("[\"foo\",42]", - ((JsonArray) field.getElement().getPropertyRaw("property")) - .toJson()); - - field.getElement().setPropertyJson("property", - JsonUtils.createArray(Json.create(37), Json.create("bar"))); - monitor.discard(); - Assert.assertEquals("[37,\"bar\"]", field.getValue().toJson()); - } - - @Test - public void noOwnPublicApi() { - List newPublicMethods = PublicApiAnalyzer - .findNewPublicMethods(AbstractSinglePropertyField.class) - .collect(Collectors.toList()); - Assert.assertEquals(Collections.emptyList(), newPublicMethods); - } - - @Test - public void serializable() { - StringField field = new StringField(); - field.addValueChangeListener(ignore -> { - }); - field.setValue("foo"); - - StringField anotherField = SerializationUtils.roundtrip(field); - Assert.assertEquals("foo", anotherField.getValue()); - } - - @Test - public void getValue_wrapExistingElement_elementHasProperty_valueIsThePropertyValue() { - Element element = new Element("tag"); - element.setProperty("property", "foo"); - - UI ui = new UI(); - UI.setCurrent(ui); - VaadinSession session = Mockito.mock(VaadinSession.class); - ui.getInternals().setSession(session); - - VaadinService service = Mockito.mock(VaadinService.class); - Mockito.when(session.getService()).thenReturn(service); - - Instantiator instantiator = Mockito.mock(Instantiator.class); - - Mockito.when(service.getInstantiator()).thenReturn(instantiator); - - Mockito.when(instantiator.createComponent(StringField.class)) - .thenAnswer(a -> new StringField()); - - StringField field = Component.from(element, StringField.class); - Assert.assertEquals("foo", field.getValue()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ComponentEventBusTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ComponentEventBusTest.java deleted file mode 100644 index 8f5e67c66be..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ComponentEventBusTest.java +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.math.BigDecimal; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import com.vaadin.flow.component.ComponentTest.TestComponent; -import com.vaadin.flow.component.internal.KeyboardEvent; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.internal.JsonCodec; -import com.vaadin.flow.internal.MessageDigestUtil; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; -import com.vaadin.flow.router.RouterLink; -import com.vaadin.flow.shared.JsonConstants; -import com.vaadin.flow.shared.Registration; -import com.vaadin.tests.util.MockUI; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class ComponentEventBusTest { - - private static class EventTracker> - implements ComponentEventListener { - private AtomicInteger eventHandlerCalled = new AtomicInteger(0); - private AtomicReference eventObject = new AtomicReference<>(null); - - @Override - public void onComponentEvent(T e) { - eventHandlerCalled.incrementAndGet(); - Assert.assertNull( - "Event object must be explicitly set to null before firing an event", - eventObject.get()); - eventObject.set(e); - - } - - public int getCalls() { - return eventHandlerCalled.get(); - } - - public T getEvent() { - return eventObject.get(); - } - - public void reset() { - eventObject.set(null); - eventHandlerCalled.set(0); - } - - public void assertEventCalled(TestComponent source, - boolean fromClient) { - Assert.assertEquals(1, getCalls()); - Assert.assertEquals(source, getEvent().getSource()); - Assert.assertEquals(fromClient, getEvent().isFromClient()); - - } - - public void assertEventNotCalled() { - Assert.assertEquals(0, getCalls()); - } - - @Override - public boolean equals(Object obj) { - if (!super.equals(obj)) { - return false; - } - - @SuppressWarnings("unchecked") - EventTracker o = (EventTracker) obj; - return eventHandlerCalled.get() == o.eventHandlerCalled.get() - && eventObject.equals(o.eventObject); - } - } - - @Tag("button") - private class TestButton extends Component implements ClickNotifier { - - } - - private void fireDomEvent(Component component, String domEvent, - JsonObject eventData) { - Element e = component.getElement(); - e.getNode().getFeature(ElementListenerMap.class).fireEvent( - new com.vaadin.flow.dom.DomEvent(e, domEvent, eventData)); - - } - - @Test - public void mappedDomEvent_fire() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - - component.addListener(MappedToDomEvent.class, eventTracker); - component.getEventBus().fireEvent(new MappedToDomEvent(component)); - - eventTracker.assertEventCalled(component, false); - Assert.assertEquals(32, eventTracker.getEvent().getSomeData()); - Assert.assertEquals("Default constructor", - eventTracker.getEvent().getMoreData()); - - eventTracker.reset(); - component.getEventBus() - .fireEvent(new MappedToDomEvent(component, true)); - - eventTracker.assertEventCalled(component, true); - Assert.assertEquals(12, eventTracker.getEvent().getSomeData()); - Assert.assertEquals("Two arg constructor", - eventTracker.getEvent().getMoreData()); - } - - @Test - public void serverEvent_fire() { - AtomicInteger eventHandlerCalled = new AtomicInteger(0); - AtomicReference dataValueInEvent = new AtomicReference<>( - new BigDecimal(0)); - - TestComponentWithServerEvent component = new TestComponentWithServerEvent(); - component.addServerEventListener(e -> { - eventHandlerCalled.incrementAndGet(); - dataValueInEvent.set(e.getSomeValue()); - }); - - component - .fireEvent(new ServerEvent(component, new BigDecimal("12.22"))); - - Assert.assertEquals(1, eventHandlerCalled.get()); - Assert.assertEquals(new BigDecimal("12.22"), dataValueInEvent.get()); - } - - @Test - public void serverNoDataEvent_fire() { - TestComponent c = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - c.addListener(ServerNoDataEvent.class, eventTracker); - c.fireEvent(new ServerNoDataEvent(c, false)); - eventTracker.assertEventCalled(c, false); - Assert.assertFalse(eventTracker.getEvent().isFromClient()); - } - - @Test - public void serverNoDataEvent_fire_noListeners() { - TestComponent c = new TestComponent(); - c.fireEvent(new ServerNoDataEvent(c, false)); - } - - @Test - public void mappedDomEvent_fire_noListeners() { - TestComponent c = new TestComponent(); - fireDomEvent(c, "dom-event", Json.createObject()); - } - - @Test - public void mappedDomEvent_fire_missingData() { - TestComponent c = new TestComponent(); - EventTracker eventListener = new EventTracker<>(); - c.addListener(MappedToDomEvent.class, eventListener); - fireDomEvent(c, "dom-event", createData("event.someData", 2)); - eventListener.assertEventCalled(c, true); - Assert.assertEquals(2, eventListener.getEvent().getSomeData()); - Assert.assertNull(eventListener.getEvent().getMoreData()); - Assert.assertFalse(eventListener.getEvent().getPrimitiveBoolean()); - Assert.assertNull(eventListener.getEvent().getObjectBoolean()); - } - - @Test - public void mappedDomEventWithElementEventData_clientReportsElement_mapsElement() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - component.getElement().appendChild(child.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedToDomEventWithElementData.class, listener); - - fireDomEvent(component, "dom-event", createStateNodeIdData("element", - child.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertEquals(child.getElement(), - listener.getEvent().getElement()); - } - - @Test - public void mappedDomEventWithComponentEventData_clientReportsTypeComponent_mapsComponent() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - component.getElement().appendChild(child.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedDomEventWithComponentData.class, listener); - - fireDomEvent(component, "dom-event", createStateNodeIdData("component", - child.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertEquals(child, listener.getEvent().getComponent()); - } - - @Test - public void mappedDomEventWithComponentEventData_clientReportsConcreteComponents_mapsComponents() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - final RouterLink routerLink = new RouterLink(); - component.getElement().appendChild(child.getElement()); - child.getElement().appendChild(routerLink.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedDomEventWithRouterLinkData.class, listener); - - fireDomEvent(component, "dom-event", - createStateNodeIdData("component", - child.getElement().getNode().getId(), "router.link", - routerLink.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertEquals(routerLink, listener.getEvent().getRouterLink()); - Assert.assertEquals(child, listener.getEvent().getComponent()); - } - - @Test - public void mappedDomEventWithComponentEventData_clientReportsMissingComponent_mapsComponentAndNull() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - final RouterLink routerLink = new RouterLink(); - component.getElement().appendChild(child.getElement()); - child.getElement().appendChild(routerLink.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedDomEventWithRouterLinkData.class, listener); - - // null data will be used if event data is missing - fireDomEvent(component, "dom-event", createStateNodeIdData("component", - routerLink.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertNull(listener.getEvent().getRouterLink()); - Assert.assertEquals(routerLink, listener.getEvent().getComponent()); - - listener.reset(); - - fireDomEvent(component, "dom-event", createStateNodeIdData( - "router.link", routerLink.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertEquals(routerLink, listener.getEvent().getRouterLink()); - Assert.assertNull(listener.getEvent().getComponent()); - - listener.reset(); - } - - @Test - public void mappedDomEventWithComponentEventData_clientReportsSiblingComponentToEventSource_mapsComponents() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - final RouterLink routerLink = new RouterLink(); - ui.add(component, child, routerLink); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedDomEventWithRouterLinkData.class, listener); - - fireDomEvent(component, "dom-event", - createStateNodeIdData("component", - component.getElement().getNode().getId(), "router.link", - routerLink.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertEquals(routerLink, listener.getEvent().getRouterLink()); - Assert.assertEquals(component, listener.getEvent().getComponent()); - } - - @Test - public void mappedDomEventWithComponentEventData_clientReportsElementMissing_returnsNull() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - component.getElement().appendChild(child.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedDomEventWithComponentData.class, listener); - - fireDomEvent(component, "dom-event", - createStateNodeIdData("component", -1)); - listener.assertEventCalled(component, true); - Assert.assertNull(listener.getEvent().getComponent()); - } - - @Test - public void mappedDomEventWithComponentEventData_clientReportsMissingNodeIdReported_returnsNull() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent child = new TestComponent(); - component.getElement().appendChild(child.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedDomEventWithComponentData.class, listener); - - fireDomEvent(component, "dom-event", - createStateNodeIdData("component", 999999999)); - listener.assertEventCalled(component, true); - Assert.assertNull(listener.getEvent().getComponent()); - } - - @Test - public void mappedDomEventWithElementOrComponentEventData_clientReportsStateNodeForInvisibleComponent_returnsNull() { - final MockUI ui = new MockUI(); - final TestComponent component = new TestComponent(); - final TestComponent invisible = new TestComponent(); - component.getElement().appendChild(invisible.getElement()); - ui.add(component); - - final EventTracker listener = new EventTracker<>(); - component.addListener(MappedToDomEventWithElementData.class, listener); - - invisible.setVisible(false); - - fireDomEvent(component, "dom-event", createStateNodeIdData("element", - invisible.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - Assert.assertNull( - "Invisible elements/components should not be reported", - listener.getEvent().getElement()); - listener.reset(); - - final EventTracker second = new EventTracker<>(); - component.addListener(MappedDomEventWithComponentData.class, second); - - fireDomEvent(component, "dom-event", createStateNodeIdData("component", - invisible.getElement().getNode().getId())); - listener.assertEventCalled(component, true); - second.assertEventCalled(component, true); - Assert.assertNull( - "Invisible elements/components should not be reported", - listener.getEvent().getElement()); - Assert.assertNull( - "Invisible elements/components should not be reported", - second.getEvent().getComponent()); - } - - private JsonObject createStateNodeIdData(String key, int value) { - return createData(JsonConstants.MAP_STATE_NODE_EVENT_DATA + key, value); - } - - private JsonObject createStateNodeIdData(String key, int value, String key2, - int value2) { - return createData(JsonConstants.MAP_STATE_NODE_EVENT_DATA + key, value, - JsonConstants.MAP_STATE_NODE_EVENT_DATA + key2, value2); - } - - private JsonObject createData(String key, Object value) { - JsonObject data = Json.createObject(); - data.put(key, JsonCodec.encodeWithoutTypeInfo(value)); - return data; - } - - private JsonObject createData(String key, Object value, String key2, - Object value2) { - JsonObject data = Json.createObject(); - data.put(key, JsonCodec.encodeWithoutTypeInfo(value)); - data.put(key2, JsonCodec.encodeWithoutTypeInfo(value2)); - return data; - } - - @Test - public void domEvent_removeListener() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - Registration remover = component.addListener(MappedToDomEvent.class, - eventTracker); - remover.remove(); - - JsonObject eventData = createData("event.someData", 42, - "event.moreData", 1); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventNotCalled(); - assertNoListeners(component.getEventBus()); - } - - private void assertNoListeners(ComponentEventBus eventBus) { - Assert.assertTrue(eventBus.componentEventData.isEmpty()); - } - - @Test - public void domEvent_fireClientEvent() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - component.addListener(MappedToDomEvent.class, eventTracker); - - JsonObject eventData = createData("event.someData", 42, - "event.moreData", 1); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventCalled(component, true); - MappedToDomEvent event = eventTracker.getEvent(); - Assert.assertEquals(42, event.getSomeData()); - Assert.assertEquals("1", event.getMoreData()); - } - - @Test - public void domEvent_fireServerEvent() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - component.addListener(MappedToDomEvent.class, eventTracker); - - JsonObject eventData = Json.createObject(); - eventData.put("event.someData", 42); - eventData.put("event.moreData", 1); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventCalled(component, true); - MappedToDomEvent event = eventTracker.getEvent(); - Assert.assertEquals(42, event.getSomeData()); - Assert.assertEquals("1", event.getMoreData()); - } - - @Test - public void nonDomEvent_removeListener() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - Registration remover = component.addListener(ServerEvent.class, - eventTracker); - remover.remove(); - - component.fireEvent(new ServerEvent(component, new BigDecimal("12.2"))); - - eventTracker.assertEventNotCalled(); - assertNoListeners(component.getEventBus()); - } - - @Test - public void nonDomEvent_fireEvent() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - component.addListener(ServerEvent.class, eventTracker); - - component.fireEvent(new ServerEvent(component, new BigDecimal("12.2"))); - - eventTracker.assertEventCalled(component, false); - } - - @Test - public void domEvent_addListenerWithDomListenerConsumer() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - component.getEventBus().addListener(MappedToDomEvent.class, - eventTracker, domRegistration -> domRegistration.debounce(200)); - } - - @Test(expected = IllegalArgumentException.class) - public void nonDomEvent_addListenerWithDomListenerConsumer_throws() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - component.getEventBus().addListener(ServerEvent.class, eventTracker, - domRegistration -> domRegistration.debounce(200)); - } - - private int calls = 0; - - @Test - public void domEvent_addSameListenerTwice() { - TestComponent component = new TestComponent(); - - ComponentEventListener listener = e -> calls++; - - Registration reg1 = component.addListener(MappedToDomEvent.class, - listener); - Registration reg2 = component.addListener(MappedToDomEvent.class, - listener); - - Assert.assertEquals(1, - component.getEventBus().componentEventData.size()); - Assert.assertEquals(2, component.getEventBus().componentEventData - .get(MappedToDomEvent.class).size()); - - fireDomEvent(component, "dom-event", Json.createObject()); - Assert.assertEquals(2, calls); - - reg1.remove(); - Assert.assertEquals(1, - component.getEventBus().componentEventData.size()); - Assert.assertEquals(1, component.getEventBus().componentEventData - .get(MappedToDomEvent.class).size()); - - fireDomEvent(component, "dom-event", Json.createObject()); - - Assert.assertEquals(3, calls); - - reg2.remove(); - Assert.assertEquals(0, - component.getEventBus().componentEventData.size()); - - fireDomEvent(component, "dom-event", Json.createObject()); - Assert.assertEquals(3, calls); - } - - @Test - public void multipleEventsForSameDomEvent_removeListener() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - EventTracker eventTracker2 = new EventTracker<>(); - - Registration remover = component.addListener(MappedToDomEvent.class, - eventTracker); - Registration remover2 = component - .addListener(MappedToDomNoDataEvent.class, eventTracker2); - remover.remove(); - - JsonObject eventData = createData("event.someData", 42, - "event.moreData", 1); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventNotCalled(); - eventTracker2.assertEventCalled(component, true); - remover2.remove(); - - assertNoListeners(component.getEventBus()); - } - - @Test - public void multipleEventsForSameDomEvent_fireEvent() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - EventTracker eventTracker2 = new EventTracker<>(); - - component.addListener(MappedToDomEvent.class, eventTracker); - component.addListener(MappedToDomNoDataEvent.class, eventTracker2); - - JsonObject eventData = createData("event.someData", 42, - "event.moreData", 19); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventCalled(component, true); - Assert.assertEquals("19", eventTracker.getEvent().getMoreData()); - Assert.assertEquals(42, eventTracker.getEvent().getSomeData()); - Assert.assertEquals(component, eventTracker.getEvent().getSource()); - - eventTracker2.assertEventCalled(component, true); - } - - @Test - public void multipleListenersForSameEvent_fireEvent() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - EventTracker eventTracker2 = new EventTracker<>(); - - component.addListener(MappedToDomEvent.class, eventTracker); - component.addListener(MappedToDomEvent.class, eventTracker2); - - JsonObject eventData = createData("event.someData", 42, - "event.moreData", 19); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventCalled(component, true); - eventTracker2.assertEventCalled(component, true); - Assert.assertEquals("19", eventTracker.getEvent().getMoreData()); - Assert.assertEquals("19", eventTracker2.getEvent().getMoreData()); - Assert.assertEquals(42, eventTracker.getEvent().getSomeData()); - Assert.assertEquals(42, eventTracker2.getEvent().getSomeData()); - Assert.assertEquals(component, eventTracker.getEvent().getSource()); - Assert.assertEquals(component, eventTracker2.getEvent().getSource()); - } - - @Test - public void multipleListenersForSameEvent_removeListener() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - EventTracker eventTracker2 = new EventTracker<>(); - - Registration remover = component.addListener(MappedToDomEvent.class, - eventTracker); - Registration remover2 = component.addListener(MappedToDomEvent.class, - eventTracker2); - remover.remove(); - - JsonObject eventData = createData("event.someData", 42, - "event.moreData", 19); - fireDomEvent(component, "dom-event", eventData); - - eventTracker.assertEventNotCalled(); - eventTracker2.assertEventCalled(component, true); - Assert.assertEquals("19", eventTracker2.getEvent().getMoreData()); - Assert.assertEquals(42, eventTracker2.getEvent().getSomeData()); - Assert.assertEquals(component, eventTracker2.getEvent().getSource()); - remover2.remove(); - assertNoListeners(component.getEventBus()); - } - - @Test(expected = IllegalArgumentException.class) - public void invalidEventConstructor_addListener() { - TestComponent c = new TestComponent(); - c.addListener(InvalidMappedToDomEvent.class, e -> { - }); - } - - @Test(expected = IllegalArgumentException.class) - public void invalidEventDataInConstructor_addListener() { - TestComponent c = new TestComponent(); - c.addListener(MappedToDomInvalidEventData.class, e -> { - }); - } - - @Test(expected = IllegalArgumentException.class) - public void multipleEventDataConstructors_addListener() { - TestComponent c = new TestComponent(); - c.addListener(MappedToDomEventMultipleConstructors.class, e -> { - }); - } - - @Test(expected = IllegalArgumentException.class) - public void hasListeners_nullEventType_throws() { - new ComponentEventBus(new TestComponent()).hasListener(null); - } - - @Test(expected = IllegalArgumentException.class) - public void getListeners_nullEventType_throws() { - new ComponentEventBus(new TestComponent()).getListeners(null); - } - - @Test - public void getListeners_eventType_listenersCollection() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - Registration remover = component.addListener(MappedToDomEvent.class, - eventTracker); - Collection listeners = component - .getListeners(MappedToDomEvent.class); - Assert.assertEquals(1, listeners.size()); - remover.remove(); - } - - @Test - public void getListeners_subclassOfEventType_listenersCollection() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - EventTracker eventTracker2 = new EventTracker<>(); - Registration remover = component.addListener(KeyPressEvent.class, - eventTracker); - Registration remover2 = component.addListener(KeyUpEvent.class, - eventTracker2); - Collection listeners = component.getListeners(KeyboardEvent.class); - Assert.assertEquals(2, listeners.size()); - remover.remove(); - remover2.remove(); - } - - @Test - public void getListeners_notExistingEventType_emptyListenersCollection() { - TestComponent component = new TestComponent(); - EventTracker eventTracker = new EventTracker<>(); - Registration remover = component.addListener(MappedToDomEvent.class, - eventTracker); - Collection listeners = component.getListeners(ServerEvent.class); - Assert.assertTrue(listeners.isEmpty()); - remover.remove(); - } - - @Test - public void testFireEvent_noListeners_eventBusNotCreated() { - AtomicInteger eventBusCreated = new AtomicInteger(); - TestComponent c = new TestComponent() { - @Override - public ComponentEventBus getEventBus() { - eventBusCreated.incrementAndGet(); - return super.getEventBus(); - } - }; - c.fireEvent(new ServerEvent(c, new BigDecimal(0))); - - Assert.assertEquals(0, eventBusCreated.get()); - } - - @Test - public void eventUnregisterListener_insideListener() { - TestComponent c = new TestComponent(); - c.addListener(ServerEvent.class, e -> { - e.unregisterListener(); - }); - Assert.assertTrue(c.hasListener(ServerEvent.class)); - c.fireEvent(new ServerEvent(c, new BigDecimal(0))); - Assert.assertFalse(c.hasListener(ServerEvent.class)); - } - - @Test(expected = IllegalArgumentException.class) - public void eventUnregisterListener_insideListenerTwiceThrows() { - TestComponent c = new TestComponent(); - c.addListener(ServerEvent.class, e -> { - e.unregisterListener(); - e.unregisterListener(); - }); - c.fireEvent(new ServerEvent(c, new BigDecimal(0))); - } - - @Test(expected = IllegalStateException.class) - public void eventUnregisterListener_outsideListenerTwiceThrows() { - TestComponent c = new TestComponent(); - AtomicReference storedEvent = new AtomicReference<>(); - c.addListener(ServerEvent.class, e -> { - storedEvent.set(e); - }); - c.fireEvent(new ServerEvent(c, new BigDecimal(0))); - storedEvent.get().unregisterListener(); - } - - @Test // #7826 - public void addListener_eventDataExpressionsPresent_constantPoolKeyNotCreatedAfterEachExpression() { - final TestButton button = new TestButton(); - try (MockedStatic util = Mockito - .mockStatic(MessageDigestUtil.class)) { - util.when(() -> MessageDigestUtil.sha256(Mockito.anyString())) - .thenReturn( - new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }); - button.addClickListener(event -> { - }); - util.verifyNoInteractions(); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ComponentEventBusUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ComponentEventBusUtilTest.java deleted file mode 100644 index 2499a7ba030..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ComponentEventBusUtilTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.lang.reflect.Constructor; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.ComponentTest.TestComponent; -import com.vaadin.flow.internal.ReflectionCache; - -public class ComponentEventBusUtilTest { - - @DomEvent("dom-event") - public class InnerClass extends ComponentEvent { - - public InnerClass(Component source, boolean fromClient) { - super(source, fromClient); - } - - } - - @DomEvent("dom-event") - public static class NestedClass extends ComponentEvent { - - public NestedClass(Component source, boolean fromClient) { - super(source, fromClient); - } - - } - - @Test - public void domEvent_constructorCached() { - ReflectionCache, ?> cache = ComponentEventBusUtil.cache; - TestComponent component = new TestComponent(); - cache.clear(); - Assert.assertFalse(cache.contains(MappedToDomEvent.class)); - component.addListener(MappedToDomEvent.class, e -> { - }); - Assert.assertTrue(cache.contains(MappedToDomEvent.class)); - } - - @Test - public void domEvent_dataExpressionCached() { - TestComponent component = new TestComponent(); - ReflectionCache, ?> cache = ComponentEventBusUtil.cache; - cache.clear(); - Assert.assertFalse(cache.contains(MappedToDomEvent.class)); - component.addListener(MappedToDomEvent.class, e -> { - }); - Assert.assertTrue(cache.contains(MappedToDomEvent.class)); - } - - @Test - public void domEvent_innerEventClass() { - try { - ComponentEventBusUtil.getEventConstructor(InnerClass.class); - } catch (IllegalArgumentException exception) { - Assert.assertEquals("Cannot instantiate '" - + InnerClass.class.getName() + "'. " - + "Make sure the class is static if it is an inner class.", - exception.getMessage()); - } - } - - @Test - public void domEvent_nestedEventClass() { - Constructor ctor = ComponentEventBusUtil - .getEventConstructor(NestedClass.class); - Assert.assertNotNull(ctor); - } - - @Test - public void domEvent_localEventClass() { - @DomEvent("dom-event") - class LocalClass extends ComponentEvent { - - public LocalClass(Component source, boolean fromClient) { - super(source, fromClient); - } - - } - try { - ComponentEventBusUtil.getEventConstructor(LocalClass.class); - } catch (IllegalArgumentException exception) { - Assert.assertEquals( - "Cannot instantiate local class '" - + LocalClass.class.getName() + "'. " - + "Move class declaration outside the method.", - exception.getMessage()); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ComponentMetaDataTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ComponentMetaDataTest.java deleted file mode 100644 index e01f6abaf6e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ComponentMetaDataTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.internal.ComponentMetaData; -import com.vaadin.flow.component.internal.ComponentMetaData.SynchronizedPropertyInfo; -import com.vaadin.flow.dom.DisabledUpdateMode; - -public class ComponentMetaDataTest { - - @Tag(Tag.A) - public static class Sample extends Component { - - @Synchronize(value = "bar", property = "baz") - public String getFoo() { - return null; - } - - public String getBar() { - return null; - } - } - - public interface HasFoo { - @Synchronize(value = "bar", property = "baz", allowUpdates = DisabledUpdateMode.ALWAYS) - String getFoo(); - } - - public static class SubClass extends Sample { - - @Override - public String getFoo() { - return null; - } - - @Synchronize(value = "foo", property = "bar") - public String getBaz() { - return null; - } - } - - public static class ChangeSyncProperty extends Sample { - - @Override - @Synchronize(value = "baz", property = "foo") - public String getFoo() { - return null; - } - } - - @Tag(Tag.A) - public static class HasFooImpl extends Component implements HasFoo { - - @Override - public String getFoo() { - return null; - } - } - - public static class HasFooProtected extends Component { - @Synchronize(value = "bar", property = "baz") - protected String getFoo() { - return null; - } - } - - public static class HasFooPackagePrivate extends Component { - @Synchronize(value = "bar", property = "baz") - String getFoo() { - return null; - } - } - - public static class HasFooPrivate extends Component { - @Synchronize(value = "bar", property = "baz") - private String getFoo() { - return null; - } - } - - @Test - public void synchronizedProperties_methodInClass() { - assertFooProperty(Sample.class); - } - - @Test - public void synchronizedProperties_methodInInterface() { - assertFooProperty(HasFooImpl.class, DisabledUpdateMode.ALWAYS); - } - - @Test - public void synchronizedProperties_protectedMethod() { - assertFooProperty(HasFooProtected.class); - } - - @Test - public void synchronizedProperties_packagePrivateMethod() { - assertFooProperty(HasFooPackagePrivate.class); - } - - @Test - public void synchronizedProperties_privateMethod() { - assertFooProperty(HasFooPrivate.class); - } - - @Test - public void synchronizedProperties_hasOverriddenMethod() { - ComponentMetaData data = new ComponentMetaData(SubClass.class); - - Collection props = data - .getSynchronizedProperties(); - Assert.assertEquals(2, props.size()); - - List bazProps = props.stream() - .filter(prop -> prop.getProperty().equals("baz")) - .collect(Collectors.toList()); - Assert.assertEquals(1, bazProps.size()); - SynchronizedPropertyInfo info = bazProps.get(0); - - List events = info.getEventNames().collect(Collectors.toList()); - Assert.assertEquals(1, events.size()); - Assert.assertEquals("bar", events.get(0)); - - Assert.assertTrue(props.stream() - .anyMatch(prop -> prop.getProperty().equals("bar"))); - } - - @Test - public void synchronizedProperties_overridesMethodAndProperty() { - ComponentMetaData data = new ComponentMetaData( - ChangeSyncProperty.class); - - Collection props = data - .getSynchronizedProperties(); - Assert.assertEquals(1, props.size()); - - SynchronizedPropertyInfo info = props.iterator().next(); - Assert.assertEquals("foo", info.getProperty()); - - List events = info.getEventNames().collect(Collectors.toList()); - Assert.assertEquals(1, events.size()); - Assert.assertEquals("baz", events.get(0)); - } - - private void assertFooProperty(Class clazz) { - assertFooProperty(clazz, DisabledUpdateMode.ONLY_WHEN_ENABLED); - } - - private void assertFooProperty(Class clazz, - DisabledUpdateMode mode) { - ComponentMetaData data = new ComponentMetaData(clazz); - - Collection props = data - .getSynchronizedProperties(); - Assert.assertEquals(1, props.size()); - - SynchronizedPropertyInfo info = props.iterator().next(); - Assert.assertEquals("baz", info.getProperty()); - - Assert.assertEquals(mode, info.getUpdateMode()); - - List events = info.getEventNames().collect(Collectors.toList()); - Assert.assertEquals(1, events.size()); - Assert.assertEquals("bar", events.get(0)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ComponentTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ComponentTest.java deleted file mode 100644 index 56e41049bda..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ComponentTest.java +++ /dev/null @@ -1,1757 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.StyleSheet; -import com.vaadin.flow.component.dependency.Uses; -import com.vaadin.flow.component.internal.DependencyList; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.dom.DisabledUpdateMode; -import com.vaadin.flow.dom.DomEvent; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.Registration; -import com.vaadin.flow.shared.ui.Dependency; -import com.vaadin.tests.util.MockDeploymentConfiguration; -import com.vaadin.tests.util.MockUI; -import com.vaadin.tests.util.TestUtil; - -import elemental.json.Json; - -public class ComponentTest { - - private UI ui; - - @After - public void checkThreadLocal() { - Assert.assertNull(Component.elementToMapTo.get()); - } - - @com.vaadin.flow.component.DomEvent("foo") - public static class TestDomEvent extends ComponentEvent { - - public TestDomEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - - } - - @com.vaadin.flow.component.DomEvent(value = "foo", allowUpdates = DisabledUpdateMode.ALWAYS) - public static class EnabledDomEvent extends ComponentEvent { - public EnabledDomEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - } - - @Tag("div") - public static class TestDiv extends Component { - - @Synchronize(value = "bar", property = "baz", allowUpdates = DisabledUpdateMode.ALWAYS) - public String getFoo() { - return null; - } - - @Synchronize(value = "foo", property = "bar") - public String getBaz() { - return null; - } - } - - @Tag("div") - public static class EnabledDiv extends Component implements HasComponents { - } - - @Tag("div") - public static class TestComponentWhichHasComponentField extends Component { - private TestButton button = new TestButton(); - - public TestComponentWhichHasComponentField() { - getElement().appendChild(button.getElement()); - } - } - - public static class TestComponentWhichUsesElementConstructor - extends Component { - public TestComponentWhichUsesElementConstructor() { - super(new Element("my-element")); - } - } - - public static class TestComponentWhichUsesNullElementConstructor - extends Component { - public TestComponentWhichUsesNullElementConstructor() { - super(null); - } - } - - @Tag("div") - public static class TestComponentWhichCreatesComponentInConstructor - extends Component { - - public TestComponentWhichCreatesComponentInConstructor() { - getElement().appendChild(new TestButton().getElement()); - } - } - - @Tag("button") - public static class TestButton extends Component { - } - - @Tag("button") - public static class TestOtherButton extends Component { - } - - private Component divWithTextComponent; - private Component parentDivComponent; - private Component child1SpanComponent; - private Component child2InputComponent; - private Component shadowRootParent; - private Component shadowChild; - private UI testUI; - private MockServletServiceSessionSetup mocks; - - public interface TracksAttachDetach { - default void track() { - if (this instanceof Component) { - ((Component) this).addAttachListener( - event -> getAttachEvents().incrementAndGet()); - ((Component) this).addDetachListener( - event -> getDetachEvents().incrementAndGet()); - } else { - throw new IllegalStateException("Cannot track a non-component"); - } - } - - AtomicInteger getAttachEvents(); - - AtomicInteger getDetachEvents(); - - default void assertAttachEvents(int attachEvents) { - Assert.assertEquals(attachEvents, getAttachEvents().get()); - } - - default void assertDetachEvents(int detachEvents) { - Assert.assertEquals(detachEvents, getDetachEvents().get()); - } - } - - public static abstract class TracksAttachDetachComponent extends Component - implements TracksAttachDetach { - - private AtomicInteger attachEvents = new AtomicInteger(); - private AtomicInteger detachEvents = new AtomicInteger(); - - public TracksAttachDetachComponent() { - } - - public TracksAttachDetachComponent(Element element) { - super(element); - } - - @Override - public AtomicInteger getAttachEvents() { - return attachEvents; - } - - @Override - public AtomicInteger getDetachEvents() { - return detachEvents; - } - - } - - public static class TestComponent extends TracksAttachDetachComponent { - - public TestComponent() { - this(ElementFactory.createDiv()); - } - - public TestComponent(Element element) { - super(element); - } - - @Override - public String toString() { - return getElement().getText(); - } - - @Override - public void fireEvent(ComponentEvent componentEvent) { - super.fireEvent(componentEvent); - } - - @Override - public > Registration addListener( - Class eventType, ComponentEventListener listener) { - return super.addListener(eventType, listener); - } - - @Override - public ComponentEventBus getEventBus() { - return super.getEventBus(); - } - - } - - @Tag(Tag.DIV) - private static class TestComponentWithTag extends Component { - - } - - private static class TestComponentWithInheritedTag - extends TestComponentWithTag { - - } - - @Tag("") - private static class TestComponentWithEmptyTag extends Component { - - } - - private static class TestComponentWithoutTag extends Component { - - } - - private static class BrokenComponent extends Component { - - public BrokenComponent() { - super(null); - } - - } - - static class TestComponentContainer extends TestComponent { - - public TestComponentContainer() { - } - - public void add(Component c) { - getElement().appendChild(c.getElement()); - } - - public void remove(Component c) { - getElement().removeChild(c.getElement()); - } - } - - @Before - public void setup() throws Exception { - divWithTextComponent = new TestComponent( - ElementFactory.createDiv("Test component")); - parentDivComponent = new TestComponent(ElementFactory.createDiv()); - child1SpanComponent = new TestComponent( - ElementFactory.createSpan("Span")); - child2InputComponent = new TestComponent(ElementFactory.createInput()); - parentDivComponent.getElement().appendChild( - child1SpanComponent.getElement(), - child2InputComponent.getElement()); - - mocks = new MockServletServiceSessionSetup(); - - VaadinSession session = mocks.getSession(); - ui = new UI() { - @Override - public VaadinSession getSession() { - return session; - } - }; - ui.getInternals().setSession(session); - - UI.setCurrent(ui); - } - - @After - public void tearDown() { - UI.setCurrent(null); - mocks.cleanup(); - } - - @Test - public void getElement() { - Assert.assertEquals(Tag.DIV, - divWithTextComponent.getElement().getTag()); - Assert.assertEquals("Test component", - divWithTextComponent.getElement().getTextRecursively()); - } - - @Test - public void getParentForAttachedComponent() { - Assert.assertEquals(parentDivComponent, - child1SpanComponent.getParent().get()); - Assert.assertEquals(parentDivComponent, - child2InputComponent.getParent().get()); - } - - @Test - public void getUIForAttachedComponentInShadowRoot() { - shadowRootParent = new TestComponent(ElementFactory.createDiv()); - shadowRootParent.getElement().attachShadow(); - shadowChild = new TestComponent(ElementFactory.createSpan()); - shadowRootParent.getElement().getShadowRoot().get() - .appendChild(shadowChild.getElement()); - - testUI = new UI(); - testUI.add(shadowRootParent); - - Assert.assertEquals(testUI, shadowChild.getUI().get()); - } - - @Test - public void getParentForDetachedComponent() { - Assert.assertFalse(parentDivComponent.getParent().isPresent()); - } - - @Test - public void defaultGetChildrenDirectlyAttached() { - assertChildren(parentDivComponent, child1SpanComponent, - child2InputComponent); - } - - public static void assertChildren(Component parent, - Component... expectedChildren) { - List children = parent.getChildren() - .collect(Collectors.toList()); - Assert.assertArrayEquals(expectedChildren, children.toArray()); - for (Component c : children) { - Assert.assertEquals(c.getParent().get(), parent); - } - } - - @Test - public void defaultGetChildrenMultiple() { - // parent - // * level1 - // ** child1 - // ** child2 - - Element level1 = ElementFactory.createDiv("Level1"); - - parentDivComponent.getElement().appendChild(level1); - level1.appendChild(child1SpanComponent.getElement()); - level1.appendChild(child2InputComponent.getElement()); - - assertChildren(parentDivComponent, child1SpanComponent, - child2InputComponent); - - } - - @Test - public void defaultGetChildrenDirectlyDeepElementHierarchy() { - // parent - // * level1 - // ** level2 - // *** child1 - // * child2 - // * level1b - // ** child3 - - TestComponent parent = new TestComponent(ElementFactory.createDiv()); - TestComponent child1 = new TestComponent( - ElementFactory.createDiv("Child1")); - TestComponent child2 = new TestComponent( - ElementFactory.createDiv("Child2")); - TestComponent child3 = new TestComponent( - ElementFactory.createDiv("Child2")); - - Element parentElement = parent.getElement(); - parentElement.appendChild( - new Element("level1").appendChild( - new Element("level2").appendChild(child1.getElement())), - child2.getElement(), - new Element("level1b").appendChild(child3.getElement())); - - List children = parent.getChildren() - .collect(Collectors.toList()); - Assert.assertArrayEquals(new Component[] { child1, child2, child3 }, - children.toArray()); - - } - - @Test - public void defaultGetChildrenNoChildren() { - List children = parentDivComponent.getChildren() - .collect(Collectors.toList()); - Assert.assertArrayEquals( - new Component[] { child1SpanComponent, child2InputComponent }, - children.toArray()); - - } - - @Test(expected = AssertionError.class) - public void attachBrokenComponent() { - BrokenComponent c = new BrokenComponent(); - TestComponentContainer tc = new TestComponentContainer(); - tc.add(c); - } - - @Test - public void setElement() { - Component c = new Component(null) { - - }; - Element element = ElementFactory.createDiv(); - Component.setElement(c, element); - Assert.assertEquals(c, element.getComponent().get()); - Assert.assertEquals(element, c.getElement()); - } - - @Test(expected = IllegalArgumentException.class) - public void setElementNull() { - Component c = new Component(null) { - }; - Component.setElement(c, null); - } - - @Test(expected = IllegalStateException.class) - public void setElementTwice() { - Component c = new Component(null) { - }; - Element element = ElementFactory.createDiv(); - Component.setElement(c, element); - Component.setElement(c, element); - - } - - @Test - public void createComponentWithTag() { - Component component = new TestComponentWithTag(); - - Assert.assertEquals(Tag.DIV, component.getElement().getTag()); - } - - @Test - public void createComponentWithInheritedTag() { - Component component = new TestComponentWithInheritedTag(); - - Assert.assertEquals(Tag.DIV, component.getElement().getTag()); - } - - @Test(expected = IllegalStateException.class) - public void createComponentWithEmptyTag() { - new TestComponentWithEmptyTag(); - } - - @Test(expected = IllegalStateException.class) - public void createComponentWithoutTag() { - new TestComponentWithoutTag(); - } - - @Test - public void getUI_noParent() { - TestComponent c = new TestComponent(); - assertEmpty(c.getUI()); - } - - @Test - public void getUI_detachedParent() { - TestComponentContainer parent = new TestComponentContainer(); - TestComponent child = new TestComponent(); - parent.add(child); - assertEmpty(child.getUI()); - } - - @Test - public void getUI_attachedToUI() { - TestComponent child = new TestComponent(); - UI ui = new UI(); - ui.add(child); - Assert.assertEquals(ui, child.getUI().get()); - } - - @Test - public void getUI_attachedThroughParent() { - TestComponentContainer parent = new TestComponentContainer(); - TestComponent child = new TestComponent(); - parent.add(child); - UI ui = new UI(); - ui.add(parent); - Assert.assertEquals(ui, child.getUI().get()); - } - - private void assertEmpty(Optional optional) { - Assert.assertEquals("Optional should be empty but is " + optional, - Optional.empty(), optional); - } - - @Test - public void testAttachDetachListeners_parentAttachDetach_childListenersTriggered() { - UI ui = new UI(); - TestComponentContainer parent = new TestComponentContainer(); - TestComponentContainer child = new TestComponentContainer(); - TestComponent grandChild = new TestComponent(); - child.track(); - Registration attachRegistrationHandle = grandChild.addAttachListener( - event -> grandChild.getAttachEvents().incrementAndGet()); - Registration detachRegistrationHandle = grandChild.addDetachListener( - event -> grandChild.getDetachEvents().incrementAndGet()); - - parent.add(child); - child.add(grandChild); - - child.assertAttachEvents(0); - grandChild.assertAttachEvents(0); - - ui.add(parent); - - child.assertAttachEvents(1); - grandChild.assertAttachEvents(1); - child.assertDetachEvents(0); - grandChild.assertDetachEvents(0); - - ui.remove(parent); - parent.remove(child); - - child.assertAttachEvents(1); - grandChild.assertAttachEvents(1); - child.assertDetachEvents(1); - grandChild.assertDetachEvents(1); - - ui.add(parent); - parent.add(child); - - child.assertAttachEvents(2); - grandChild.assertAttachEvents(2); - child.assertDetachEvents(1); - grandChild.assertDetachEvents(1); - - ui.remove(parent); - - child.assertAttachEvents(2); - grandChild.assertAttachEvents(2); - child.assertDetachEvents(2); - grandChild.assertDetachEvents(2); - - attachRegistrationHandle.remove(); - detachRegistrationHandle.remove(); - - ui.add(child); - - child.assertAttachEvents(3); - grandChild.assertAttachEvents(2); - - ui.remove(child); - - child.assertDetachEvents(3); - grandChild.assertDetachEvents(2); - } - - @Test - public void testAttachListener_eventOrder_childFirst() { - UI ui = new UI(); - TestComponentContainer parent = new TestComponentContainer(); - TestComponent child = new TestComponent(); - child.track(); - parent.track(); - - child.addAttachListener(event -> { - Assert.assertEquals(0, parent.getAttachEvents().get()); - }); - parent.addAttachListener(event -> { - Assert.assertEquals(1, child.getAttachEvents().get()); - }); - - parent.add(child); - - child.assertAttachEvents(0); - parent.assertAttachEvents(0); - - ui.add(parent); - - child.assertAttachEvents(1); - parent.assertAttachEvents(1); - } - - @Test - public void testDetachListener_eventOrder_childFirst() { - UI ui = new UI(); - TestComponentContainer parent = new TestComponentContainer(); - TestComponent child = new TestComponent(); - child.track(); - parent.track(); - - child.addDetachListener(event -> { - Assert.assertEquals(0, parent.getDetachEvents().get()); - }); - parent.addDetachListener(event -> { - Assert.assertEquals(1, child.getDetachEvents().get()); - }); - - parent.add(child); - ui.add(parent); - - child.assertDetachEvents(0); - parent.assertDetachEvents(0); - - ui.remove(parent); - - child.assertDetachEvents(1); - parent.assertDetachEvents(1); - } - - @Test - public void testAttachDetach_elementMoved_bothEventsTriggered() { - UI ui = new UI(); - TestComponentContainer parent = new TestComponentContainer(); - TestComponent child = new TestComponent(); - - parent.add(child); - ui.add(parent); - - child.track(); - - child.addAttachListener(event -> { - Assert.assertEquals(1, child.getDetachEvents().get()); - }); - child.addDetachListener(event -> { - Assert.assertEquals(0, child.getAttachEvents().get()); - }); - - ui.add(child); - - child.assertAttachEvents(1); - child.assertDetachEvents(1); - } - - @Test - public void testAttachDetachEvent_uiCanBeFound() { - UI ui = new UI(); - TestComponent testComponent = new TestComponent(); - testComponent.track(); - - testComponent.addAttachListener(event -> Assert.assertEquals(ui, - event.getSource().getUI().get())); - - testComponent.addDetachListener(event -> Assert.assertEquals(ui, - event.getSource().getUI().get())); - - testComponent.assertAttachEvents(0); - - ui.add(testComponent); - - testComponent.assertAttachEvents(1); - - testComponent.assertDetachEvents(0); - - ui.remove(testComponent); - - testComponent.assertDetachEvents(1); - } - - @Test - public void testOnAttachOnDetachAndEventsOrder() { - List triggered = new ArrayList<>(); - Component customComponent = new Component(new Element("div")) { - @Override - protected void onAttach(AttachEvent attachEvent) { - triggered.add("onAttach"); - } - - @Override - protected void onDetach(DetachEvent detachEvent) { - triggered.add("onDetach"); - } - }; - customComponent - .addAttachListener(event -> triggered.add("attachEvent")); - customComponent - .addDetachListener(event -> triggered.add("detachEvent")); - - UI ui = new UI(); - ui.add(customComponent); - - TestUtil.assertArrays(triggered.toArray(), - new String[] { "onAttach", "attachEvent" }); - - triggered.clear(); - ui.remove(customComponent); - - TestUtil.assertArrays(triggered.toArray(), - new String[] { "onDetach", "detachEvent" }); - - TestComponentContainer container = new TestComponentContainer(); - - ui.add(customComponent, container); - triggered.clear(); - - container.add(customComponent); - - TestUtil.assertArrays(triggered.toArray(), new String[] { "onDetach", - "detachEvent", "onAttach", "attachEvent" }); - } - - @Test - public void testUIInitialAttach() { - AtomicBoolean initialAttach = new AtomicBoolean(false); - UI ui = new UI(); - ui.addAttachListener(e -> { - initialAttach.set(e.isInitialAttach()); - }); - - MockDeploymentConfiguration config = new MockDeploymentConfiguration(); - ui.getInternals().setSession( - new VaadinSession(new MockVaadinServletService(config))); - Assert.assertTrue(initialAttach.get()); - // UI is never detached and reattached - } - - @Test - public void testInitialAttach() { - AtomicBoolean initialAttach = new AtomicBoolean(false); - TestComponent c = new TestComponent(); - c.addAttachListener(e -> { - initialAttach.set(e.isInitialAttach()); - }); - UI ui = new UI(); - ui.add(c); - Assert.assertTrue(initialAttach.get()); - } - - @Test - public void testSecondAttach() { - AtomicBoolean initialAttach = new AtomicBoolean(false); - TestComponent c = new TestComponent(); - c.addAttachListener(e -> { - initialAttach.set(e.isInitialAttach()); - }); - UI ui = new UI(); - ui.add(c); - ui.remove(c); - ui.add(c); - Assert.assertFalse(initialAttach.get()); - } - - /** - * Tests {@link Component#isAttached}. - */ - @Test - public void testIsAttached() { - UI ui = new UI(); - // ui is initially attached - Assert.assertTrue(ui.isAttached()); - - TestComponentContainer parent = new TestComponentContainer(); - TestComponentContainer child = new TestComponentContainer(); - TestComponent grandChild = new TestComponent(); - child.track(); - grandChild.addAttachListener( - event -> Assert.assertTrue(grandChild.isAttached())); - grandChild.addDetachListener( - event -> grandChild.getDetachEvents().incrementAndGet()); - - parent.add(child); - child.add(grandChild); - Assert.assertFalse(parent.isAttached()); - Assert.assertFalse(child.isAttached()); - Assert.assertFalse(grandChild.isAttached()); - - ui.add(parent); - Assert.assertTrue(parent.isAttached()); - Assert.assertTrue(child.isAttached()); - Assert.assertTrue(grandChild.isAttached()); - - ui.remove(parent); - Assert.assertFalse(parent.isAttached()); - Assert.assertFalse(child.isAttached()); - Assert.assertFalse(grandChild.isAttached()); - - ui.add(parent); - Assert.assertTrue(parent.isAttached()); - Assert.assertTrue(child.isAttached()); - Assert.assertTrue(grandChild.isAttached()); - - // Mock closing of UI after request handled - ui.getInternals().setSession(Mockito.mock(VaadinSession.class)); - ui.close(); - ui.getInternals().setSession(null); - - Assert.assertFalse(parent.isAttached()); - Assert.assertFalse(child.isAttached()); - Assert.assertFalse(grandChild.isAttached()); - Assert.assertFalse(ui.isAttached()); - } - - @Test(expected = IllegalArgumentException.class) - public void wrapNullComponentType() { - new Element("div").as(null); - } - - @Test(expected = IllegalArgumentException.class) - public void wrapWrongTag() { - Element foo = new Element("foo"); - foo.as(TestDiv.class); - } - - @Test(expected = IllegalStateException.class) - public void wrappedComponentGetParent() { - Element div = new Element("div"); - Element button = new Element("button"); - div.appendChild(button); - - div.as(TestDiv.class); - button.as(TestButton.class).getParent(); - } - - @Test(expected = IllegalStateException.class) - public void wrappedComponentGetChildren() { - Element div = new Element("div"); - Element button = new Element("button"); - div.appendChild(button); - - button.as(TestButton.class); - div.as(TestDiv.class).getChildren(); - } - - @Test - public void componentFromHierarchy() { - Element div = new Element("div"); - Element button = new Element("button"); - div.appendChild(button); - - TestDiv testDiv = Component.from(div, TestDiv.class); - TestButton testButton = Component.from(button, TestButton.class); - Assert.assertEquals(testButton.getParent().get(), testDiv); - Assert.assertTrue(testDiv.getChildren().anyMatch(c -> c == testButton)); - } - - @Test - public void wrappedComponentUsesElement() { - Element div = new Element("div"); - div.setAttribute("id", "foo"); - Assert.assertEquals(Optional.of("foo"), div.as(TestDiv.class).getId()); - - } - - @Test - public void wrappedComponentModifyElement() { - Element div = new Element("div"); - div.as(TestDiv.class).setId("foo"); - Assert.assertEquals("foo", div.getAttribute("id")); - } - - @Test - public void wrapToExistingComponent() { - TestButton button = new TestButton(); - TestButton button2 = button.getElement().as(TestButton.class); - button.setId("id1"); - Assert.assertEquals(Optional.of("id1"), button2.getId()); - Assert.assertEquals(Optional.of("id1"), button.getId()); - } - - @Test - public void wrapDifferentTypeToExistingComponent() { - TestButton button = new TestButton(); - TestOtherButton button2 = button.getElement().as(TestOtherButton.class); - button.setId("id1"); - Assert.assertEquals(Optional.of("id1"), button2.getId()); - Assert.assertEquals(Optional.of("id1"), button.getId()); - } - - @Test(expected = IllegalArgumentException.class) - public void mapToExistingComponent() { - TestButton button = new TestButton(); - Component.from(button.getElement(), TestButton.class); - } - - @Test(expected = IllegalArgumentException.class) - public void mapToNullComponentType() { - Component.from(new Element("div"), null); - } - - @Test(expected = IllegalArgumentException.class) - public void mapFromNullElement() { - Component.from(null, TestButton.class); - } - - @Test - public void mapToComponentWhichCreatesComponentInConstructor() { - Element e = new Element("div"); - TestComponentWhichCreatesComponentInConstructor c = Component.from(e, - TestComponentWhichCreatesComponentInConstructor.class); - Element buttonElement = c.getElement().getChild(0); - - Assert.assertEquals(e, c.getElement()); - Assert.assertNotEquals(e, buttonElement); - Assert.assertEquals("button", buttonElement.getTag()); - } - - @Test - public void mapToComponentWhichHasComponentField() { - Element e = new Element("div"); - TestComponentWhichHasComponentField c = Component.from(e, - TestComponentWhichHasComponentField.class); - Element buttonElement = c.getElement().getChild(0); - - Assert.assertEquals(e, c.getElement()); - Assert.assertNotEquals(e, buttonElement); - Assert.assertEquals("button", buttonElement.getTag()); - } - - @Test - public void mapToComponentWithElementConstructor() { - Element e = new Element("my-element"); - TestComponentWhichUsesElementConstructor c = Component.from(e, - TestComponentWhichUsesElementConstructor.class); - - Assert.assertSame(e, c.getElement()); - Assert.assertSame(c, e.getComponent().get()); - } - - @Test - public void mapToComponentWithNullElementConstructor() { - Element e = new Element("div"); - TestComponentWhichUsesNullElementConstructor c = Component.from(e, - TestComponentWhichUsesNullElementConstructor.class); - - Assert.assertSame(e, c.getElement()); - Assert.assertSame(c, e.getComponent().get()); - } - - @Tag("div") - public static class SynchronizePropertyOnChangeComponent extends Component { - @Synchronize("change") - public String getFoo() { - return ""; - } - } - - public static class SynchronizePropertyUsingElementConstructor - extends Component { - public SynchronizePropertyUsingElementConstructor() { - super(null); - } - - @Synchronize("change") - public String getFoo() { - return ""; - } - - public void customInit() { - setElement(this, new Element("Span")); - - } - } - - @Tag("div") - public static class SynchronizePropertyOnChangeGivenPropertyComponent - extends Component { - @Synchronize(value = "change", property = "bar") - public String getFoo() { - return ""; - } - } - - @Tag("div") - public static class SynchronizePropertyOnMultipleEventsComponent - extends Component { - @Synchronize(value = { "input", "blur" }) - public String getFoo() { - return ""; - } - } - - @Tag("div") - public static class SynchronizeOnNonGetterComponent extends Component { - @Synchronize("change") - public String doWork() { - return ""; - } - } - - private void assertSynchronizedProperties(String domEventName, - Element element, String... properties) { - Set expected = Stream.of(properties) - .collect(Collectors.toSet()); - - Set expressions = element.getNode() - .getFeature(ElementListenerMap.class) - .getExpressions(domEventName); - - Assert.assertEquals(expected, expressions); - } - - @Test - public void synchronizePropertyBasedOnGetterName() { - SynchronizePropertyOnChangeComponent component = new SynchronizePropertyOnChangeComponent(); - Element element = component.getElement(); - assertSynchronizedProperties("change", element, "}foo"); - } - - @Test - public void synchronizePropertyElementConstructor() { - SynchronizePropertyUsingElementConstructor component = new SynchronizePropertyUsingElementConstructor(); - component.customInit(); - Element element = component.getElement(); - assertSynchronizedProperties("change", element, "}foo"); - } - - @Test - public void componentMetaDataCached() { - ComponentUtil.componentMetaDataCache.clear(); - Assert.assertFalse( - ComponentUtil.componentMetaDataCache.contains(Text.class)); - new Text("foobar"); - Assert.assertTrue( - ComponentUtil.componentMetaDataCache.contains(Text.class)); - } - - @Test - public void synchronizePropertyWithPropertyName() { - SynchronizePropertyOnChangeGivenPropertyComponent component = new SynchronizePropertyOnChangeGivenPropertyComponent(); - Element element = component.getElement(); - assertSynchronizedProperties("change", element, "}bar"); - } - - @Test - public void synchronizePropertyWithMultipleEvents() { - SynchronizePropertyOnMultipleEventsComponent component = new SynchronizePropertyOnMultipleEventsComponent(); - Element element = component.getElement(); - assertSynchronizedProperties("input", element, "}foo"); - assertSynchronizedProperties("blur", element, "}foo"); - } - - @Test(expected = IllegalStateException.class) - public void synchronizeOnNonGetter() { - new SynchronizeOnNonGetterComponent(); - } - - @Tag("div") - @JavaScript("js.js") - @StyleSheet("css.css") - public static class ComponentWithDependencies extends Component { - - } - - @Tag("span") - @Uses(ComponentWithDependencies.class) - @JavaScript("uses.js") - public static class UsesComponentWithDependencies extends Component { - - } - - @Tag("span") - @Uses(UsesComponentWithDependencies.class) - public static class UsesUsesComponentWithDependencies extends Component { - - } - - @Tag("div") - @StyleSheet("css1.css") - @Uses(CircularDependencies2.class) - public static class CircularDependencies1 extends Component { - - } - - @Tag("div") - @StyleSheet("css2.css") - @Uses(CircularDependencies1.class) - public static class CircularDependencies2 extends Component { - - } - - @Test - public void usesComponent() { - UI ui = UI.getCurrent(); - - ui.getInternals() - .addComponentDependencies(UsesComponentWithDependencies.class); - - Map pendingDependencies = getDependenciesMap( - ui.getInternals().getDependencyList().getPendingSendToClient()); - Assert.assertEquals(1, pendingDependencies.size()); - - assertDependency(Dependency.Type.STYLESHEET, "css.css", - pendingDependencies); - } - - @Test - public void usesChain() { - UIInternals internals = UI.getCurrent().getInternals(); - - internals.addComponentDependencies( - UsesUsesComponentWithDependencies.class); - - Map pendingDependencies = getDependenciesMap( - internals.getDependencyList().getPendingSendToClient()); - Assert.assertEquals(1, pendingDependencies.size()); - - assertDependency(Dependency.Type.STYLESHEET, "css.css", - pendingDependencies); - } - - @Test - public void circularDependencies() { - UIInternals internals = new MockUI().getInternals(); - DependencyList dependencyList = internals.getDependencyList(); - - internals.addComponentDependencies(CircularDependencies1.class); - Map pendingDependencies = getDependenciesMap( - dependencyList.getPendingSendToClient()); - Assert.assertEquals(2, pendingDependencies.size()); - - assertDependency(Dependency.Type.STYLESHEET, "css1.css", - pendingDependencies); - assertDependency(Dependency.Type.STYLESHEET, "css2.css", - pendingDependencies); - - internals = new MockUI().getInternals(); - dependencyList = internals.getDependencyList(); - internals.addComponentDependencies(CircularDependencies2.class); - pendingDependencies = getDependenciesMap( - dependencyList.getPendingSendToClient()); - Assert.assertEquals(2, pendingDependencies.size()); - assertDependency(Dependency.Type.STYLESHEET, "css1.css", - pendingDependencies); - assertDependency(Dependency.Type.STYLESHEET, "css2.css", - pendingDependencies); - - } - - @Test - public void noJsDependenciesAreAdded() { - UIInternals internals = new MockUI().getInternals(); - DependencyList dependencyList = internals.getDependencyList(); - - internals.addComponentDependencies(ComponentWithDependencies.class); - - Map pendingDependencies = getDependenciesMap( - dependencyList.getPendingSendToClient()); - Assert.assertEquals(1, pendingDependencies.size()); - assertDependency(Dependency.Type.STYLESHEET, "css.css", - pendingDependencies); - } - - @Test - public void declarativeSyncProperties_propertiesAreRegisteredWithProperDisabledUpdateMode() { - TestDiv div = new TestDiv(); - - ElementListenerMap feature = div.getElement().getNode() - .getFeature(ElementListenerMap.class); - - Set props = feature.getExpressions("bar"); - Assert.assertEquals(1, props.size()); - Assert.assertTrue(props.contains("}baz")); - Assert.assertEquals(DisabledUpdateMode.ALWAYS, - feature.getPropertySynchronizationMode("baz")); - - props = feature.getExpressions("foo"); - Assert.assertEquals(1, props.size()); - Assert.assertTrue(props.contains("}bar")); - Assert.assertEquals(DisabledUpdateMode.ONLY_WHEN_ENABLED, - feature.getPropertySynchronizationMode("bar")); - } - - @Test - public void enabledComponent_fireDomEvent_listenerReceivesEvent() { - TestDiv div = new TestDiv(); - - AtomicInteger count = new AtomicInteger(); - div.addListener(TestDomEvent.class, vent -> count.incrementAndGet()); - div.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(createEvent("foo", div)); - - Assert.assertEquals(1, count.get()); - } - - @Test - public void disabledComponent_fireDomEvent_listenerDoesntReceivesEvent() { - TestDiv div = new TestDiv(); - div.getElement().setEnabled(false); - - AtomicInteger count = new AtomicInteger(); - div.addListener(TestDomEvent.class, vent -> count.incrementAndGet()); - div.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(createEvent("foo", div)); - - Assert.assertEquals(0, count.get()); - } - - @Test - public void implicityDisabledComponent_fireDomEvent_listenerDoesntReceivesEvent() { - TestDiv div = new TestDiv(); - - UI ui = new UI(); - ui.add(div); - ui.setEnabled(false); - - AtomicInteger count = new AtomicInteger(); - div.addListener(TestDomEvent.class, event -> count.incrementAndGet()); - div.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(createEvent("foo", div)); - - Assert.assertEquals(0, count.get()); - } - - @Test - public void disabledComponent_fireAlwaysEnabledDomEvent_listenerReceivesEvent() { - TestDiv div = new TestDiv(); - - div.getElement().setEnabled(false); - - AtomicInteger count = new AtomicInteger(); - div.addListener(EnabledDomEvent.class, - event -> count.incrementAndGet()); - div.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(createEvent("foo", div)); - - Assert.assertEquals(1, count.get()); - } - - @Test - public void removeOnRegistration_registrationIsIdempotent() { - TestDiv div = new TestDiv(); - Registration registration = div.addListener(ComponentEvent.class, - (ComponentEventListener) event -> { - }); - - registration.remove(); - // It's still possible to call the same method one more time - registration.remove(); - } - - private DomEvent createEvent(String type, Component component) { - return new DomEvent(component.getElement(), type, Json.createObject()); - } - - private void assertDependency(Dependency.Type type, String url, - Map pendingDependencies) { - Dependency dependency = pendingDependencies.get(url); - Assert.assertNotNull( - "Could not locate a dependency object for url=" + url, - dependency); - Assert.assertEquals(type, dependency.getType()); - Assert.assertEquals(url, dependency.getUrl()); - } - - private Map getDependenciesMap( - Collection dependencies) { - return dependencies.stream().collect( - Collectors.toMap(Dependency::getUrl, Function.identity())); - } - - @Test // 3818 - public void enabledStateChangeOnAttachCalledForParentState() { - enabledStateChangeOnAttachCalledForParentState(false, - (parent, child) -> parent.add(child)); - } - - @Test // 7085 - public void enabledStateChangeOnDisableParent() { - enabledStateChangeOnAttachCalledForParentState(true, - (parent, child) -> { - parent.add(child); - parent.setEnabled(false); - }); - } - - @Test - public void enabledStateChangeOnAttachCalledForParentOfVirtualChildState() { - enabledStateChangeOnAttachCalledForParentState(false, - (parent, child) -> { - Element wrapper = ElementFactory.createAnchor(); - parent.getElement().appendVirtualChild(wrapper); - wrapper.appendChild(child.getElement()); - }); - } - - @Test - public void enabledStateChangeOnDisableParentOfVirtualChild() { - enabledStateChangeOnAttachCalledForParentState(true, - (parent, child) -> { - Element wrapper = ElementFactory.createAnchor(); - parent.getElement().appendVirtualChild(wrapper); - wrapper.appendChild(child.getElement()); - parent.setEnabled(false); - }); - } - - @Test // 3818 - public void enabledStateChangeOnDetachReturnsOldState() { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - parent.setEnabled(false); - ui.add(parent); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - stateChange.set(enabled); - } - }; - - Assert.assertFalse("Parent should be disabled", parent.isEnabled()); - Assert.assertTrue("Child should be enabled.", child.isEnabled()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - - parent.add(child); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - - parent.remove(child); - - Assert.assertTrue("After detach child should be enabled", - child.isEnabled()); - Assert.assertTrue("Enable event should have triggered", - stateChange.get()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - } - - @Test - public void enabledStateChangeOnParentDetachReturnsOldState() { - enabledStateChangeOnParentDetachReturnsOldState( - (parent, child) -> parent.add(child)); - } - - @Test - public void enabledStateChangeOnParentOfVirtualChildDetachReturnsOldState() { - enabledStateChangeOnParentDetachReturnsOldState((parent, child) -> { - Element wrapper = ElementFactory.createAnchor(); - parent.getElement().appendVirtualChild(wrapper); - wrapper.appendChild(child.getElement()); - }); - } - - @Test // 3818 - public void enabledStateChangeOnDetachChildKeepsDisabledState() { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - parent.setEnabled(false); - ui.add(parent); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - stateChange.set(enabled); - } - }; - child.setEnabled(false); - // Clear state change from setEnabled - stateChange.set(null); - - Assert.assertFalse("Parent should be disabled", parent.isEnabled()); - Assert.assertFalse("Child should be enabled.", child.isEnabled()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - - parent.add(child); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertNull("No change event should have fired", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - - parent.remove(child); - - Assert.assertFalse("After detach child should still be disabled", - child.isEnabled()); - Assert.assertNull("No change event should have fired", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - } - - @Test // 3818 - public void enabledStateChangeOnAttachAndDetachChildAndGrandChildrenAreNotified() { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - parent.setEnabled(false); - ui.add(parent); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - stateChange.set(enabled); - } - }; - AtomicReference grandStateChange = new AtomicReference<>(); - EnabledDiv grandChild = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - grandStateChange.set(enabled); - } - }; - child.add(grandChild); - - Assert.assertFalse("Parent should be disabled", parent.isEnabled()); - Assert.assertTrue("Child should be enabled.", child.isEnabled()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - Assert.assertTrue("GrandChild should be enabled.", - grandChild.isEnabled()); - Assert.assertNull(grandChild.getElement().getAttribute("disabled")); - - parent.add(child); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - Assert.assertFalse("After attach GrandChild should be disabled", - grandChild.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - grandStateChange.get()); - Assert.assertNotNull(grandChild.getElement().getAttribute("disabled")); - - parent.remove(child); - - Assert.assertTrue("After detach child should be enabled", - child.isEnabled()); - Assert.assertTrue("Enable event should have triggered", - stateChange.get()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - Assert.assertTrue("After detach GrandChild should be enabled", - grandChild.isEnabled()); - Assert.assertTrue("GrandChild should have gotten true event", - grandStateChange.get()); - Assert.assertNull(grandChild.getElement().getAttribute("disabled")); - } - - @Test // 3818 - public void enabledStateChangeOnAttachAndDetachDisabledChildAndGrandChildAreDisabled() { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - parent.setEnabled(false); - ui.add(parent); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - stateChange.set(enabled); - } - }; - child.setEnabled(false); - // Clear state change from setEnabled - stateChange.set(null); - AtomicReference grandStateChange = new AtomicReference<>(); - EnabledDiv grandChild = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - grandStateChange.set(enabled); - } - }; - child.add(grandChild); - - Assert.assertFalse("Parent should be disabled", parent.isEnabled()); - Assert.assertFalse("Child should be disabled.", child.isEnabled()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - Assert.assertFalse("GrandChild should be disabled.", - grandChild.isEnabled()); - // note that add doesn't create an attach event as we are not connected - // to the UI. - Assert.assertNull(grandChild.getElement().getAttribute("disabled")); - - parent.add(child); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertNull("Disabled event should have triggered", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - Assert.assertFalse("After attach GrandChild should be disabled", - grandChild.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - grandStateChange.get()); - Assert.assertNotNull(grandChild.getElement().getAttribute("disabled")); - - parent.remove(child); - - Assert.assertFalse("After detach child should be disabled", - child.isEnabled()); - Assert.assertNull("No change event should have been sent", - stateChange.get()); - Assert.assertFalse("After detach GrandChild should be disabled", - grandChild.isEnabled()); - Assert.assertFalse("Latest state change should have been disabled", - grandStateChange.get()); - } - - @Test // 3818 - public void enabledStateChangeOnAttachAndDetachDisabledGrandChildAreDisabled() { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - parent.setEnabled(false); - ui.add(parent); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - stateChange.set(enabled); - } - }; - AtomicReference grandStateChange = new AtomicReference<>(); - EnabledDiv grandChild = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - grandStateChange.set(enabled); - } - }; - grandChild.setEnabled(false); - child.add(grandChild); - - Assert.assertFalse("Parent should be disabled", parent.isEnabled()); - Assert.assertTrue("Child should be enabled.", child.isEnabled()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - Assert.assertFalse("GrandChild should be disabled.", - grandChild.isEnabled()); - Assert.assertNotNull(grandChild.getElement().getAttribute("disabled")); - - parent.add(child); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - Assert.assertFalse("After attach GrandChild should be disabled", - grandChild.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - grandStateChange.get()); - Assert.assertNotNull(grandChild.getElement().getAttribute("disabled")); - - parent.remove(child); - - Assert.assertTrue("After detach child should be enabled", - child.isEnabled()); - Assert.assertTrue("Enable event should have triggered", - stateChange.get()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - Assert.assertFalse("After detach GrandChild should be disabled", - grandChild.isEnabled()); - Assert.assertFalse("Latest state change should have been disabled", - grandStateChange.get()); - Assert.assertNotNull(grandChild.getElement().getAttribute("disabled")); - } - - @Test // 3818 - public void enabledPassesThroughAllChildensChildrenAndAttributeShouldBeSet() { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - EnabledDiv child = new EnabledDiv(); - EnabledDiv subChild = new EnabledDiv(); - EnabledDiv subSubChild = new EnabledDiv(); - - parent.add(child); - child.add(subChild); - subChild.add(subSubChild); - - ui.add(parent); - - Assert.assertTrue("Parent should be enabled.", parent.isEnabled()); - Assert.assertTrue("Child should be enabled.", child.isEnabled()); - Assert.assertTrue("SubChild should be enabled.", subChild.isEnabled()); - Assert.assertTrue("SubsubChild should be enabled.", - subSubChild.isEnabled()); - - Assert.assertNull("No disabled attribute should not exist for parent", - parent.getElement().getAttribute("disabled")); - Assert.assertNull("No disabled attribute should not exist for child", - child.getElement().getAttribute("disabled")); - Assert.assertNull("No disabled attribute should not exist for subChild", - subChild.getElement().getAttribute("disabled")); - Assert.assertNull( - "No disabled attribute should not exist for subSubChild", - subSubChild.getElement().getAttribute("disabled")); - - parent.setEnabled(false); - - Assert.assertFalse("Parent should be disabled.", parent.isEnabled()); - Assert.assertFalse("Child should be disabled.", child.isEnabled()); - Assert.assertFalse("SubChild should be disabled.", - subChild.isEnabled()); - Assert.assertFalse("SubsubChild should be disabled.", - subSubChild.isEnabled()); - - Assert.assertNotNull("Disabled attribute should exist for parent", - parent.getElement().getAttribute("disabled")); - Assert.assertNotNull("Disabled attribute should exist for child", - child.getElement().getAttribute("disabled")); - Assert.assertNotNull("Disabled attribute should exist for subChild", - subChild.getElement().getAttribute("disabled")); - Assert.assertNotNull("Disabled attribute should exist for subSubChild", - subSubChild.getElement().getAttribute("disabled")); - - } - - @Test(expected = IllegalStateException.class) - public void add_componentIsAttachedToAnotherUI_throwsIllegalStateException() { - // given - TestComponent child = new TestComponent(); - UI ui1 = new UI(); - ui1.add(child); - UI ui2 = new UI(); - - // then - ui2.add(child); - } - - @Test - public void getTranslation_delegateToDeprecated() { - Component component = Mockito.mock(Component.class); - Mockito.doCallRealMethod().when(component).getTranslation( - Mockito.any(Locale.class), Mockito.anyString(), Mockito.any()); - - component.getTranslation(Locale.GERMAN, "foo"); - - Mockito.verify(component).getTranslation("foo", Locale.GERMAN); - } - - @Test - public void findAncestorTest() { - UI ui = new UI(); - TestComponentContainer componentContainer = new TestComponentContainer(); - TestComponent component = new TestComponent(); - componentContainer.add(component); - ui.add(componentContainer); - - Assert.assertEquals(componentContainer, - component.findAncestor(TestComponentContainer.class)); - Assert.assertEquals(ui, component.findAncestor(UI.class)); - Assert.assertEquals(ui, component.findAncestor(PollNotifier.class)); - Assert.assertNull(component.findAncestor(TestButton.class)); - - } - - private void enabledStateChangeOnAttachCalledForParentState( - boolean initiallyEnabled, - BiConsumer modificationStartegy) { - UI ui = new UI(); - - EnabledDiv parent = new EnabledDiv(); - parent.setEnabled(initiallyEnabled); - ui.add(parent); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - Assert.assertTrue("Expected empty state for enabled change", - stateChange.compareAndSet(null, enabled)); - } - }; - - Assert.assertEquals("Parent should be disabled", initiallyEnabled, - parent.isEnabled()); - Assert.assertTrue("Child should be enabled.", child.isEnabled()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - - modificationStartegy.accept(parent, child); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - } - - private void enabledStateChangeOnParentDetachReturnsOldState( - BiConsumer modificationStartegy) { - UI ui = new UI(); - - EnabledDiv grandParent = new EnabledDiv(); - grandParent.setEnabled(false); - ui.add(grandParent); - - EnabledDiv parent = new EnabledDiv(); - - AtomicReference stateChange = new AtomicReference<>(); - EnabledDiv child = new EnabledDiv() { - @Override - public void onEnabledStateChanged(boolean enabled) { - super.onEnabledStateChanged(enabled); - - stateChange.set(enabled); - } - }; - - Assert.assertTrue("Parent should be enabled", parent.isEnabled()); - Assert.assertTrue("Child should be enabled.", child.isEnabled()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - - modificationStartegy.accept(parent, child); - - grandParent.add(parent); - - Assert.assertFalse("After attach child should be disabled", - child.isEnabled()); - Assert.assertFalse("Disabled event should have triggered", - stateChange.get()); - Assert.assertNotNull(child.getElement().getAttribute("disabled")); - - grandParent.remove(parent); - - Assert.assertTrue("After detach child should be enabled", - child.isEnabled()); - Assert.assertTrue("Enable event should have triggered", - stateChange.get()); - Assert.assertNull(child.getElement().getAttribute("disabled")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ComponentUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ComponentUtilTest.java deleted file mode 100644 index 2e4d5aa6771..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ComponentUtilTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Collection; - -import com.vaadin.flow.shared.Registration; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.ComponentTest.TestDiv; - -public class ComponentUtilTest { - private Component component = new TestDiv(); - - @Test - public void setData_byString() { - Assert.assertNull("There should initially not be any value", - ComponentUtil.getData(component, "name")); - - ComponentUtil.setData(component, "name", "value"); - Assert.assertEquals("The stored value should be returned", "value", - ComponentUtil.getData(component, "name")); - - ComponentUtil.setData(component, "name", "value2"); - Assert.assertEquals("The replaced value should be returned", "value2", - ComponentUtil.getData(component, "name")); - - ComponentUtil.setData(component, "name", null); - Assert.assertNull("The value should be removed", - ComponentUtil.getData(component, "name")); - Assert.assertNull( - "Storage should be cleared after removing the last attribute", - component.attributes); - } - - @Test - public void setData_byClass() { - Integer instance1 = new Integer(1); - Integer instance2 = new Integer(2); - - Assert.assertNull("There should initially not be any value", - ComponentUtil.getData(component, Integer.class)); - - ComponentUtil.setData(component, Integer.class, instance1); - Assert.assertSame("The stored value should be returned", instance1, - ComponentUtil.getData(component, Integer.class)); - - Assert.assertNull( - "Attribute should not be available based on super type", - ComponentUtil.getData(component, Number.class)); - - ComponentUtil.setData(component, Integer.class, instance2); - Assert.assertSame("The replaced value should be returned", instance2, - ComponentUtil.getData(component, Integer.class)); - - ComponentUtil.setData(component, Integer.class, null); - Assert.assertNull("The value should be removed", - ComponentUtil.getData(component, Integer.class)); - Assert.assertNull( - "Storage should be cleared after removing the last attribute", - component.attributes); - } - - @Test - public void addListenerToComponent_hasListener_returnsTrue() { - Assert.assertFalse( - ComponentUtil.hasEventListener(component, PollEvent.class)); - - Registration listener = ComponentUtil.addListener(component, - PollEvent.class, event -> { - }); - Assert.assertTrue( - ComponentUtil.hasEventListener(component, PollEvent.class)); - - listener.remove(); - Assert.assertFalse( - ComponentUtil.hasEventListener(component, PollEvent.class)); - } - - @Test - public void addListenerToComponent_getListeners_returnsCollection() { - Assert.assertFalse( - ComponentUtil.hasEventListener(component, PollEvent.class)); - - Registration listener = ComponentUtil.addListener(component, - PollEvent.class, event -> { - }); - Collection listeners = ComponentUtil.getListeners(component, - PollEvent.class); - Assert.assertEquals(1, listeners.size()); - - listener.remove(); - Assert.assertTrue(ComponentUtil.getListeners(component, PollEvent.class) - .isEmpty()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/CompositeNestedTest.java b/flow-server/src/test/java/com/vaadin/flow/component/CompositeNestedTest.java deleted file mode 100644 index 3b62cf49994..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/CompositeNestedTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.ComponentTest.TestComponent; -import com.vaadin.flow.component.ComponentTest.TracksAttachDetach; -import com.vaadin.flow.dom.ElementFactory; - -public class CompositeNestedTest { - TestLayout layout; - TestComponent componentInComposite; - Composite compositeOuter; - Composite compositeInner; - - public static class TestComposite extends Composite - implements TracksAttachDetach { - - private Component content; - - private AtomicInteger attachEvents = new AtomicInteger(); - private AtomicInteger detachEvents = new AtomicInteger(); - - public TestComposite(Component content) { - this.content = content; - } - - @Override - protected Component initContent() { - return content; - } - - @Override - public AtomicInteger getAttachEvents() { - return attachEvents; - } - - @Override - public AtomicInteger getDetachEvents() { - return detachEvents; - } - - } - - public static class TestLayout extends TestComponent { - - public TestLayout() { - super(ElementFactory.createDiv()); - } - - public void addComponent(Component... components) { - for (Component component : components) { - getElement().appendChild(component.getElement()); - } - } - - } - - @Before - public void setup() { - layout = new TestLayout(); - componentInComposite = new TestComponent( - ElementFactory.createDiv("Inside composite")); - compositeInner = new TestComposite(componentInComposite) { - @Override - public String toString() { - return "compositeInner"; - } - }; - compositeOuter = new TestComposite(compositeInner) { - @Override - public String toString() { - return "compositeOuter"; - } - }; - layout.addComponent(compositeOuter); - } - - @Test - public void compositeOuterElement() { - Assert.assertEquals(componentInComposite.getElement(), - compositeOuter.getElement()); - } - - @Test - public void compositeInnerElement() { - Assert.assertEquals(componentInComposite.getElement(), - compositeInner.getElement()); - } - - @Test - public void getParentElement_compositeOuter() { - Assert.assertEquals(layout.getElement(), - compositeOuter.getElement().getParent()); - } - - @Test - public void getParentElement_compositeInner() { - Assert.assertEquals(layout.getElement(), - compositeInner.getElement().getParent()); - } - - @Test - public void layoutChildElements() { - CompositeTest.assertElementChildren(layout.getElement(), - componentInComposite.getElement()); - } - - @Test - public void getParent_compositeOuter() { - Assert.assertEquals(layout, compositeOuter.getParent().get()); - } - - @Test - public void getParent_compositeInner() { - Assert.assertEquals(compositeOuter, compositeInner.getParent().get()); - } - - @Test - public void getParent_componentInComposite() { - Assert.assertEquals(compositeInner, - componentInComposite.getParent().get()); - } - - @Test - public void getChildren_layout() { - ComponentTest.assertChildren(layout, compositeOuter); - } - - @Test - public void getChildren_compositeOuter() { - ComponentTest.assertChildren(compositeOuter, compositeInner); - } - - @Test - public void getChildren_compositeInner() { - ComponentTest.assertChildren(compositeInner, componentInComposite); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/CompositeTest.java b/flow-server/src/test/java/com/vaadin/flow/component/CompositeTest.java deleted file mode 100644 index 8964e382cbb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/CompositeTest.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import net.jcip.annotations.NotThreadSafe; - -import com.vaadin.flow.component.ComponentTest.TestComponent; -import com.vaadin.flow.component.ComponentTest.TracksAttachDetach; -import com.vaadin.flow.component.CompositeNestedTest.TestLayout; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.tests.util.TestUtil; - -import static org.junit.Assert.assertEquals; - -@NotThreadSafe -public class CompositeTest { - - // layoutWithSingleComponentComposite (TestLayout) - // - compositeWithComponent (CompositeWithComponent) - // --- layoutInsideComposite (TestLayout) content for compositeWithComponent - // ---- componentInsideLayoutInsideComposite (TestComponent) - - TestLayout layoutWithSingleComponentComposite; - CompositeWithComponent compositeWithComponent; - TestLayout layoutInsideComposite; - Component componentInsideLayoutInsideComposite; - - protected Component createTestComponent() { - return new TestComponent( - ElementFactory.createDiv("Component in composite")); - - } - - protected TestLayout createTestLayout() { - return new TestLayout() { - @Override - public String toString() { - return "layoutInsideComposite"; - } - }; - } - - public class CompositeWithComponent extends Composite - implements TracksAttachDetach { - - private AtomicInteger attachEvents = new AtomicInteger(); - private AtomicInteger detachEvents = new AtomicInteger(); - - @Override - protected Component initContent() { - layoutInsideComposite = createTestLayout(); - componentInsideLayoutInsideComposite = createTestComponent(); - layoutInsideComposite - .addComponent(componentInsideLayoutInsideComposite); - return layoutInsideComposite; - } - - @Override - public AtomicInteger getAttachEvents() { - return attachEvents; - } - - @Override - public AtomicInteger getDetachEvents() { - return detachEvents; - } - - } - - @Before - public void setup() { - compositeWithComponent = new CompositeWithComponent() { - @Override - public String toString() { - return "Composite"; - } - }; - - layoutWithSingleComponentComposite = new TestLayout() { - @Override - public String toString() { - return "Layout"; - } - }; - layoutWithSingleComponentComposite.addComponent(compositeWithComponent); - - ((TracksAttachDetach) componentInsideLayoutInsideComposite).track(); - compositeWithComponent.track(); - layoutInsideComposite.track(); - layoutWithSingleComponentComposite.track(); - - Assert.assertNull(VaadinService.getCurrent()); - VaadinService service = Mockito.mock(VaadinService.class); - DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(configuration.isProductionMode()).thenReturn(true); - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - VaadinService.setCurrent(service); - } - - @After - public void tearDown() { - VaadinService.setCurrent(null); - } - - @Test - public void getElement_compositeAndCompositeComponent() { - assertEquals(layoutInsideComposite.getElement(), - compositeWithComponent.getElement()); - } - - @Test - public void getParentElement_compositeInLayout() { - assertEquals(layoutWithSingleComponentComposite.getElement(), - compositeWithComponent.getElement().getParent()); - } - - @Test - public void getElementChildren_layoutWithComponentInComposite() { - assertElementChildren(layoutWithSingleComponentComposite.getElement(), - layoutInsideComposite.getElement()); - } - - @Test - public void getParent_compositeInLayout() { - assertEquals(layoutWithSingleComponentComposite, - compositeWithComponent.getParent().get()); - } - - @Test - public void getParent_componentInComposite() { - assertEquals(compositeWithComponent, - layoutInsideComposite.getParent().get()); - } - - @Test - public void getParent_componentInLayoutInComposite() { - assertEquals(layoutInsideComposite, - componentInsideLayoutInsideComposite.getParent().get()); - } - - @Test - public void getChildren_layoutWithComposite() { - ComponentTest.assertChildren(layoutWithSingleComponentComposite, - compositeWithComponent); - } - - @Test - public void getChildren_compositeWithComponent() { - ComponentTest.assertChildren(compositeWithComponent, - layoutInsideComposite); - } - - @Test - public void getChildren_layoutInComposite() { - ComponentTest.assertChildren(layoutInsideComposite, - componentInsideLayoutInsideComposite); - } - - @Test - public void automaticCompositeContentType() { - class CompositeWithGenericType extends Composite { - } - - CompositeWithGenericType instance = new CompositeWithGenericType(); - - assertEquals(TestComponent.class, instance.getContent().getClass()); - } - - @Test(expected = IllegalStateException.class) - public void compositeContentTypeWithVariableTypeParameter() { - class CompositeWithVariableType - extends Composite { - } - - CompositeWithVariableType composite = new CompositeWithVariableType<>(); - composite.getContent(); - } - - public static class CustomComponent extends UI { - } - - @Test - public void compositeContentTypeWithSpecifiedType() { - class CompositeWithCustomComponent - extends Composite>> { - } - - CompositeWithCustomComponent composite = new CompositeWithCustomComponent(); - - assertEquals(CustomComponent.class, composite.getContent().getClass()); - } - - public static class CompositeWithVariableType - extends Composite { - } - - @Test(expected = IllegalStateException.class) - public void compositeContentTypeWithTypeVariable() { - class CompositeWithComposite - extends Composite> { - } - - CompositeWithComposite composite = new CompositeWithComposite(); - composite.getContent(); - } - - @Test(expected = IllegalStateException.class) - public void rawContentType() { - @SuppressWarnings("rawtypes") - class CompositeWithRawType extends Composite { - } - - CompositeWithRawType composite = new CompositeWithRawType(); - composite.getContent(); - } - - @Test(expected = IllegalArgumentException.class) - public void noDefaultConstructor() { - class NoDefaultConstructor extends Composite { - } - - NoDefaultConstructor composite = new NoDefaultConstructor(); - composite.getContent(); - } - - @Test - public void compositeHierarchy() { - class Class1 extends Composite { - } - class Class2 extends Class1 { - } - class Class3 extends Class2 { - } - class Class4 extends Class3 { - } - class ComplexClass extends Class4 { - } - - ComplexClass composite = new ComplexClass(); - - assertEquals(UI.class, composite.getContent().getClass()); - } - - // layoutWithSingleComponentComposite (TestLayout) - // - compositeWithComponent (CompositeWithComponent) - // --- layoutInsideComposite (TestLayout) content for compositeWithComponent - // ---- componentInsideLayoutInsideComposite (TestComponent) - @Test - public void attachDetachEvents_compositeHierarchy_correctOrder() { - UI ui = new UI(); - - List attached = new ArrayList<>(); - List detached = new ArrayList<>(); - - ComponentEventListener attachListener = event -> attached - .add(event.getSource()); - ComponentEventListener detachListener = event -> detached - .add(event.getSource()); - - layoutInsideComposite.addAttachListener(attachListener); - layoutWithSingleComponentComposite.addAttachListener(attachListener); - compositeWithComponent.addAttachListener(attachListener); - componentInsideLayoutInsideComposite.addAttachListener(attachListener); - - layoutInsideComposite.addDetachListener(detachListener); - layoutWithSingleComponentComposite.addDetachListener(detachListener); - compositeWithComponent.addDetachListener(detachListener); - componentInsideLayoutInsideComposite.addDetachListener(detachListener); - - layoutInsideComposite.assertAttachEvents(0); - layoutWithSingleComponentComposite.assertAttachEvents(0); - compositeWithComponent.assertAttachEvents(0); - ((TracksAttachDetach) componentInsideLayoutInsideComposite) - .assertAttachEvents(0); - - ui.add(layoutWithSingleComponentComposite); - - layoutInsideComposite.assertAttachEvents(1); - layoutWithSingleComponentComposite.assertAttachEvents(1); - compositeWithComponent.assertAttachEvents(1); - ((TracksAttachDetach) componentInsideLayoutInsideComposite) - .assertAttachEvents(1); - - TestUtil.assertArrays(attached.toArray(), - new Component[] { componentInsideLayoutInsideComposite, - layoutInsideComposite, compositeWithComponent, - layoutWithSingleComponentComposite }); - - layoutInsideComposite.assertDetachEvents(0); - layoutWithSingleComponentComposite.assertDetachEvents(0); - compositeWithComponent.assertDetachEvents(0); - ((TracksAttachDetach) componentInsideLayoutInsideComposite) - .assertDetachEvents(0); - - ui.removeAll(); - - layoutInsideComposite.assertDetachEvents(1); - layoutWithSingleComponentComposite.assertDetachEvents(1); - compositeWithComponent.assertDetachEvents(1); - ((TracksAttachDetach) componentInsideLayoutInsideComposite) - .assertDetachEvents(1); - - TestUtil.assertArrays(detached.toArray(), - new Component[] { componentInsideLayoutInsideComposite, - layoutInsideComposite, compositeWithComponent, - layoutWithSingleComponentComposite }); - } - - @Test - public void testOnAttachOnDetachAndEventsOrder() { - List triggered = new ArrayList<>(); - - Component component = new Component(new Element("div")) { - @Override - protected void onAttach(AttachEvent attachEvent) { - triggered.add(1); - } - - @Override - protected void onDetach(DetachEvent detachEvent) { - triggered.add(-1); - } - }; - component.addAttachListener(event -> triggered.add(2)); - component.addDetachListener(event -> triggered.add(-2)); - - Composite compositeInsideComposite = new Composite() { - @Override - protected Component initContent() { - return component; - }; - - @Override - protected void onAttach(AttachEvent attachEvent) { - triggered.add(3); - } - - @Override - protected void onDetach(DetachEvent detachEvent) { - triggered.add(-3); - } - }; - compositeInsideComposite.addAttachListener(event -> triggered.add(4)); - compositeInsideComposite.addDetachListener(event -> triggered.add(-4)); - - Composite composite = new Composite() { - @Override - protected Component initContent() { - return compositeInsideComposite; - } - - @Override - protected void onAttach(AttachEvent attachEvent) { - triggered.add(5); - } - - @Override - protected void onDetach(DetachEvent detachEvent) { - triggered.add(-5); - } - }; - composite.addAttachListener(event -> triggered.add(6)); - composite.addDetachListener(event -> triggered.add(-6)); - - UI ui = new UI(); - ui.add(composite); - - TestUtil.assertArrays(triggered.toArray(), - new Integer[] { 1, 2, 3, 4, 5, 6 }); - triggered.clear(); - - ui.remove(composite); - - TestUtil.assertArrays(triggered.toArray(), - new Integer[] { -1, -2, -3, -4, -5, -6 }); - - TestLayout container = createTestLayout(); - ui.add(container, composite); - - triggered.clear(); - - container.addComponent(composite); - - TestUtil.assertArrays(triggered.toArray(), - new Integer[] { -1, -2, -3, -4, -5, -6, 1, 2, 3, 4, 5, 6 }); - } - - public static void assertElementChildren(Element parent, - Element... expected) { - assertEquals(expected.length, parent.getChildCount()); - for (int i = 0; i < parent.getChildCount(); i++) { - assertEquals(expected[i], parent.getChild(i)); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/CompositeTextNodeTest.java b/flow-server/src/test/java/com/vaadin/flow/component/CompositeTextNodeTest.java deleted file mode 100644 index 8b6054a8bc8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/CompositeTextNodeTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.util.concurrent.atomic.AtomicInteger; - -import com.vaadin.flow.component.ComponentTest.TracksAttachDetach; - -public class CompositeTextNodeTest extends CompositeTest { - - static class TracksAttachDetachText extends Text - implements TracksAttachDetach { - - public TracksAttachDetachText(String text) { - super(text); - } - - private AtomicInteger attachEvents = new AtomicInteger(); - private AtomicInteger detachEvents = new AtomicInteger(); - - @Override - public AtomicInteger getAttachEvents() { - return attachEvents; - } - - @Override - public AtomicInteger getDetachEvents() { - return detachEvents; - } - - } - - @Override - protected Component createTestComponent() { - return new TracksAttachDetachText("Test component"); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/DefaultWebComponentExporterFactoryTest.java b/flow-server/src/test/java/com/vaadin/flow/component/DefaultWebComponentExporterFactoryTest.java deleted file mode 100644 index 0418b56f125..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/DefaultWebComponentExporterFactoryTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.vaadin.flow.component.WebComponentExporterFactory.DefaultWebComponentExporterFactory; -import com.vaadin.flow.component.webcomponent.WebComponent; - -public class DefaultWebComponentExporterFactoryTest { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private class InnerClass extends WebComponentExporter { - - protected InnerClass() { - super("a-b"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - } - - } - - public static class NoSpecifiedTagClass - extends WebComponentExporter { - - public NoSpecifiedTagClass() { - super(null); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - } - - } - - @Test(expected = NullPointerException.class) - public void ctor_nullArg_throws() { - new DefaultWebComponentExporterFactory(null); - } - - @Test - public void createInnerClass_throws() { - exception.expect(RuntimeException.class); - exception.expectCause( - CoreMatchers.instanceOf(IllegalArgumentException.class)); - exception.expectMessage( - CoreMatchers.containsString(InnerClass.class.getName())); - exception.expectMessage(CoreMatchers.containsString("inner")); - DefaultWebComponentExporterFactory factory = new DefaultWebComponentExporterFactory<>( - InnerClass.class); - - factory.create(); - } - - @Test - public void create_exporterHasNoTag_throws() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(CoreMatchers - .containsString(NoSpecifiedTagClass.class.getCanonicalName())); - exception.expectMessage(CoreMatchers - .containsString("give null value to super(String)")); - DefaultWebComponentExporterFactory factory = new DefaultWebComponentExporterFactory<>( - NoSpecifiedTagClass.class); - factory.create(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/DomEventTest.java b/flow-server/src/test/java/com/vaadin/flow/component/DomEventTest.java deleted file mode 100644 index 4dc55ca8d12..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/DomEventTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.dom.DebouncePhase; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.internal.ConstantPoolKey; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.NodeChange; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; -import elemental.json.JsonType; - -public class DomEventTest { - @DomEvent("event") - public static class BareAnnotation extends ComponentEvent { - public BareAnnotation(Component source, boolean fromClient) { - super(source, fromClient); - } - } - - @Test - public void bareAnnotation() { - assertSettings(BareAnnotation.class, null, 0); - } - - @DomEvent(value = "event", filter = "a == b") - public static class FilterEvent extends ComponentEvent { - public FilterEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - } - - @Test - public void filter() { - assertSettings(FilterEvent.class, "a == b", 0); - } - - @DomEvent(value = "event", debounce = @DebounceSettings(timeout = 200, phases = { - DebouncePhase.INTERMEDIATE, DebouncePhase.TRAILING })) - public static class DebounceTimeoutPhasesEvent - extends ComponentEvent { - public DebounceTimeoutPhasesEvent(Component source, - boolean fromClient) { - super(source, fromClient); - } - } - - @Test - public void debouncePhases() { - assertSettings(DebounceTimeoutPhasesEvent.class, - ElementListenerMap.ALWAYS_TRUE_FILTER, 200, - DebouncePhase.INTERMEDIATE, DebouncePhase.TRAILING); - } - - @DomEvent(value = "event", debounce = @DebounceSettings(timeout = 200, phases = {})) - public static class DebounceEmptyPhasesEvent - extends ComponentEvent { - public DebounceEmptyPhasesEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - } - - @Test(expected = IllegalStateException.class) - public void emptyPhases() { - getEventSettings(DebounceEmptyPhasesEvent.class); - } - - @DomEvent(value = "event", filter = "filter(event)", debounce = @DebounceSettings(timeout = 300, phases = DebouncePhase.TRAILING)) - public static class DebounceFilterEvent extends ComponentEvent { - public DebounceFilterEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - } - - @Test - public void debounceFilter() { - assertSettings(DebounceFilterEvent.class, "filter(event)", 300, - DebouncePhase.TRAILING); - } - - private > void assertSettings( - Class eventType, String expectedFilter, int expectedTimeout, - DebouncePhase... expectedPhases) { - JsonObject settings = getEventSettings(eventType); - - if (expectedFilter == null) { - Assert.assertArrayEquals(new String[0], settings.keys()); - return; - } - - Assert.assertArrayEquals(new String[] { expectedFilter }, - settings.keys()); - - if (expectedTimeout == 0 && expectedPhases.length == 0) { - Assert.assertEquals( - "There should be a boolean instead of empty phase list", - JsonType.BOOLEAN, settings.get(expectedFilter).getType()); - boolean isFilter = settings.getBoolean(expectedFilter); - Assert.assertTrue("Expression should be used as a filter", - isFilter); - return; - } - - JsonArray filterSettings = settings.getArray(expectedFilter); - - Assert.assertEquals(1, filterSettings.length()); - - JsonArray filterSetting = filterSettings.getArray(0); - - Assert.assertEquals("Debunce timeout should be as expected", - expectedTimeout, (int) filterSetting.getNumber(0)); - - Assert.assertEquals("Number of phases should be as expected", - expectedPhases.length, filterSetting.length() - 1); - - for (int i = 0; i < expectedPhases.length; i++) { - String expectedIdentifier = expectedPhases[i].getIdentifier(); - Assert.assertEquals(expectedIdentifier, - filterSetting.getString(i + 1)); - } - } - - private void assertFilter(String expectedFilter, - JsonObject filterSettings) { - } - - private > JsonObject getEventSettings( - Class eventType) { - Component component = new Component(new Element("element")) { - }; - component.addListener(eventType, e -> { - }); - - ElementListenerMap elementListenerMap = component.getElement().getNode() - .getFeature(ElementListenerMap.class); - - List changes = new ArrayList<>(); - elementListenerMap.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - MapPutChange change = (MapPutChange) changes.get(0); - Assert.assertEquals("event", change.getKey()); - - ConstantPoolKey value = (ConstantPoolKey) change.getValue(); - JsonObject constantPoolUpdate = Json.createObject(); - value.export(constantPoolUpdate); - - String[] keys = constantPoolUpdate.keys(); - Assert.assertEquals(1, keys.length); - JsonObject eventSettings = constantPoolUpdate.getObject(keys[0]); - - return eventSettings; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/FocusableTest.java b/flow-server/src/test/java/com/vaadin/flow/component/FocusableTest.java deleted file mode 100644 index 04d70479a3f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/FocusableTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.internal.PendingJavaScriptInvocation; -import com.vaadin.tests.util.MockUI; - -public class FocusableTest { - @Tag("div") - private static class FocusableTestComponent extends Component - implements Focusable { - - } - - private final MockUI ui = new MockUI(); - private final FocusableTestComponent component = new FocusableTestComponent(); - - @Test - public void focusUnattached_nothingScheduled() { - component.focus(); - - assertPendingInvocationCount( - "Nothing should be scheduled when component is not attached", - 0); - } - - @Test - public void focusBeforeAttach_executionScheduled() { - component.focus(); - ui.add(component); - - assertPendingInvocationCount( - "An focus() inovocation should be pending for the attached component", - 1); - } - - @Test - public void focusAfterAttach_executionScheduled() { - ui.add(component); - component.focus(); - - assertPendingInvocationCount( - "An focus() inovocation should be pending for the attached component", - 1); - } - - @Test - public void detachAfterFocus_nothingScheduled() { - ui.add(component); - component.focus(); - ui.remove(component); - - assertPendingInvocationCount( - "Nothing should be scheduled when component is not attached", - 0); - } - - private void assertPendingInvocationCount(String message, int expected) { - List invocations = ui - .dumpPendingJsInvocations(); - Assert.assertEquals(message, expected, invocations.size()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HTMLTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HTMLTest.java deleted file mode 100644 index 8e8affbed68..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HTMLTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.dom.Element; - -public class HTMLTest { - - @Test - public void attachedToElement() { - // This will throw an assertion error if the element is not attached to - // the component - new Html("Hello").getParent(); - } - - @Test(expected = IllegalArgumentException.class) - public void nullHtml() { - new Html((String) null); - } - - @Test(expected = IllegalArgumentException.class) - public void nullStream() { - new Html((InputStream) null); - } - - @Test(expected = IllegalArgumentException.class) - public void emptyHtml() { - new Html(""); - } - - @Test(expected = IllegalArgumentException.class) - public void twoRoots() { - new Html("
"); - } - - @Test(expected = IllegalArgumentException.class) - public void text() { - new Html("hello"); - } - - @Test - public void simpleHtml() { - Html html = new Html("hello"); - Assert.assertEquals(Tag.SPAN, html.getElement().getTag()); - Assert.assertEquals("hello", html.getInnerHtml()); - } - - @Test - public void setHtmlContent() { - Html html = new Html("hello"); - Assert.assertEquals(Tag.SPAN, html.getElement().getTag()); - Assert.assertEquals("hello", html.getInnerHtml()); - html.setHtmlContent("world"); - Assert.assertEquals("world", html.getInnerHtml()); - } - - @Test(expected = IllegalStateException.class) - public void setHtmlContent_tagMismatch() { - Html html = new Html("hello"); - Assert.assertEquals(Tag.SPAN, html.getElement().getTag()); - Assert.assertEquals("hello", html.getInnerHtml()); - html.setHtmlContent("
world
"); - Assert.assertEquals("world", html.getInnerHtml()); - } - - @Test - public void rootAttributes() { - Html html = new Html("hello"); - Assert.assertEquals(Tag.SPAN, html.getElement().getTag()); - Assert.assertEquals(1, html.getElement().getAttributeNames().count()); - Assert.assertEquals("bar", html.getElement().getAttribute("foo")); - Assert.assertEquals("hello", html.getInnerHtml()); - } - - @Test - public void rootSpecialAttributes() { - Html html = new Html( - "hello"); - Element element = html.getElement(); - Assert.assertEquals(Tag.SPAN, element.getTag()); - - Assert.assertEquals(2, element.getAttributeNames().count()); - Assert.assertEquals("foo", element.getAttribute("class")); - Assert.assertEquals("color:red", element.getAttribute("style")); - Assert.assertEquals("hello", html.getInnerHtml()); - } - - @Test - public void fromStream() { - new Html(new ByteArrayInputStream( - "
contents
".getBytes())); - } - - @Test - public void brokenHtml() { - Html html = new Html(""); - Assert.assertEquals("b", html.getElement().getTag()); - Assert.assertEquals("", html.getInnerHtml()); - } - - @Test - public void extraWhitespace() { - String input = " " // - + "
" // - + " Hello!" // - + "
" // - + "
" + " " // - + "" // - + ""; - Html html = new Html(input); - Assert.assertEquals(Tag.SPAN, html.getElement().getTag()); - String expectedInnerHtml = input.replaceAll("^[ ]*", "") - .replaceAll("[ ]*$", ""); - Assert.assertEquals(expectedInnerHtml, html.getInnerHtml()); - } - - @Test - public void emptyAttribute_elementIsCreatedAndHasAttribute() { - Html html = new Html(""); - - Assert.assertEquals("", html.getElement().getAttribute("controls")); - - Assert.assertEquals("", - html.getElement().getOuterHTML()); - } - - @Test - public void styleElementAsString_elementIsUsed() { - Html html = new Html(""); - Assert.assertEquals("style", html.getElement().getTag()); - } - - @Test - - public void styleElementAsStream_elementIsUsed() { - Html html = new Html(new ByteArrayInputStream( - "".getBytes(StandardCharsets.UTF_8))); - Assert.assertEquals("style", html.getElement().getTag()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasAriaLabelTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasAriaLabelTest.java deleted file mode 100644 index a2c8b4f190e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasAriaLabelTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import org.junit.Test; - -public class HasAriaLabelTest { - - @Tag(Tag.MAIN) // main is used, because div is not a valid target by default - private static class TestComponent extends Component - implements HasAriaLabel { - - } - - @Test - public void withoutAriaLabelComponent_getAriaLabelReturnsEmptyOptional() { - TestComponent component = new TestComponent(); - - assertFalse(component.getAriaLabel().isPresent()); - } - - @Test - public void withNullAriaLabel_getAriaLabelReturnsEmptyOptional() { - TestComponent component = new TestComponent(); - component.setAriaLabel(null); - assertFalse(component.getAriaLabel().isPresent()); - } - - @Test - public void withEmptyAriaLabel_getAriaLabelReturnsEmptyString() { - TestComponent component = new TestComponent(); - component.setAriaLabel(""); - assertEquals("", component.getAriaLabel().get()); - } - - @Test - public void withAriaLabel_setAriaLabelToNullClearsAriaLabel() { - TestComponent component = new TestComponent(); - component.setAriaLabel("test AriaLabel"); - - component.setAriaLabel(null); - assertFalse(component.getAriaLabel().isPresent()); - } - - @Test - public void setAriaLabel() { - TestComponent component = new TestComponent(); - component.setAriaLabel("test AriaLabel"); - - assertEquals("test AriaLabel", component.getAriaLabel().get()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasComponentsTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasComponentsTest.java deleted file mode 100644 index 06712a4f4f2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasComponentsTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Test; - -public class HasComponentsTest { - - @Tag("div") - private static class TestComponent extends Component - implements HasComponents { - - } - - @Test - public void addStringToComponent() { - String text = "Add text"; - TestComponent component = new TestComponent(); - component.add(text); - - Assert.assertEquals(text, component.getElement().getText()); - } - - @Test - public void insertComponentAtFirst() { - TestComponent component = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - innerComponent.setId("insert-component-first"); - component.addComponentAsFirst(innerComponent); - checkChildren(4, component); - Assert.assertEquals(innerComponent.getId(), - component.getChildren().findFirst().get().getId()); - } - - @Test - public void insertComponentAtIndex() { - TestComponent component = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - innerComponent.setId("insert-component-index"); - component.addComponentAtIndex(2, innerComponent); - checkChildren(4, component); - Assert.assertEquals(innerComponent.getId(), component.getElement() - .getChild(2).getComponent().get().getId()); - } - - @Test(expected = IllegalArgumentException.class) - public void insertComponentIndexLessThanZero() { - TestComponent component = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - innerComponent.setId("insert-component-index-less"); - component.addComponentAtIndex(-5, innerComponent); - } - - @Test(expected = IllegalArgumentException.class) - public void insertComponentIndexGreaterThanChildrenNumber() { - TestComponent component = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - innerComponent.setId("insert-component-index-greater"); - component.addComponentAtIndex(100, innerComponent); - } - - @Test - public void remove_removeComponentWithNoParent() { - TestComponent component = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - - // No any exception is thrown - component.remove(innerComponent); - } - - @Test - public void remove_removeSeveralComponents_oneHasParent_nothingRemovedAndThrows() { - TestComponent component = createTestStructure(); - - TestComponent child = new TestComponent(); - component.add(child); - - TestComponent another = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - another.add(innerComponent); - - try { - component.remove(child, innerComponent); - Assert.fail(); - } catch (IllegalArgumentException exception) { - Assert.assertEquals(component, child.getParent().get()); - } - } - - @Test - public void remove_removeSeveralComponents_oneHasNoParent_childIsRemoved() { - TestComponent component = createTestStructure(); - - TestComponent child = new TestComponent(); - component.add(child); - - TestComponent notAChild = new TestComponent(); - - component.remove(notAChild, child); - Assert.assertFalse(child.getParent().isPresent()); - Assert.assertFalse(component.getChildren() - .filter(comp -> comp.equals(child)).findAny().isPresent()); - } - - @Test - public void remove_removeComponentWithCorrectParent() { - TestComponent component = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - - long size = component.getChildren().count(); - - component.add(innerComponent); - - component.remove(innerComponent); - - Assert.assertEquals(size, component.getChildren().count()); - } - - @Test(expected = IllegalArgumentException.class) - public void remove_removeComponentWithDifferentParent() { - TestComponent component = createTestStructure(); - - TestComponent another = createTestStructure(); - TestComponent innerComponent = new TestComponent(); - - another.add(innerComponent); - - component.remove(innerComponent); - } - - private TestComponent createTestStructure() { - TestComponent component = new TestComponent(); - checkChildren(0, component); - component.add(new TestComponent(), new TestComponent(), - new TestComponent()); - checkChildren(3, component); - return component; - } - - private void checkChildren(int number, TestComponent component) { - Assert.assertEquals(number, component.getChildren().count()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasEnabledTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasEnabledTest.java deleted file mode 100644 index d0638ddca29..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasEnabledTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Test; - -public class HasEnabledTest { - - @Tag(Tag.DIV) - private static class TestComponent extends Component - implements HasComponents { - - } - - @Test - public void enabledComponent_isEnabledReturnsTrue() { - TestComponent component = new TestComponent(); - - Assert.assertTrue(component.isEnabled()); - } - - @Test - public void explicitlyDisabledComponent_isEnabledReturnsFalse() { - TestComponent component = new TestComponent(); - component.setEnabled(false); - - Assert.assertFalse(component.isEnabled()); - } - - @Test - public void implicitlyDisabledComponent_isEnabledReturnsFalse() { - TestComponent component = new TestComponent(); - - TestComponent parent = new TestComponent(); - parent.setEnabled(false); - - parent.add(component); - - Assert.assertFalse(component.isEnabled()); - } - - @Test - public void implicitlyDisabledComponent_detach_componentBecomesEnabled() { - TestComponent component = new TestComponent(); - - TestComponent parent = new TestComponent(); - parent.add(component); - - parent.setEnabled(false); - - parent.remove(component); - - Assert.assertTrue(component.isEnabled()); - } - - @Test - public void explicitlyDisabledComponent_enableParent_componentRemainsDisabled() { - TestComponent component = new TestComponent(); - component.setEnabled(false); - - TestComponent parent = new TestComponent(); - parent.add(component); - - parent.setEnabled(false); - - Assert.assertFalse(component.isEnabled()); - - parent.setEnabled(true); - - Assert.assertFalse(component.isEnabled()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasHelperTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasHelperTest.java deleted file mode 100644 index 62e1c686665..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasHelperTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Test; - -public class HasHelperTest { - - @Tag("div") - public static class HasHelperComponent extends Component - implements HasHelper { - } - - @Test - public void getHelperText() { - final HasHelperComponent c = new HasHelperComponent(); - Assert.assertNull(c.getHelperText()); - } - - @Test - public void getHelperComponent() { - final HasHelperComponent c = new HasHelperComponent(); - Assert.assertNull(c.getHelperComponent()); - } - - @Test - public void setHelperText() { - final HasHelperComponent c = new HasHelperComponent(); - c.setHelperText("helper"); - Assert.assertEquals("helper", c.getHelperText()); - } - - @Test - public void setHelperComponent() { - final HasHelperComponent c = new HasHelperComponent(); - final HasHelperComponent slotted = new HasHelperComponent(); - c.setHelperComponent(slotted); - Assert.assertEquals(slotted, c.getHelperComponent()); - } - - @Test - public void removeHelperText() { - final HasHelperComponent c = new HasHelperComponent(); - c.setHelperText("helper"); - Assert.assertEquals("helper", c.getHelperText()); - - c.setHelperText(null); - Assert.assertNull(c.getHelperText()); - } - - @Test - public void removeHelperComponent() { - final HasHelperComponent c = new HasHelperComponent(); - final HasHelperComponent slotted = new HasHelperComponent(); - - c.setHelperComponent(slotted); - Assert.assertEquals(slotted, c.getHelperComponent()); - - c.setHelperComponent(null); - Assert.assertNull(c.getHelperComponent()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasLabelTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasLabelTest.java deleted file mode 100644 index 03e2b777948..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasLabelTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Test; - -public class HasLabelTest { - - @Tag(Tag.DIV) - private static class TestComponent extends Component implements HasLabel { - - } - - @Test - public void withoutLabelComponent_getLabelReturnsNull() { - TestComponent component = new TestComponent(); - - assertNull(component.getLabel()); - } - - @Test - public void withNullLabel_getLabelReturnsNull() { - TestComponent component = new TestComponent(); - component.setLabel(null); - assertNull(component.getLabel()); - } - - @Test - public void withEmptyLabel_getLabelReturnsEmptyString() { - TestComponent component = new TestComponent(); - component.setLabel(""); - assertEquals("", component.getLabel()); - } - - @Test - public void setLabel() { - TestComponent component = new TestComponent(); - component.setLabel("test label"); - - assertEquals("test label", component.getLabel()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasOrderedComponentsTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasOrderedComponentsTest.java deleted file mode 100644 index a15f93577f2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasOrderedComponentsTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.dom.Element; - -public class HasOrderedComponentsTest { - - static class TestOrderedComponents implements HasOrderedComponents { - - @Override - public Element getElement() { - return null; - } - - @Override - public Stream getChildren() { - return null; - } - - } - - @Tag("div") - static class TestComponentContianer extends Component - implements HasOrderedComponents { - - } - - @Tag(Tag.A) - static class Anchor extends Component { - - } - - private HasOrderedComponents components = Mockito - .spy(TestOrderedComponents.class); - - private TestComponentContianer contianer = new TestComponentContianer(); - - @Test - public void indexOf_componentIsChild_returnsIndexOfChild() { - Component comp = Mockito.mock(Component.class); - Mockito.when(components.getChildren()) - .thenReturn(Arrays.asList(Mockito.mock(Component.class), comp, - Mockito.mock(Component.class)).stream()); - - Assert.assertEquals(1, components.indexOf(comp)); - - contianer = new TestComponentContianer(); - comp = new Anchor(); - contianer.add(new Text(""), comp); - Assert.assertEquals(1, contianer.indexOf(comp)); - } - - @Test - public void indexOf_componentIsNotChild_returnsNegative() { - Component comp = Mockito.mock(Component.class); - Mockito.when(components.getChildren()) - .thenReturn(Arrays.asList(Mockito.mock(Component.class), - Mockito.mock(Component.class)).stream()); - - Assert.assertEquals(-1, components.indexOf(comp)); - } - - @Test(expected = IllegalArgumentException.class) - public void indexOf_componentIsNull_throws() { - Mockito.when(components.getChildren()).thenReturn(Stream.empty()); - - components.indexOf(null); - } - - @Test - public void getComponentCount_returnsChildrenSize() { - Mockito.when(components.getChildren()) - .thenReturn(Arrays.asList(Mockito.mock(Component.class), - Mockito.mock(Component.class)).stream()); - Assert.assertEquals(2, components.getComponentCount()); - - contianer = new TestComponentContianer(); - contianer.add(new Text(""), new Anchor()); - Assert.assertEquals(2, contianer.getComponentCount()); - } - - @Test - public void getComponentAt_returnsComponentAtIndex() { - Component comp = Mockito.mock(Component.class); - Mockito.when(components.getChildren()) - .thenReturn(Arrays.asList(Mockito.mock(Component.class), comp, - Mockito.mock(Component.class)).stream()); - - Assert.assertSame(comp, components.getComponentAt(1)); - - contianer = new TestComponentContianer(); - comp = new Anchor(); - contianer.add(new Text(""), comp); - Assert.assertSame(comp, contianer.getComponentAt(1)); - } - - @Test(expected = IllegalArgumentException.class) - public void getComponentAt_negativeIndex_throws() { - Mockito.when(components.getChildren()) - .thenReturn(Arrays.asList(Mockito.mock(Component.class), - Mockito.mock(Component.class)).stream()); - - components.getComponentAt(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void getComponentAt_indexIsGreaterThanSize_throws() { - Mockito.when(components.getChildren()) - .thenReturn(Stream.of(Mockito.mock(Component.class))); - - components.getComponentAt(2); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasSizeTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasSizeTest.java deleted file mode 100644 index 6fee666a62b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasSizeTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Test; - -public class HasSizeTest { - - @Tag("div") - public static class HasSizeComponent extends Component implements HasSize { - - } - - @Test - public void setWidth() { - HasSizeComponent c = new HasSizeComponent(); - c.setWidth("100px"); - Assert.assertEquals("100px", c.getWidth()); - } - - @Test - public void setMinWidth() { - HasSizeComponent c = new HasSizeComponent(); - c.setMinWidth("100px"); - Assert.assertEquals("100px", c.getMinWidth()); - } - - @Test - public void setMaxWidth() { - HasSizeComponent c = new HasSizeComponent(); - c.setMaxWidth("100px"); - Assert.assertEquals("100px", c.getMaxWidth()); - } - - @Test - public void removeWidth() { - HasSizeComponent c = new HasSizeComponent(); - c.setWidth("100px"); - Assert.assertEquals("100px", c.getWidth()); - - c.setWidth(null); - Assert.assertNull(c.getWidth()); - } - - @Test - public void removeMinWidth() { - HasSizeComponent c = new HasSizeComponent(); - c.setMinWidth("100px"); - Assert.assertEquals("100px", c.getMinWidth()); - - c.setMinWidth(null); - Assert.assertNull(c.getMinWidth()); - } - - @Test - public void removeMaxWidth() { - HasSizeComponent c = new HasSizeComponent(); - c.setMaxWidth("100px"); - Assert.assertEquals("100px", c.getMaxWidth()); - - c.setMaxWidth(null); - Assert.assertNull(c.getMaxWidth()); - } - - @Test - public void setHeight() { - HasSizeComponent c = new HasSizeComponent(); - c.setHeight("100px"); - Assert.assertEquals("100px", c.getHeight()); - } - - @Test - public void setMinHeight() { - HasSizeComponent c = new HasSizeComponent(); - c.setMinHeight("100px"); - Assert.assertEquals("100px", c.getMinHeight()); - } - - @Test - public void setMaxHeight() { - HasSizeComponent c = new HasSizeComponent(); - c.setMaxHeight("100px"); - Assert.assertEquals("100px", c.getMaxHeight()); - } - - @Test - public void removeHeight() { - HasSizeComponent c = new HasSizeComponent(); - c.setHeight("100px"); - Assert.assertEquals("100px", c.getHeight()); - - c.setHeight(null); - Assert.assertNull(c.getHeight()); - } - - @Test - public void removeMinHeight() { - HasSizeComponent c = new HasSizeComponent(); - c.setMinHeight("100px"); - Assert.assertEquals("100px", c.getMinHeight()); - - c.setMinHeight(null); - Assert.assertNull(c.getMinHeight()); - } - - @Test - public void removeMaxHeight() { - HasSizeComponent c = new HasSizeComponent(); - c.setMaxHeight("100px"); - Assert.assertEquals("100px", c.getMaxHeight()); - - c.setMaxHeight(null); - Assert.assertNull(c.getMaxHeight()); - } - - @Test - public void setSizeFull() { - HasSizeComponent component = new HasSizeComponent(); - component.setSizeFull(); - - Assert.assertEquals("100%", component.getWidth()); - Assert.assertEquals("100%", component.getHeight()); - } - - @Test - public void setWidthFull() { - HasSizeComponent component = new HasSizeComponent(); - component.setWidthFull(); - - Assert.assertEquals("100%", component.getWidth()); - } - - @Test - public void setHeightFull() { - HasSizeComponent component = new HasSizeComponent(); - component.setHeightFull(); - - Assert.assertEquals("100%", component.getHeight()); - } - - @Test - public void setSizeUndefined() { - HasSizeComponent component = new HasSizeComponent(); - component.setWidth("10px"); - component.setHeight("5em"); - - component.setSizeUndefined(); - - Assert.assertNull(component.getWidth()); - Assert.assertNull(component.getHeight()); - } - - @Test - public void getWidthUnit() { - HasSizeComponent component = new HasSizeComponent(); - Assert.assertFalse(component.getWidthUnit().isPresent()); - - component.setWidth("10px"); - Assert.assertTrue(component.getWidthUnit().isPresent()); - Assert.assertEquals(Unit.PIXELS, component.getWidthUnit().get()); - - component.setSizeUndefined(); - Assert.assertFalse(component.getWidthUnit().isPresent()); - } - - @Test - public void getHeightUnit() { - HasSizeComponent component = new HasSizeComponent(); - Assert.assertFalse(component.getHeightUnit().isPresent()); - - component.setHeight("10%"); - Assert.assertTrue(component.getHeightUnit().isPresent()); - Assert.assertEquals(Unit.PERCENTAGE, component.getHeightUnit().get()); - - component.setSizeUndefined(); - Assert.assertFalse(component.getHeightUnit().isPresent()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasSizeUnitTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasSizeUnitTest.java deleted file mode 100644 index 9b4605d54f1..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasSizeUnitTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Test; - -public class HasSizeUnitTest { - - @Tag("div") - public static class HasSizeComponent extends Component implements HasSize { - - } - - @Test - public void setWidthFloat() { - HasSizeComponent c = new HasSizeComponent(); - for (Unit unit : Unit.values()) { - c.setWidth(100, unit); - Assert.assertEquals("100.0" + unit.toString(), c.getWidth()); - } - } - - @Test - public void setMinWidthFloat() { - HasSizeComponent c = new HasSizeComponent(); - for (Unit unit : Unit.values()) { - c.setMinWidth(100, unit); - Assert.assertEquals("100.0" + unit.toString(), c.getMinWidth()); - } - } - - @Test - public void setMaxWidthFloat() { - HasSizeComponent c = new HasSizeComponent(); - for (Unit unit : Unit.values()) { - c.setMaxWidth(100, unit); - Assert.assertEquals("100.0" + unit.toString(), c.getMaxWidth()); - } - } - - @Test - public void setHeightFloat() { - HasSizeComponent c = new HasSizeComponent(); - for (Unit unit : Unit.values()) { - c.setHeight(100, unit); - Assert.assertEquals("100.0" + unit.toString(), c.getHeight()); - } - } - - @Test - public void setMinHeightFloat() { - HasSizeComponent c = new HasSizeComponent(); - for (Unit unit : Unit.values()) { - c.setMinHeight(100, unit); - Assert.assertEquals("100.0" + unit.toString(), c.getMinHeight()); - } - } - - @Test - public void setMaxHeightFloat() { - HasSizeComponent c = new HasSizeComponent(); - for (Unit unit : Unit.values()) { - c.setMaxHeight(100, unit); - Assert.assertEquals("100.0" + unit.toString(), c.getMaxHeight()); - } - } - - @Test - public void getUnit() { - for (Unit unit : Unit.values()) { - String cssSize = 100f + unit.toString(); - Optional theUnit = Unit.getUnit(cssSize); - Assert.assertTrue(theUnit.isPresent()); - Assert.assertEquals(theUnit.get(), unit); - } - } - - @Test - public void getSize() { - for (Unit unit : Unit.values()) { - String cssSize = 100f + unit.toString(); - float size = Unit.getSize(cssSize); - Assert.assertEquals(100f, size, 0.01); - } - for (Unit unit : Unit.values()) { - String cssSize = unit.toString(); - float size = Unit.getSize(cssSize); - Assert.assertEquals(0f, size, 0.01); - } - } - - @Test(expected = NumberFormatException.class) - public void getSizeException() { - String cssSize = "10a0px"; - float size = Unit.getSize(cssSize); - } - - @Test(expected = IllegalArgumentException.class) - public void getSizeNoUnit() { - String cssSize = "100"; - float size = Unit.getSize(cssSize); - } - - @Test(expected = IllegalArgumentException.class) - public void getSizeNoValidUnit() { - String cssSize = "100p"; - float size = Unit.getSize(cssSize); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasStyleTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasStyleTest.java deleted file mode 100644 index 04b6329383b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasStyleTest.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; - -public class HasStyleTest { - - @Tag("div") - public static class HasStyleComponent extends Component - implements HasStyle { - - } - - @Test - public void addClassName() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassName("foo"); - assertClasses(component, "foo"); - component.addClassName("bar"); - assertClasses(component, "foo", "bar"); - - // use ClassList - - component.getClassNames().add("baz"); - assertClasses(component, "foo", "bar", "baz"); - } - - @Test - public void setClassName_useClassList() { - HasStyleComponent component = new HasStyleComponent(); - component.setClassName("foo bar"); - - component.getClassNames().set("bar", false); - assertClasses(component, "foo"); - } - - @Test - public void removeClassName() { - HasStyleComponent component = new HasStyleComponent(); - component.setClassName("foo Bar baz"); - component.removeClassName("foo"); - assertClasses(component, "Bar", "baz"); - component.removeClassName("bar"); - assertClasses(component, "Bar", "baz"); - component.removeClassName("Bar"); - assertClasses(component, "baz"); - component.removeClassName("baz"); - assertClasses(component); - - // use ClassList - component.setClassName("foo"); - - component.getClassNames().remove("foo"); - assertClasses(component); - } - - @Test - public void setClassName() { - HasStyleComponent component = new HasStyleComponent(); - component.setClassName("foo"); - assertClasses(component, "foo"); - component.setClassName("bar"); - assertClasses(component, "bar"); - component.setClassName("bar foo"); - assertClasses(component, "bar", "foo"); - component.setClassName(" "); - assertClasses(component); - component.setClassName(""); - assertClasses(component); - - component.setClassName("removeMe"); - // setting null to classname should remove class name attribute - component.setClassName(null); - assertClasses(component); - } - - @Test - public void getClassName() { - HasStyleComponent component = new HasStyleComponent(); - component.setClassName("foo"); - Assert.assertEquals("foo", component.getClassName()); - component.setClassName(" "); - Assert.assertNull(component.getClassName()); - } - - @Test - public void setClassNameToggle() { - HasStyleComponent component = new HasStyleComponent(); - component.setClassName("foo", false); - assertClasses(component); - component.setClassName("foo", true); - assertClasses(component, "foo"); - component.setClassName("foo", false); - assertClasses(component); - component.setClassName("foo", true); - component.setClassName("bar", true); - component.setClassName("baz", true); - assertClasses(component, "foo", "bar", "baz"); - component.setClassName("baz", false); - assertClasses(component, "foo", "bar"); - - } - - @Test - public void hasClassName() { - HasStyleComponent component = new HasStyleComponent(); - Assert.assertFalse(component.hasClassName("foo")); - component.setClassName("foo"); - Assert.assertTrue(component.hasClassName("foo")); - Assert.assertFalse(component.hasClassName("fo")); - component.setClassName("foo bar"); - Assert.assertTrue(component.hasClassName("foo")); - Assert.assertTrue(component.hasClassName("bar")); - - } - - @Test - public void getClassList_elementClassList() { - HasStyleComponent component = new HasStyleComponent(); - - Assert.assertEquals(component.getElement().getClassList(), - component.getClassNames()); - } - - @Test - public void testAddClassNames() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames(); - assertClasses(component); - component.addClassNames("foo", "bar"); - assertClasses(component, "foo", "bar"); - - component.removeClassNames("foo bar"); - assertClasses(component); - - component.addClassNames("foo bar"); - assertClasses(component, "foo", "bar"); - - component.addClassNames("baz1", "baz2"); - assertClasses(component, "foo", "bar", "baz1", "baz2"); - } - - @Test - public void testRemoveClassNames() { - HasStyleComponent component = new HasStyleComponent(); - component.setClassName("foo bar baz1 baz2 foo2 bar1"); - - component.removeClassNames(); - assertClasses(component, "foo", "bar", "baz1", "baz2", "foo2", "bar1"); - - component.removeClassNames("baz2"); - assertClasses(component, "foo", "bar", "baz1", "foo2", "bar1"); - - component.removeClassNames("bar", "foo2", "foo"); - assertClasses(component, "baz1", "bar1"); - } - - @Test - public void addClassNames_extraSpacesBetweenAndAroundClassNames_validationPasses() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames(" foo bar baz"); - - Assert.assertEquals( - "Unexpected component's class names count after adding 3 class names", - 3, component.getClassNames().size()); - - Assert.assertTrue(component.getClassNames().contains("foo")); - Assert.assertTrue(component.getClassNames().contains("bar")); - Assert.assertTrue(component.getClassNames().contains("baz")); - } - - @Test - public void removeClassNames_extraSpacesBetweenAndAroundClassNames_validationPasses() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames("foo", "bar", "baz"); - component.removeClassNames(" foo bar baz"); - - Assert.assertEquals( - "Unexpected component's class names count after removing all class names", - 0, component.getClassNames().size()); - } - - @Test(expected = IllegalArgumentException.class) - public void addClassNames_addEmptyClassName_throws() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames(" "); - } - - @Test(expected = IllegalArgumentException.class) - public void addClassNames_addNullClassName_throws() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames(null, null); - } - - @Test(expected = IllegalArgumentException.class) - public void removeClassNames_removeEmptyClassName_throws() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames(" "); - } - - @Test(expected = IllegalArgumentException.class) - public void removeClassNames_removeNullClassName_throws() { - HasStyleComponent component = new HasStyleComponent(); - component.addClassNames(null, null); - } - - private void assertClasses(HasStyleComponent c, String... expectedClasses) { - Set actual = c.getClassNames(); - Set expected = new HashSet<>(Arrays.asList(expectedClasses)); - Assert.assertEquals(expected, actual); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasTextTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasTextTest.java deleted file mode 100644 index 84d4eba36a2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasTextTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.HasText.WhiteSpace; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; - -public class HasTextTest { - - private HasText hasText = Mockito.mock(HasText.class); - - @Before - public void setUp() { - Element element = ElementFactory.createDiv(); - Mockito.when(hasText.getElement()).thenReturn(element); - - Mockito.doCallRealMethod().when(hasText).setWhiteSpace(Mockito.any()); - Mockito.doCallRealMethod().when(hasText).getWhiteSpace(); - } - - @Test - public void setWhiteSpace_styleIsSet() { - hasText.setWhiteSpace(WhiteSpace.NOWRAP); - - Assert.assertEquals("nowrap", - hasText.getElement().getStyle().get("white-space")); - } - - @Test - public void getWhiteSpace_getStyleValue() { - hasText.getElement().getStyle().set("white-space", "inherit"); - - Assert.assertEquals(WhiteSpace.INHERIT, hasText.getWhiteSpace()); - } - - @Test - public void getWhiteSpace_noStyleIsSet_normalIsReturned() { - Assert.assertEquals(WhiteSpace.NORMAL, hasText.getWhiteSpace()); - } - - @Test - public void getWhiteSpace_notStandardValue_nullIsReturned() { - hasText.getElement().getStyle().set("white-space", "foo"); - - Assert.assertEquals(null, hasText.getWhiteSpace()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/HasThemeTest.java b/flow-server/src/test/java/com/vaadin/flow/component/HasThemeTest.java deleted file mode 100644 index 01b7cbdda9d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/HasThemeTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; - -public class HasThemeTest { - - @Tag("div") - public static class HasThemeComponent extends Component - implements HasTheme { - - } - - @Test - public void addThemeName() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - component.addThemeName("foo"); - assertThemes(component, "foo"); - component.addThemeName("bar"); - assertThemes(component, "foo", "bar"); - - // use ThemeList - - component.getThemeNames().add("baz"); - assertThemes(component, "foo", "bar", "baz"); - } - - @Test - public void setThemeName_useThemeList() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - component.setThemeName("foo bar"); - - component.getThemeNames().set("bar", false); - assertThemes(component, "foo"); - } - - @Test - public void removeThemeName() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - component.setThemeName("foo Bar baz"); - component.removeThemeName("foo"); - assertThemes(component, "Bar", "baz"); - component.removeThemeName("bar"); - assertThemes(component, "Bar", "baz"); - component.removeThemeName("Bar"); - assertThemes(component, "baz"); - component.removeThemeName("baz"); - assertThemes(component); - - // use ThemeList - component.setThemeName("foo"); - - component.getThemeNames().remove("foo"); - assertThemes(component); - } - - @Test - public void setThemeName() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - Assert.assertNull(component.getThemeName()); - component.setThemeName("foo"); - assertThemes(component, "foo"); - component.setThemeName("bar"); - assertThemes(component, "bar"); - component.setThemeName("bar foo"); - assertThemes(component, "bar", "foo"); - component.setThemeName(""); - assertThemes(component); - component.setThemeName(""); - assertThemes(component); - } - - @Test - public void getThemeName() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - Assert.assertNull(component.getThemeName()); - component.setThemeName("foo"); - Assert.assertEquals("foo", component.getThemeName()); - component.setThemeName(""); - Assert.assertEquals("", component.getThemeName()); - } - - @Test - public void setThemeNameToggle() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - component.setThemeName("foo", false); - assertThemes(component); - component.setThemeName("foo", true); - assertThemes(component, "foo"); - component.setThemeName("foo", false); - assertThemes(component); - component.setThemeName("foo", true); - component.setThemeName("bar", true); - component.setThemeName("baz", true); - assertThemes(component, "foo", "bar", "baz"); - component.setThemeName("baz", false); - assertThemes(component, "foo", "bar"); - - } - - @Test - public void hasThemeName() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - Assert.assertFalse(component.hasThemeName("foo")); - component.setThemeName("foo"); - Assert.assertTrue(component.hasThemeName("foo")); - Assert.assertFalse(component.hasThemeName("fo")); - component.setThemeName("foo bar"); - Assert.assertTrue(component.hasThemeName("foo")); - Assert.assertTrue(component.hasThemeName("bar")); - - } - - @Test - public void getThemeList_elementThemeList() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - - Assert.assertEquals(component.getElement().getThemeList().isEmpty(), - component.getThemeNames().isEmpty()); - } - - @Test - public void testAddThemeNames() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - component.addThemeNames(); - assertThemes(component); - component.addThemeNames("foo", "bar"); - assertThemes(component, "foo", "bar"); - component.addThemeNames("baz1", "baz2"); - assertThemes(component, "foo", "bar", "baz1", "baz2"); - } - - @Test - public void testRemoveThemeNames() { - HasThemeTest.HasThemeComponent component = new HasThemeTest.HasThemeComponent(); - component.setThemeName("foo bar baz1 baz2 foo2 bar1"); - - component.removeThemeNames(); - assertThemes(component, "foo", "bar", "baz1", "baz2", "foo2", "bar1"); - - component.removeThemeNames("baz2"); - assertThemes(component, "foo", "bar", "baz1", "foo2", "bar1"); - - component.removeThemeNames("bar", "foo2", "foo"); - assertThemes(component, "baz1", "bar1"); - } - - private void assertThemes(HasThemeTest.HasThemeComponent c, - String... expectedThemes) { - Set actual = c.getThemeNames(); - Set expected = new HashSet<>(Arrays.asList(expectedThemes)); - Assert.assertEquals(expected, actual); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/InvalidMappedToDomEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/InvalidMappedToDomEvent.java deleted file mode 100644 index 134e7a7749d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/InvalidMappedToDomEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -@DomEvent("dom-event") -public class InvalidMappedToDomEvent extends ComponentEvent { - - public InvalidMappedToDomEvent(Component source) { - super(source, true); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/InvalidUrlTest.java b/flow-server/src/test/java/com/vaadin/flow/component/InvalidUrlTest.java deleted file mode 100644 index f6decfcd200..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/InvalidUrlTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Arrays; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.server.BootstrapHandlerTest; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; - -import static org.junit.Assert.assertEquals; - -public class InvalidUrlTest { - - @Test - public void invalidUrlAtInitialization_uiInitialiazesWith404ReturnCode() - throws InvalidRouteConfigurationException, ServiceException { - UI ui = new UI(); - - ArgumentCaptor statusCodeCaptor = ArgumentCaptor - .forClass(Integer.class); - - initUI(ui, "%3faaa", statusCodeCaptor); - - assertEquals("Return message should have been 404 not found.", - Integer.valueOf(404), statusCodeCaptor.getValue()); - } - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - private static void initUI(UI ui, String initialLocation, - ArgumentCaptor statusCodeCaptor) - throws InvalidRouteConfigurationException, ServiceException { - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - VaadinResponse response = Mockito.mock(VaadinResponse.class); - - String pathInfo; - if (initialLocation.isEmpty()) { - pathInfo = null; - } else { - Assert.assertFalse(initialLocation.startsWith("/")); - pathInfo = "/" + initialLocation; - } - Mockito.when(request.getPathInfo()).thenReturn(pathInfo); - - VaadinService service = new MockVaadinServletService() { - @Override - public VaadinContext getContext() { - return new MockVaadinContext(); - } - }; - service.setCurrentInstances(request, response); - - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - - DeploymentConfiguration config = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(config.isProductionMode()).thenReturn(false); - - session.lock(); - session.setConfiguration(config); - - ui.getInternals().setSession(session); - - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(ui.getRouter().getRegistry()); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - Arrays.asList(UITest.RootNavigationTarget.class, - UITest.FooBarNavigationTarget.class) - .forEach(routeConfiguration::setAnnotatedRoute); - }); - - ui.doInit(request, 0); - ui.getRouter().initializeUI(ui, - BootstrapHandlerTest.requestToLocation(request)); - - session.unlock(); - - if (statusCodeCaptor != null) { - Mockito.verify(response).setStatus(statusCodeCaptor.capture()); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/JavaScriptInvocationTest.java b/flow-server/src/test/java/com/vaadin/flow/component/JavaScriptInvocationTest.java deleted file mode 100644 index c9b70bfc16f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/JavaScriptInvocationTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.component.internal.UIInternals.JavaScriptInvocation; - -import elemental.json.Json; -import elemental.json.JsonString; - -public class JavaScriptInvocationTest { - @Test - public void testSerializable() { - JavaScriptInvocation invocation = new UIInternals.JavaScriptInvocation( - "expression", "string", Json.create("jsonString")); - - JavaScriptInvocation deserialized = SerializationUtils - .deserialize(SerializationUtils.serialize(invocation)); - - Assert.assertNotSame(invocation, deserialized); - - Assert.assertEquals("expression", deserialized.getExpression()); - Assert.assertEquals(2, deserialized.getParameters().size()); - Assert.assertEquals("string", deserialized.getParameters().get(0)); - Assert.assertEquals("jsonString", - ((JsonString) deserialized.getParameters().get(1)).getString()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/KeyTest.java b/flow-server/src/test/java/com/vaadin/flow/component/KeyTest.java deleted file mode 100644 index a2df9e93d17..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/KeyTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Assert; -import org.junit.Test; - -public class KeyTest { - - @Tag("input") - public static class InputComponent extends Component - implements KeyNotifier { - - } - - @Test - public void listenerWithMultipleKeyValues() { - InputComponent input = new InputComponent(); - AtomicBoolean fired = new AtomicBoolean(false); - input.addKeyPressListener(Key.of("foo", "bar"), - event -> fired.set(true)); - - input.fireEvent(new KeyPressEvent(input, "foo")); - Assert.assertTrue(fired.get()); - - fired.set(false); - input.fireEvent(new KeyPressEvent(input, "bar")); - Assert.assertTrue(fired.get()); - - fired.set(false); - input.fireEvent(new KeyPressEvent(input, "baz")); - Assert.assertFalse(fired.get()); - } - - @Test - public void of_toString_returnsKeys() { - Key key = Key.of("foo"); - - Assert.assertEquals("foo", key.toString()); - - key = Key.of("foo", "bar"); - - Assert.assertEquals("foo, additional keys : [bar]", key.toString()); - } - - @Test - public void of_equals_stringRepresentationsEqual_toKeysAreEqual() { - Key key1 = Key.of("foo"); - Key key2 = Key.of("foo"); - - Assert.assertEquals(key1, key2); - } - - @Test - public void of_equals_stringRepresentationsNotEqual_toKeysAreNotEqual() { - Key key1 = Key.of("foo"); - Key key2 = Key.of("bar"); - - Assert.assertNotEquals(key1, key2); - } - - @Test - public void of_equals_secondKeyHasAdditionalKeys_toKeysAreNotEqual() { - Key key1 = Key.of("foo"); - Key key2 = Key.of("foo", "bar"); - - Assert.assertNotEquals(key1, key2); - } - - @Test - public void of_equals_differentClasses_toKeysAreNotEqual() { - Key key1 = Key.of("foo"); - Key key2 = new Key() { - - @Override - public List getKeys() { - return Collections.singletonList("foo"); - } - }; - - Assert.assertNotEquals(key1, key2); - } - - @Test - public void of_equalKeys_hasSameHashCode() { - Key key1 = Key.of("foo", "bar"); - Key key2 = Key.of("foo", "bar"); - Assert.assertEquals(key1.hashCode(), key2.hashCode()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/LocationObserverTest.java b/flow-server/src/test/java/com/vaadin/flow/component/LocationObserverTest.java deleted file mode 100644 index 144996f26bf..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/LocationObserverTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.i18n.LocaleChangeEvent; -import com.vaadin.flow.i18n.LocaleChangeObserver; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.TestRouteRegistry; -import com.vaadin.flow.server.Command; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; -import com.vaadin.tests.util.MockUI; - -public class LocationObserverTest { - - protected Router router; - private UI ui; - - private static List eventCollector = new ArrayList<>(0); - - @Route("") - @Tag(Tag.DIV) - public static class Translations extends Component - implements LocaleChangeObserver { - - @Override - public void localeChange(LocaleChangeEvent event) { - eventCollector.add("Received locale change event for locale: " - + event.getLocale().getDisplayName()); - Assert.assertNotNull(event.getUI()); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class RootComponent extends Component { - } - - public static class RouterTestMockUI extends MockUI { - - public RouterTestMockUI(Router router) { - super(createMockSession(router)); - } - - private static VaadinSession createMockSession(Router router) { - MockVaadinServletService service = new MockVaadinServletService(); - service.setRouter(router); - - VaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(service.getDeploymentConfiguration()); - return session; - } - - @Override - public void accessSynchronously(Command command) - throws UIDetachedException { - // NOOP - } - } - - @Before - public void init() throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - ui = new UI(); - eventCollector.clear(); - } - - @Test - public void navigation_and_locale_change_should_fire_locale_change_observer() - throws InvalidRouteConfigurationException { - router = new Router(new TestRouteRegistry()); - ui = new RouterTestMockUI(router); - - RouteConfiguration.forRegistry(router.getRegistry()) - .setAnnotatedRoute(Translations.class); - - ui.navigate(""); - - Assert.assertEquals("Expected event amount was wrong", 1, - eventCollector.size()); - Assert.assertEquals( - "Received locale change event for locale: " - + Locale.getDefault().getDisplayName(), - eventCollector.get(0)); - - ui.setLocale(Locale.CANADA); - - Assert.assertEquals("Expected event amount was wrong", 2, - eventCollector.size()); - Assert.assertEquals( - "Received locale change event for locale: " - + Locale.CANADA.getDisplayName(), - eventCollector.get(1)); - } - - @Test - public void location_change_should_only_fire_if_location_actually_changed() { - ui.add(new Translations()); - - Assert.assertEquals("Expected event amount was wrong", 1, - eventCollector.size()); - Assert.assertEquals( - "Received locale change event for locale: " - + Locale.getDefault().getDisplayName(), - eventCollector.get(0)); - - ui.setLocale(ui.getLocale()); - - Assert.assertEquals("Expected event amount was wrong", 1, - eventCollector.size()); - - ui.setLocale(Locale.FRENCH); - - Assert.assertEquals("Expected event amount was wrong", 2, - eventCollector.size()); - Assert.assertEquals( - "Received locale change event for locale: " - + Locale.FRENCH.getDisplayName(), - eventCollector.get(1)); - } - - @Test - public void location_change_should_be_fired_also_on_component_attach() { - RootComponent root = new RootComponent(); - - ui.add(root); - - Assert.assertEquals("Expected event amount was wrong", 0, - eventCollector.size()); - - root.getElement().appendChild(new Translations().getElement()); - - Assert.assertEquals("Expected event amount was wrong", 1, - eventCollector.size()); - Assert.assertEquals( - "Received locale change event for locale: " - + Locale.getDefault().getDisplayName(), - eventCollector.get(0)); - } - - @Test - public void location_change_should_be_fired_also_on_consequent_component_attach() { - RootComponent root = new RootComponent(); - - ui.add(root); - - Assert.assertEquals( - "No change observers so no events should be gotten.", 0, - eventCollector.size()); - - Translations translations = new Translations(); - root.getElement().appendChild(translations.getElement()); - - Assert.assertEquals("Observer should have been notified on attach", 1, - eventCollector.size()); - - translations.getElement().removeFromParent(); - - Assert.assertEquals("No event should have been gotten for removal", 1, - eventCollector.size()); - - root.getElement().appendChild(translations.getElement()); - Assert.assertEquals("Reattach should have given an event", 2, - eventCollector.size()); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedDomEventWithComponentData.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedDomEventWithComponentData.java deleted file mode 100644 index e26fafe04a2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedDomEventWithComponentData.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -@DomEvent("dom-event") -public class MappedDomEventWithComponentData extends ComponentEvent { - - private final Component component; - - public MappedDomEventWithComponentData(Component source, boolean fromClient, - @EventData("component") Component component) { - super(source, fromClient); - this.component = component; - } - - public Component getComponent() { - return component; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedDomEventWithRouterLinkData.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedDomEventWithRouterLinkData.java deleted file mode 100644 index 325f4ad8679..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedDomEventWithRouterLinkData.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import com.vaadin.flow.router.RouterLink; - -public class MappedDomEventWithRouterLinkData - extends MappedDomEventWithComponentData { - - private final RouterLink routerLink; - - public MappedDomEventWithRouterLinkData(Component source, - boolean fromClient, @EventData("component") Component component, - @EventData("router.link") RouterLink routerLink) { - super(source, fromClient, component); - this.routerLink = routerLink; - } - - public RouterLink getRouterLink() { - return routerLink; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEvent.java deleted file mode 100644 index 7414a5a1282..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEvent.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -@DomEvent("dom-event") -public class MappedToDomEvent extends ComponentEvent { - - private int someData; - private String moreData; - private boolean primitiveBoolean; - private Boolean objectBoolean; - - public MappedToDomEvent(Component source) { - super(source, false); - someData = 32; - moreData = "Default constructor"; - } - - public MappedToDomEvent(Component source, boolean fromClient) { - super(source, fromClient); - someData = 12; - moreData = "Two arg constructor"; - } - - public MappedToDomEvent(Component source, boolean fromClient, - @EventData("event.someData") int someData, - @EventData("event.moreData") String moreData, - @EventData("event.primitiveBoolean") boolean primitiveBoolean, - @EventData("event.objectBoolean") Boolean objectBoolean) { - super(source, fromClient); - this.someData = someData; - this.moreData = moreData; - this.primitiveBoolean = primitiveBoolean; - this.objectBoolean = objectBoolean; - } - - public int getSomeData() { - return someData; - } - - public String getMoreData() { - return moreData; - } - - public boolean getPrimitiveBoolean() { - return primitiveBoolean; - } - - public Boolean getObjectBoolean() { - return objectBoolean; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEventMultipleConstructors.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEventMultipleConstructors.java deleted file mode 100644 index 702e49153ed..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEventMultipleConstructors.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -@DomEvent("dom-event") -public class MappedToDomEventMultipleConstructors - extends ComponentEvent { - - public MappedToDomEventMultipleConstructors(Component source, - boolean fromClient, @EventData("someParam") int someParam) { - super(source, fromClient); - } - - public MappedToDomEventMultipleConstructors(Component source, - boolean fromClient, @EventData("otherParam") boolean otherParam) { - super(source, fromClient); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEventWithElementData.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEventWithElementData.java deleted file mode 100644 index 6cea0e13165..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomEventWithElementData.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import com.vaadin.flow.dom.Element; - -@DomEvent("dom-event") -public class MappedToDomEventWithElementData extends ComponentEvent { - - private final Element element; - - /** - * Creates a new event using the given source and indicator whether the - * event originated from the client side or the server side. - * - * @param source - * the source component - * @param fromClient - * true if the event originated from the client - */ - public MappedToDomEventWithElementData(Component source, boolean fromClient, - @EventData("element") Element element) { - super(source, fromClient); - this.element = element; - } - - public Element getElement() { - return element; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomInvalidEventData.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomInvalidEventData.java deleted file mode 100644 index f458b6eb1f0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomInvalidEventData.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -@DomEvent("dom-event") -public class MappedToDomInvalidEventData extends ComponentEvent { - - public MappedToDomInvalidEventData(Component source, boolean fromClient, - @EventData("") int strangeServerSideParam) { - super(source, fromClient); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomNoDataEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomNoDataEvent.java deleted file mode 100644 index 2089c2016c2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/MappedToDomNoDataEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -@DomEvent("dom-event") -public class MappedToDomNoDataEvent extends ComponentEvent { - - public MappedToDomNoDataEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - - public MappedToDomNoDataEvent(Component source, boolean fromClient, - int strangeServerSideParam) { - super(source, fromClient); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/NpmPackageTest.java b/flow-server/src/test/java/com/vaadin/flow/component/NpmPackageTest.java deleted file mode 100644 index 0bfbc604289..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/NpmPackageTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.component; - -import java.lang.annotation.Annotation; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.component.dependency.NpmPackage; - -public class NpmPackageTest { - - // Keep this here just to make sure the @NpmPackage annotation exists, since - // it's used outside of the flow-server module, and it has no other use - // inside flow-server, yet. - - @JsModule("test-component") - @NpmPackage(value = "test-package", version = "0.0.0") - private static class TestComponent extends Component { - } - - @Test - public void testDummy() { - Annotation[] annotations = TestComponent.class.getAnnotations(); - - Assert.assertEquals("NpmPackage is missing", - annotations[1].annotationType(), NpmPackage.class); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/PropertyDescriptorsTest.java b/flow-server/src/test/java/com/vaadin/flow/component/PropertyDescriptorsTest.java deleted file mode 100644 index 03cee8a2313..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/PropertyDescriptorsTest.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.ComponentTest.TestComponent; - -public class PropertyDescriptorsTest { - - private static final Integer ZERO = Integer.valueOf(0); - private static final Integer ONE = Integer.valueOf(1); - private static final Double ZERO_DOUBLE = 0.0; - private static final Double ONE_DOUBLE = 1.0; - private static final String EMPTY_STRING = ""; - private static final String FOO = "foo"; - private static final String SOME_STRING_VALUE = "foobar123456"; - private static final Integer SOME_INTEGER_VALUE = Integer - .valueOf(129837419); - private static final Double SOME_DOUBLE_VALUE = 3.14; - private static final String TEST_PROPERTY = "someproperty"; - private TestComponent component; - - private static PropertyDescriptor stringAttributeDefaultEmpty = PropertyDescriptors - .attributeWithDefault(TEST_PROPERTY, EMPTY_STRING); - private static PropertyDescriptor stringAttributeDefaultFoo = PropertyDescriptors - .attributeWithDefault(TEST_PROPERTY, FOO); - private static PropertyDescriptor> stringAttributeOptionalDefaultEmpty = PropertyDescriptors - .optionalAttributeWithDefault(TEST_PROPERTY, EMPTY_STRING); - private static PropertyDescriptor> stringAttributeOptionalDefaultFoo = PropertyDescriptors - .optionalAttributeWithDefault(TEST_PROPERTY, FOO); - - private static PropertyDescriptor stringPropertyDefaultEmpty = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, EMPTY_STRING); - private static PropertyDescriptor stringPropertyDefaultFoo = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, FOO); - private static PropertyDescriptor integerPropertyDefaultZero = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, 0); - private static PropertyDescriptor integerPropertyDefaultOne = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, 1); - private static PropertyDescriptor doublePropertyDefaultZero = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, 0.0); - private static PropertyDescriptor doublePropertyDefaultOne = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, 1.0); - private static PropertyDescriptor booleanPropertyDefaultFalse = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, false); - private static PropertyDescriptor booleanPropertyDefaultTrue = PropertyDescriptors - .propertyWithDefault(TEST_PROPERTY, true); - - @Before - public void setup() { - component = new TestComponent(); - } - - @Test - public void stringPropertyDefaultEmptyString_initial() { - Assert.assertEquals(EMPTY_STRING, - stringPropertyDefaultEmpty.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void stringPropertyDefaultEmptyString_setNonDefault() { - stringPropertyDefaultEmpty.set(component, SOME_STRING_VALUE); - Assert.assertEquals(SOME_STRING_VALUE, - stringPropertyDefaultEmpty.get(component)); - Assert.assertEquals(SOME_STRING_VALUE, - component.getElement().getPropertyRaw(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void stringPropertyDefaultEmptyString_resetToDefault() { - stringPropertyDefaultEmpty.set(component, SOME_STRING_VALUE); - stringPropertyDefaultEmpty.set(component, EMPTY_STRING); - Assert.assertEquals(EMPTY_STRING, - stringPropertyDefaultEmpty.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void stringPropertyDefaultEmptyString_setToNull() { - stringPropertyDefaultEmpty.set(component, null); - } - - @Test - public void stringPropertyDefaultFoo_initial() { - Assert.assertEquals(FOO, stringPropertyDefaultFoo.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void stringPropertyDefaultFoo_setNonDefault() { - stringPropertyDefaultFoo.set(component, SOME_STRING_VALUE); - Assert.assertEquals(SOME_STRING_VALUE, - stringPropertyDefaultFoo.get(component)); - Assert.assertEquals(SOME_STRING_VALUE, - component.getElement().getPropertyRaw(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void stringPropertyDefaultFoo_resetToDefault() { - stringPropertyDefaultFoo.set(component, SOME_STRING_VALUE); - stringPropertyDefaultFoo.set(component, FOO); - Assert.assertEquals(FOO, stringPropertyDefaultFoo.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void stringPropertyDefaultFoo_setToNull() { - stringPropertyDefaultFoo.set(component, null); - } - - @Test - public void integerPropertyDefaultZero_initial() { - Assert.assertEquals(ZERO, integerPropertyDefaultZero.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void integerPropertyDefaultZero_setNonDefault() { - integerPropertyDefaultZero.set(component, SOME_INTEGER_VALUE); - Assert.assertEquals(SOME_INTEGER_VALUE, - integerPropertyDefaultZero.get(component)); - Assert.assertEquals(SOME_INTEGER_VALUE, Integer.valueOf( - component.getElement().getProperty(TEST_PROPERTY, -1))); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void integerPropertyDefaultZero_resetToDefault() { - integerPropertyDefaultZero.set(component, SOME_INTEGER_VALUE); - integerPropertyDefaultZero.set(component, ZERO); - Assert.assertEquals(ZERO, integerPropertyDefaultZero.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void integerPropertyDefaultZero_setToNull() { - integerPropertyDefaultZero.set(component, null); - } - - @Test - public void integerPropertyDefaultOne_initial() { - Assert.assertEquals(ONE, integerPropertyDefaultOne.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void integerPropertyDefaultOne_setNonDefault() { - integerPropertyDefaultOne.set(component, SOME_INTEGER_VALUE); - Assert.assertEquals(SOME_INTEGER_VALUE, - integerPropertyDefaultOne.get(component)); - Assert.assertEquals(SOME_INTEGER_VALUE, Integer.valueOf( - component.getElement().getProperty(TEST_PROPERTY, -1))); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void integerPropertyDefaultOne_resetToDefault() { - integerPropertyDefaultOne.set(component, SOME_INTEGER_VALUE); - integerPropertyDefaultOne.set(component, ONE); - Assert.assertEquals(ONE, integerPropertyDefaultOne.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void integerPropertyDefaultOne_setToNull() { - integerPropertyDefaultOne.set(component, null); - } - - @Test - public void doublePropertyDefaultZero_initial() { - Assert.assertEquals(ZERO_DOUBLE, - doublePropertyDefaultZero.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void doublePropertyDefaultZero_setNonDefault() { - doublePropertyDefaultZero.set(component, SOME_DOUBLE_VALUE); - Assert.assertEquals(SOME_DOUBLE_VALUE, - doublePropertyDefaultZero.get(component)); - Assert.assertEquals(SOME_DOUBLE_VALUE, Double.valueOf( - component.getElement().getProperty(TEST_PROPERTY, -1.0))); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void doublePropertyDefaultZero_resetToDefault() { - doublePropertyDefaultZero.set(component, SOME_DOUBLE_VALUE); - doublePropertyDefaultZero.set(component, ZERO_DOUBLE); - Assert.assertEquals(ZERO_DOUBLE, - doublePropertyDefaultZero.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void doublePropertyDefaultZero_setToNull() { - doublePropertyDefaultZero.set(component, null); - } - - @Test - public void doublePropertyDefaultOne_initial() { - Assert.assertEquals(ONE_DOUBLE, - doublePropertyDefaultOne.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void doublePropertyDefaultOne_setNonDefault() { - doublePropertyDefaultOne.set(component, SOME_DOUBLE_VALUE); - Assert.assertEquals(SOME_DOUBLE_VALUE, - doublePropertyDefaultOne.get(component)); - Assert.assertEquals(SOME_DOUBLE_VALUE, Double.valueOf( - component.getElement().getProperty(TEST_PROPERTY, -1.0))); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void doublePropertyDefaultOne_resetToDefault() { - doublePropertyDefaultOne.set(component, SOME_DOUBLE_VALUE); - doublePropertyDefaultOne.set(component, ONE_DOUBLE); - Assert.assertEquals(ONE_DOUBLE, - doublePropertyDefaultOne.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void doublePropertyDefaultOne_setToNull() { - doublePropertyDefaultOne.set(component, null); - } - - @Test - public void booleanPropertyDefaultFalse_initial() { - Assert.assertEquals(false, booleanPropertyDefaultFalse.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void booleanPropertyDefaultFalse_setNonDefault() { - booleanPropertyDefaultFalse.set(component, true); - Assert.assertEquals(true, booleanPropertyDefaultFalse.get(component)); - Assert.assertEquals(true, Boolean.valueOf(component.getElement() - .getProperty(TEST_PROPERTY, "neverused"))); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void booleanPropertyDefaultFalse_resetToDefault() { - booleanPropertyDefaultFalse.set(component, true); - booleanPropertyDefaultFalse.set(component, false); - Assert.assertEquals(false, booleanPropertyDefaultFalse.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void booleanPropertyDefaultFalse_setToNull() { - booleanPropertyDefaultFalse.set(component, null); - } - - @Test - public void booleanPropertyDefaultTrue_initial() { - Assert.assertEquals(true, booleanPropertyDefaultTrue.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void booleanPropertyDefaultTrue_setNonDefault() { - booleanPropertyDefaultTrue.set(component, false); - Assert.assertEquals(false, booleanPropertyDefaultTrue.get(component)); - Assert.assertEquals(false, Boolean.valueOf(component.getElement() - .getProperty(TEST_PROPERTY, "neverused"))); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test - public void booleanPropertyDefaultTrue_resetToDefault() { - booleanPropertyDefaultTrue.set(component, false); - booleanPropertyDefaultTrue.set(component, true); - Assert.assertEquals(true, booleanPropertyDefaultTrue.get(component)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void booleanPropertyDefaultTrue_setToNull() { - booleanPropertyDefaultTrue.set(component, null); - } - - @Test - public void stringAttributeDefaultEmpty_initial() { - Assert.assertEquals(EMPTY_STRING, - stringAttributeDefaultEmpty.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeDefaultEmpty_setNonDefault() { - stringAttributeDefaultEmpty.set(component, SOME_STRING_VALUE); - Assert.assertEquals(SOME_STRING_VALUE, - stringAttributeDefaultEmpty.get(component)); - Assert.assertEquals(SOME_STRING_VALUE, - component.getElement().getAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeDefaultEmpty_resetToDefault() { - stringAttributeDefaultEmpty.set(component, SOME_STRING_VALUE); - stringAttributeDefaultEmpty.set(component, EMPTY_STRING); - Assert.assertEquals(EMPTY_STRING, - stringAttributeDefaultEmpty.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - - } - - @Test(expected = IllegalArgumentException.class) - public void stringAttributeDefaultEmpty_setToNull() { - stringAttributeDefaultEmpty.set(component, null); - } - - @Test - public void stringAttributeDefaultFoo_initial() { - Assert.assertEquals(FOO, stringAttributeDefaultFoo.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeDefaultFoo_setNonDefault() { - stringAttributeDefaultFoo.set(component, SOME_STRING_VALUE); - Assert.assertEquals(SOME_STRING_VALUE, - stringAttributeDefaultFoo.get(component)); - Assert.assertEquals(SOME_STRING_VALUE, - component.getElement().getAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeDefaultFoo_resetToDefault() { - stringAttributeDefaultFoo.set(component, SOME_STRING_VALUE); - stringAttributeDefaultFoo.set(component, FOO); - Assert.assertEquals(FOO, stringAttributeDefaultFoo.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - - } - - @Test(expected = IllegalArgumentException.class) - public void stringAttributeDefaultFoo_setToNull() { - stringAttributeDefaultFoo.set(component, null); - } - - @Test - public void stringAttributeOptionalDefaultEmpty_initial() { - Assert.assertEquals(Optional.empty(), - stringAttributeOptionalDefaultEmpty.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeOptionalDefaultEmpty_setNonOptionalDefault() { - stringAttributeOptionalDefaultEmpty.set(component, SOME_STRING_VALUE); - Assert.assertEquals(Optional.of(SOME_STRING_VALUE), - stringAttributeOptionalDefaultEmpty.get(component)); - Assert.assertEquals(SOME_STRING_VALUE, - component.getElement().getAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeOptionalDefaultEmpty_resetToOptionalDefault() { - stringAttributeOptionalDefaultEmpty.set(component, SOME_STRING_VALUE); - stringAttributeOptionalDefaultEmpty.set(component, EMPTY_STRING); - Assert.assertEquals(Optional.empty(), - stringAttributeOptionalDefaultEmpty.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - - } - - @Test(expected = IllegalArgumentException.class) - public void stringAttributeOptionalDefaultEmpty_setToNull() { - stringAttributeOptionalDefaultEmpty.set(component, null); - } - - @Test - public void stringAttributeOptionalDefaultFoo_initial() { - Assert.assertEquals(Optional.empty(), - stringAttributeOptionalDefaultFoo.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeOptionalDefaultFoo_setNonOptionalDefault() { - stringAttributeOptionalDefaultFoo.set(component, SOME_STRING_VALUE); - Assert.assertEquals(Optional.of(SOME_STRING_VALUE), - stringAttributeOptionalDefaultFoo.get(component)); - Assert.assertEquals(SOME_STRING_VALUE, - component.getElement().getAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - } - - @Test - public void stringAttributeOptionalDefaultFoo_resetToOptionalDefault() { - stringAttributeOptionalDefaultFoo.set(component, SOME_STRING_VALUE); - stringAttributeOptionalDefaultFoo.set(component, FOO); - Assert.assertEquals(Optional.empty(), - stringAttributeOptionalDefaultFoo.get(component)); - Assert.assertFalse(component.getElement().hasAttribute(TEST_PROPERTY)); - Assert.assertFalse(component.getElement().hasProperty(TEST_PROPERTY)); - - } - - @Test(expected = IllegalArgumentException.class) - public void stringAttributeOptionalDefaultFoo_setToNull() { - stringAttributeOptionalDefaultFoo.set(component, null); - } - - @Test - public void propertyName() { - Assert.assertEquals(TEST_PROPERTY, - stringAttributeDefaultEmpty.getPropertyName()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ServerEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/ServerEvent.java deleted file mode 100644 index c05e8e574d3..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ServerEvent.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.math.BigDecimal; - -public class ServerEvent extends ComponentEvent { - - private BigDecimal someValue; - - public ServerEvent(Component source, BigDecimal someValue) { - super(source, false); - this.someValue = someValue; - } - - public BigDecimal getSomeValue() { - return someValue; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ServerNoDataEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/ServerNoDataEvent.java deleted file mode 100644 index 8d0e7780e96..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ServerNoDataEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -public class ServerNoDataEvent extends ComponentEvent { - - public ServerNoDataEvent(Component source, boolean fromClient) { - super(source, fromClient); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ShortcutEventTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ShortcutEventTest.java deleted file mode 100644 index a13ff14bab2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ShortcutEventTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.vaadin.flow.component; - -import java.util.Arrays; -import java.util.HashSet; - -import org.junit.Test; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; - -public class ShortcutEventTest { - - private ShortcutEvent eventNoModifiers = event(Key.KEY_F); - private ShortcutEvent eventOneModifier = event(Key.KEY_F, KeyModifier.ALT); - private ShortcutEvent eventTwoModifiers = event(Key.KEY_F, KeyModifier.ALT, - KeyModifier.CONTROL); - - @Test - public void matches() { - assertFalse("Null key should return false", - eventNoModifiers.matches(null)); - assertFalse("Extra modifier should return false", - eventNoModifiers.matches(Key.KEY_F, KeyModifier.ALT)); - assertFalse("Missing modifier should return false", - eventOneModifier.matches(Key.KEY_F)); - - assertTrue("Matching key should return true", - eventNoModifiers.matches(Key.KEY_F)); - assertTrue("Matching key and modifier should return true", - eventOneModifier.matches(Key.KEY_F, KeyModifier.ALT)); - assertTrue("Matching key and two modifiers should return true", - eventTwoModifiers.matches(Key.KEY_F, KeyModifier.ALT, - KeyModifier.CONTROL)); - } - - private static ShortcutEvent event(Key key, KeyModifier... modifiers) { - Component component = mock(Component.class); - return new ShortcutEvent(component, component, key, - new HashSet<>(Arrays.asList(modifiers))); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ShortcutRegistrationTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ShortcutRegistrationTest.java deleted file mode 100644 index f44bfe429a8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ShortcutRegistrationTest.java +++ /dev/null @@ -1,735 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.component.internal.PendingJavaScriptInvocation; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.function.SerializableConsumer; -import com.vaadin.flow.internal.ExecutionContext; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.Registration; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class ShortcutRegistrationTest { - - private UI ui; - private Component lifecycleOwner; - private Component[] listenOn = new Component[3]; - - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); - - @Before - public void initTests() { - ui = mock(UI.class); - lifecycleOwner = mock(Component.class); - Arrays.setAll(listenOn, i -> mock(Component.class)); - - when(lifecycleOwner.getUI()).thenReturn(Optional.of(ui)); - when(lifecycleOwner.addAttachListener(any())) - .thenReturn(mock(Registration.class)); - when(lifecycleOwner.addDetachListener(any())) - .thenReturn(mock(Registration.class)); - - for (Component component : listenOn) { - when(component.getUI()).thenReturn(Optional.of(ui)); - } - } - - @Test - public void registrationWillBeCompletedBeforeClientResponse() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - clientResponse(); - - // If everything went according to plan, the shortcut should be - // active - // on our fake UI - assertTrue(registration.isShortcutActive()); - - // There should be no need to update the client - assertFalse(registration.isDirty()); - } - - @Test - public void constructedRegistrationIsDirty() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - assertTrue(registration.isDirty()); - } - - @Test - public void lateUpdateOfModifiersDirtiesRegistration() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - clientResponse(); - - assertFalse(registration.isDirty()); - - registration.withModifiers(KeyModifier.ALT); - - assertTrue(registration.isDirty()); - assertEquals(1, registration.getModifiers().size()); - } - - @Test - public void fluentModifiersAreAddedCorrectly() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - registration.withAlt().withCtrl().withMeta().withShift(); - - assertEquals(4, registration.getModifiers().size()); - } - - @Test - public void preventDefaultAndStopPropagationValuesDefaultToTrue() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - assertFalse(registration.isBrowserDefaultAllowed()); - assertFalse(registration.isEventPropagationAllowed()); - - registration.allowBrowserDefault().allowEventPropagation(); - - assertTrue(registration.isBrowserDefaultAllowed()); - assertTrue(registration.isEventPropagationAllowed()); - } - - @Test - public void bindLifecycleToChangesLifecycleOwner() { - Component newOwner = mock(Component.class); - - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - assertEquals(lifecycleOwner, registration.getLifecycleOwner()); - - registration.bindLifecycleTo(newOwner); - - assertEquals(newOwner, registration.getLifecycleOwner()); - - } - - @Test - public void settersAndGettersChangeValuesCorrectly() { - - // Component listenOn = mock(Component.class); - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - registration.setBrowserDefaultAllowed(true); - registration.setEventPropagationAllowed(true); - - clientResponse(); - - assertTrue("Allow default was not set to true", - registration.isBrowserDefaultAllowed()); - assertTrue("Allow propagation was not set to true", - registration.isBrowserDefaultAllowed()); - - registration.setBrowserDefaultAllowed(false); - registration.setEventPropagationAllowed(false); - - clientResponse(); - - assertFalse("Allow default was not set to false", - registration.isBrowserDefaultAllowed()); - assertFalse("Allow propagation was not set to false", - registration.isEventPropagationAllowed()); - } - - @Test - public void listenOnChangesTheComponentThatOwnsTheListener() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - for (Component component : listenOn) { - when(component.addDetachListener(Mockito.any())) - .thenReturn(mock(Registration.class)); - } - clientResponse(); - - // listenOn component should be set after client response - assertEquals(listenOn[0], registration.getOwner()); - assertArrayEquals(listenOn, registration.getOwners()); - - // Change the listenOn component - Component[] newListenOn = new Component[2]; - Arrays.setAll(newListenOn, i -> mock(Component.class)); - for (Component component : newListenOn) - when(component.getUI()).thenReturn(Optional.of(ui)); - registration.listenOn(newListenOn); - - clientResponse(newListenOn); - - // listenOn component should be set to the new component - assertEquals(newListenOn[0], registration.getOwner()); - assertArrayEquals(newListenOn, registration.getOwners()); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Test - public void listenOnComponentIsChanged_eventIsPopulatedForANewListenOnComponent() { - UI ui = Mockito.spy(UI.class); - Component owner = new FakeComponent(); - Component initialComponentToListenOn = new FakeComponent(); - - Component[] components = new Component[] { initialComponentToListenOn }; - - ui.add(owner); - ui.add(initialComponentToListenOn); - new ShortcutRegistration(owner, () -> components, event -> { - }, Key.KEY_A); - - ArgumentCaptor captor = ArgumentCaptor - .forClass(SerializableConsumer.class); - - verify(ui, atLeastOnce()).beforeClientResponse(eq(owner), - captor.capture()); - - SerializableConsumer consumer = captor.getValue(); - - // Fake beforeClientExecution call. - consumer.accept(mock(ExecutionContext.class)); - - // Once the shortcut listener is registered the expression should - // contain KeyA - Assert.assertTrue( - hasKeyAInKeyDownExpression(initialComponentToListenOn)); - - Component replacementComponentToListenOn = new FakeComponent(); - components[0] = replacementComponentToListenOn; - ui.add(components[0]); - // detach the original "listen on" component: the new one replaces the - // old one - ui.remove(initialComponentToListenOn); - - // now re-attach the owner - ui.remove(owner); - - ui.add(owner); - - consumer.accept(mock(ExecutionContext.class)); - // the new component should now also have expression with KeyA - Assert.assertTrue( - hasKeyAInKeyDownExpression(replacementComponentToListenOn)); - } - - @Test - public void listenOnUIIsClosing_eventIsPopulatedForANewUI() { - UI ui = Mockito.spy(UI.class); - Component owner = new FakeComponent(); - - Component[] components = new Component[] { ui }; - - ui.add(owner); - new ShortcutRegistration(owner, () -> components, event -> { - }, Key.KEY_A); - - UI newUI = Mockito.spy(UI.class); - // close the previous UI - ui.close(); - components[0] = newUI; - - owner.getElement().removeFromTree(); - newUI.add(owner); - - ArgumentCaptor captor = ArgumentCaptor - .forClass(SerializableConsumer.class); - - verify(ui, atLeastOnce()).beforeClientResponse(eq(owner), - captor.capture()); - - SerializableConsumer consumer = captor.getValue(); - - // Fake beforeClientExecution call. - consumer.accept(mock(ExecutionContext.class)); - // the new UI should now also have expression with KeyA - Assert.assertTrue(hasKeyAInKeyDownExpression(newUI)); - } - - @Test - public void shortcutRegistrationReturnedByClickNotifierHasCorrectDefault() { - FakeComponent fakeComponent = new FakeComponent(); - - ShortcutRegistration registration = fakeComponent - .addClickShortcut(Key.KEY_A); - - assertTrue("Allows default was not true", - registration.isBrowserDefaultAllowed()); - - assertFalse("Allows propagation was not false", - registration.isEventPropagationAllowed()); - } - - @Test - public void shortcutRegistrationReturnedByFocusableHasCorrectDefaults() { - FakeComponent fakeComponent = new FakeComponent(); - - ShortcutRegistration registration = fakeComponent - .addFocusShortcut(Key.KEY_A); - - assertFalse("Allows default was not false", - registration.isBrowserDefaultAllowed()); - - assertFalse("Allows propagation was not false", - registration.isEventPropagationAllowed()); - } - - @Test - public void listenOnWithDuplicateShouldThrowException() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - exceptionRule.expect(IllegalArgumentException.class); - exceptionRule.expectMessage( - ShortcutRegistration.LISTEN_ON_COMPONENTS_SHOULD_NOT_HAVE_DUPLICATE_ENTRIES); - registration.listenOn(listenOn[0], listenOn[1], listenOn[1]); - } - - @Test - public void listenOnWithNullEntriesShouldThrowException() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - exceptionRule.expect(IllegalArgumentException.class); - exceptionRule.expectMessage( - ShortcutRegistration.LISTEN_ON_COMPONENTS_SHOULD_NOT_CONTAIN_NULL); - registration.listenOn(listenOn[0], null, listenOn[1]); - } - - @Test - public void listenOnItemsAreChangedAfterCallingListenOnShouldNotHaveAnyEffect() { - ShortcutRegistration registration = new ShortcutRegistration( - lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - Component[] newListenOn = new Component[] { listenOn[0], listenOn[1] }; - registration.listenOn(newListenOn); - newListenOn[0] = null; - newListenOn[1] = null; - - clientResponse(); - - assertTrue(registration.isShortcutActive()); - } - - @Test - public void listenOnComponentHasElementLocatorJs_jsExecutionScheduled() { - final ElementLocatorTestFixture fixture = new ElementLocatorTestFixture(); - final Key key = Key.KEY_A; - fixture.createNewShortcut(key); - - List pendingJavaScriptInvocations = fixture - .writeResponse(); - - final PendingJavaScriptInvocation js = pendingJavaScriptInvocations - .get(0); - final String expression = js.getInvocation().getExpression(); - Assert.assertTrue( - "element locator string " + fixture.elementLocatorJs - + " missing from JS execution string " + expression, - expression.contains( - "const delegate=" + fixture.elementLocatorJs + ";")); - Assert.assertTrue( - "JS execution string should have event.preventDefault() in it" - + expression, - expression.contains("event.preventDefault();")); - Assert.assertTrue( - "JS execution string should always have event.stopPropagation() in it" - + expression, - expression.contains("event.stopPropagation();")); - Assert.assertTrue("JS execution string missing the key" + key, - expression.contains(key.getKeys().get(0))); - - fixture.registration.remove(); - - fixture.createNewShortcut(Key.KEY_X); - - pendingJavaScriptInvocations = fixture.writeResponse(); - Assert.assertEquals(0, pendingJavaScriptInvocations.size()); - } - - @Test - public void listenOnComponentHasElementLocatorJs_allowBrowserDefault_JsExecutionDoesNotPreventDefault() { - final ElementLocatorTestFixture fixture = new ElementLocatorTestFixture(); - final Key key = Key.KEY_A; - fixture.createNewShortcut(key).allowBrowserDefault(); - - List pendingJavaScriptInvocations = fixture - .writeResponse(); - - final PendingJavaScriptInvocation js = pendingJavaScriptInvocations - .get(0); - final String expression = js.getInvocation().getExpression(); - Assert.assertFalse( - "JS execution string should NOT have event.preventDefault() in it" - + expression, - expression.contains("event.preventDefault();")); - } - - @Test - public void constructedRegistration_lifecycleIsVisibleAndEnabled_shorcutEventIsFired() { - AtomicReference event = new AtomicReference<>(); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, event::set, - Key.KEY_A); - - mockLifecycle(true); - - clientResponse(); - - listenOn[0].getEventBus() - .fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString())); - - Assert.assertNotNull(event.get()); - } - - @Test - public void constructedRegistration_lifecycleOnwerIsDisabled_shorcutEventIsNotFired() { - AtomicReference event = new AtomicReference<>(); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, event::set, - Key.KEY_A); - - Element element = mockLifecycle(true); - element.setEnabled(false); - - clientResponse(); - - listenOn[0].getEventBus() - .fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString())); - - Assert.assertNull(event.get()); - } - - @Test - public void constructedRegistration_lifecycleOnwerIsInvisible_shorcutEventIsNotFired() { - AtomicReference event = new AtomicReference<>(); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, event::set, - Key.KEY_A); - - mockLifecycle(false); - - clientResponse(); - - listenOn[0].getEventBus() - .fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString())); - - Assert.assertNull(event.get()); - } - - @Test - public void constructedRegistration_lifecycleOnwerAncestorsAreVisible_shorcutEventIsFired() { - AtomicReference event = new AtomicReference<>(); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, event::set, - Key.KEY_A); - - mockLifecycle(true); - Mockito.when(lifecycleOwner.getParent()) - .thenReturn(Optional.of(new FakeComponent())); - - clientResponse(); - - listenOn[0].getEventBus() - .fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString())); - - Assert.assertNotNull(event.get()); - } - - @Test - public void uiRegistration_uiHasModalComponent_eventIsSentFromModalComponentInsteadOfUi() { - AtomicReference eventRef = new AtomicReference<>(); - - Component modal = Mockito.mock(Component.class); - when(modal.getUI()).thenReturn(Optional.of(ui)); - when(modal.getEventBus()).thenReturn(new ComponentEventBus(modal)); - when(modal.getElement()).thenReturn(new Element("tag")); - when(modal.isVisible()).thenReturn(true); - - UIInternals uiInternals = Mockito.mock(UIInternals.class); - Mockito.when(uiInternals.hasModalComponent()).thenReturn(true); - Mockito.when(uiInternals.getActiveModalComponent()).thenReturn(modal); - Mockito.when(ui.getInternals()).thenReturn(uiInternals); - - listenOn = new Component[] { ui }; - when(ui.getUI()).thenReturn(Optional.of(ui)); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, eventRef::set, - Key.KEY_A); - - mockLifecycle(true); - Mockito.when(lifecycleOwner.getParent()).thenReturn(Optional.of(modal)); - - clientResponse(listenOn); - - modal.getEventBus() - .fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString())); - - ShortcutEvent event = eventRef.get(); - Assert.assertNotNull(event); - Assert.assertEquals(modal, event.getSource()); - } - - @Test - public void constructedRegistration_lifecycleOnwerHasInvisibleParent_shorcutEventIsNotFired() { - AtomicReference event = new AtomicReference<>(); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, event::set, - Key.KEY_A); - - mockLifecycle(true); - - FakeComponent component = new FakeComponent(); - component.setVisible(false); - Mockito.when(lifecycleOwner.getParent()) - .thenReturn(Optional.of(component)); - - clientResponse(); - - listenOn[0].getEventBus() - .fireEvent(new KeyDownEvent(listenOn[0], Key.KEY_A.toString())); - - Assert.assertNull(event.get()); - } - - @Test - public void constructedRegistration_lifeCycleOwnerIsDetached_detachListenerIsDeregisteredFromListenOnComponents() { - AtomicReference detachListener = new AtomicReference<>(); - Mockito.doAnswer(invocaation -> { - detachListener.set( - invocaation.getArgument(0, ComponentEventListener.class)); - return mock(Registration.class); - }).when(lifecycleOwner).addDetachListener(any()); - - new ShortcutRegistration(lifecycleOwner, () -> listenOn, event -> { - }, Key.KEY_A); - - Registration registration = Mockito.mock(Registration.class); - for (Component component : listenOn) { - Mockito.when(component.addDetachListener(Mockito.any())) - .thenReturn(registration); - } - - clientResponse(); - - detachListener.get().onComponentEvent(new DetachEvent(lifecycleOwner)); - - Mockito.verify(registration, Mockito.times(3)).remove(); - } - - @Test - public void reattachComponent_detachListenerIsAddedOnEveryAttach_listenOnUIIsClosing_eventIsPopulatedForANewUI() { - UI ui = Mockito.spy(UI.class); - Component owner = new FakeComponent(); - - Registration registration = Mockito.mock(Registration.class); - AtomicInteger count = new AtomicInteger(); - Mockito.when(ui.addDetachListener(any())).thenAnswer(invocation -> { - count.incrementAndGet(); - return registration; - }); - - Component[] components = new Component[] { ui }; - - ui.add(owner); - new ShortcutRegistration(owner, () -> components, event -> { - }, Key.KEY_A); - - ArgumentCaptor captor = ArgumentCaptor - .forClass(SerializableConsumer.class); - verify(ui, atLeastOnce()).beforeClientResponse(eq(owner), - captor.capture()); - - SerializableConsumer consumer = captor.getValue(); - - // Fake beforeClientExecution call. - consumer.accept(mock(ExecutionContext.class)); - Assert.assertEquals(1, count.get()); - - ui.remove(owner); - - // reattach - ui.add(owner); - - // Fake beforeClientExecution call. - consumer.accept(mock(ExecutionContext.class)); - Assert.assertEquals(2, count.get()); - - UI newUI = Mockito.spy(UI.class); - // close the previous UI - ui.close(); - components[0] = newUI; - - owner.getElement().removeFromTree(); - newUI.add(owner); - - verify(newUI, atLeastOnce()).beforeClientResponse(eq(owner), - captor.capture()); - // Fake beforeClientExecution call. - captor.getValue().accept(mock(ExecutionContext.class)); - - // the new UI should now also have expression with KeyA - Assert.assertTrue(hasKeyAInKeyDownExpression(newUI)); - } - - private Element mockLifecycle(boolean visible) { - Mockito.when(lifecycleOwner.isVisible()).thenReturn(visible); - Element element = ElementFactory.createAnchor(); - Mockito.when(lifecycleOwner.getElement()).thenReturn(element); - return element; - } - - class ElementLocatorTestFixture { - - final Registration registration; - final Component owner; - private final String elementLocatorJs; - private final Component[] components; - private final UI ui; - - ElementLocatorTestFixture() { - VaadinSession session = Mockito.mock(VaadinSession.class); - Mockito.when(session.hasLock()).thenReturn(true); - ui = Mockito.spy(UI.class); - ui.getInternals().setSession(session); - - owner = new FakeComponent(); - Component initialComponentToListenOn = new FakeComponent(); - components = new Component[] { initialComponentToListenOn }; - - ui.add(owner); - ui.add(initialComponentToListenOn); - - elementLocatorJs = "foobar"; - registration = Shortcuts.setShortcutListenOnElement( - elementLocatorJs, initialComponentToListenOn); - } - - List writeResponse() { - ui.getInternals().getStateTree() - .runExecutionsBeforeClientResponse(); - - return ui.getInternals().dumpPendingJavaScriptInvocations(); - } - - ShortcutRegistration createNewShortcut(Key key) { - return new ShortcutRegistration(owner, () -> components, event -> { - }, key); - } - - } - - /** - * Works only with the {@code registration} member variable. - * - * Simulates a "beforeClientResponse" callback for the given - * {@link ShortcutRegistration} - */ - private void clientResponse() { - clientResponse(listenOn); - } - - /** - * Works only with the {@code registration} member variable, but allows - * configuring the {@code listenOn} component - * - * Simulates a "beforeClientResponse" callback for the given - * {@link ShortcutRegistration} - */ - private void clientResponse(Component[] listenOnMock) { - for (Component component : listenOnMock) { - when(component.getElement()).thenReturn(new Element("tag")); - when(component.getEventBus()) - .thenReturn(new ComponentEventBus(component)); - } - - ArgumentCaptor captor = ArgumentCaptor - .forClass(SerializableConsumer.class); - - verify(ui, atLeastOnce()).beforeClientResponse(eq(lifecycleOwner), - captor.capture()); - - SerializableConsumer consumer = captor.getValue(); - - // Fake beforeClientExecution call. - consumer.accept(mock(ExecutionContext.class)); - } - - private boolean hasKeyAInKeyDownExpression(Component component) { - ElementListenerMap map = component.getElement().getNode() - .getFeature(ElementListenerMap.class); - - // Once the shortcut listener is registered the expression should - // contain KeyA - boolean hasKeyA = false; - for (String expression : map.getExpressions("keydown")) { - if (expression.contains(Key.KEY_A.getKeys().get(0))) { - hasKeyA = true; - } - } - return hasKeyA; - } - - @Tag("imaginary-tag") - private class FakeComponent extends Component - implements ClickNotifier, Focusable { - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ShortcutsTest.java b/flow-server/src/test/java/com/vaadin/flow/component/ShortcutsTest.java deleted file mode 100644 index 6b62ae2f749..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ShortcutsTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.router.RouterLink; -import com.vaadin.flow.shared.Registration; - -public class ShortcutsTest { - - @Test - public void hasOnlyStaticMethods() { - Method[] methods = Shortcuts.class.getDeclaredMethods(); - - for (Method method : methods) { - if (!Modifier.isStatic(method.getModifiers())) { - Assert.fail(String.format("Method %s(%s) should be static", - method.getName(), - Stream.of(method.getParameterTypes()) - .map(Class::getSimpleName) - .collect(Collectors.joining(", ")))); - } - } - } - - @Test - public void setShortcutListenOnElementLocatorJs_storesLocatorOnComponentData() { - final RouterLink routerLink = new RouterLink(); - final String locator = "foobar"; - final Registration registration = Shortcuts - .setShortcutListenOnElement(locator, routerLink); - - Assert.assertEquals(locator, ComponentUtil.getData(routerLink, - Shortcuts.ELEMENT_LOCATOR_JS_KEY)); - - registration.remove(); - - Assert.assertNull(ComponentUtil.getData(routerLink, - Shortcuts.ELEMENT_LOCATOR_JS_KEY)); - } - - @Test - public void setShortcutListenOnElementLocatorJs_registrationDoesNotRemoveModifiedData_nullClearsAlways() { - final RouterLink routerLink = new RouterLink(); - final String locator = "foobar"; - final Registration registration = Shortcuts - .setShortcutListenOnElement(locator, routerLink); - - Assert.assertEquals(locator, ComponentUtil.getData(routerLink, - Shortcuts.ELEMENT_LOCATOR_JS_KEY)); - - Shortcuts.setShortcutListenOnElement("another", routerLink); - - registration.remove(); - - Assert.assertEquals("another", ComponentUtil.getData(routerLink, - Shortcuts.ELEMENT_LOCATOR_JS_KEY)); - - final Registration nullRegistration = Shortcuts - .setShortcutListenOnElement(null, routerLink); - - Assert.assertNull(ComponentUtil.getData(routerLink, - Shortcuts.ELEMENT_LOCATOR_JS_KEY)); - - nullRegistration.remove(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/TestComponentWithDomEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/TestComponentWithDomEvent.java deleted file mode 100644 index 12df7bead73..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/TestComponentWithDomEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import com.vaadin.flow.component.ComponentTest.TestComponent; - -public class TestComponentWithDomEvent extends TestComponent { - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/TestComponentWithServerEvent.java b/flow-server/src/test/java/com/vaadin/flow/component/TestComponentWithServerEvent.java deleted file mode 100644 index ca807610c68..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/TestComponentWithServerEvent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import com.vaadin.flow.component.ComponentTest.TestComponent; -import com.vaadin.flow.shared.Registration; - -public class TestComponentWithServerEvent extends TestComponent { - public Registration addServerEventListener( - ComponentEventListener listener) { - return super.addListener(ServerEvent.class, listener); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/TextTest.java b/flow-server/src/test/java/com/vaadin/flow/component/TextTest.java deleted file mode 100644 index 57e27930157..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/TextTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TextTest { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Test - public void elementAttached() { - // This will throw an assertion error if the element is not attached to - // the component - new Text("Foo").getParent(); - } - - @Test - public void nullText_transformsToEmptyAndDoesNotThrowException() { - Assert.assertEquals("", new Text(null).getText()); - } - - @Test - public void emptyText() { - Assert.assertEquals("", new Text("").getText()); - } - - @Test - public void setText_emptyTextCanBeChangedLater() { - Text text = new Text(null); - text.setText("Non Empty"); - Assert.assertEquals("Non Empty", text.getText()); - } - - @Test - public void setText_nullIsChangedToEmptyAndDoesNotThrowException() { - Text text = new Text("Default"); - text.setText(null); - Assert.assertEquals("", text.getText()); - } - - @Test - public void setGetText() { - Assert.assertEquals("Simple", new Text("Simple").getText()); - Assert.assertEquals("åäö €#%°#", new Text("åäö €#%°#").getText()); - } - - @Test - public void setId_throwsWithMeaningfulMessage() { - assertExceptionOnSetProperty("id"); - - new Text("").setId("foo"); - } - - @Test - public void setFooProperty_throwsWithMeaningfulMessage() { - assertExceptionOnSetProperty("foo"); - - new Text("").set(PropertyDescriptors.propertyWithDefault("foo", true), - false); - } - - @Test - public void setVisibility_throwsWithMeaningfulMessage() { - exception.expect(UnsupportedOperationException.class); - - exception.expectMessage(CoreMatchers.allOf( - CoreMatchers.containsString( - "Cannot change Text component visibility"), - CoreMatchers.containsString( - "because it doesn't represent an HTML Element"))); - - new Text("").setVisible(false); - } - - private void assertExceptionOnSetProperty(String property) { - exception.expect(UnsupportedOperationException.class); - - exception.expectMessage(CoreMatchers.allOf( - CoreMatchers.containsString("Cannot set '" + property + "' "), - CoreMatchers.containsString( - "component because it doesn't represent an HTML Element"))); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/UITest.java b/flow-server/src/test/java/com/vaadin/flow/component/UITest.java deleted file mode 100644 index 082f1dfc806..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/UITest.java +++ /dev/null @@ -1,1512 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; -import org.slf4j.Logger; - -import com.vaadin.flow.component.internal.PendingJavaScriptInvocation; -import com.vaadin.flow.component.page.History; -import com.vaadin.flow.component.page.History.HistoryStateChangeEvent; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementDetachEvent; -import com.vaadin.flow.dom.Node; -import com.vaadin.flow.dom.NodeVisitor; -import com.vaadin.flow.dom.impl.AbstractTextElementStateProvider; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.function.SerializableConsumer; -import com.vaadin.flow.function.SerializableRunnable; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.router.AfterNavigationEvent; -import com.vaadin.flow.router.AfterNavigationListener; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.BeforeEnterListener; -import com.vaadin.flow.router.BeforeEvent; -import com.vaadin.flow.router.BeforeLeaveEvent; -import com.vaadin.flow.router.BeforeLeaveListener; -import com.vaadin.flow.router.HasUrlParameter; -import com.vaadin.flow.router.ListenerPriority; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.NavigationTrigger; -import com.vaadin.flow.router.NotFoundException; -import com.vaadin.flow.router.QueryParameters; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RouteNotFoundError; -import com.vaadin.flow.router.RouteParam; -import com.vaadin.flow.router.RouteParameters; -import com.vaadin.flow.router.RoutePrefix; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.internal.AfterNavigationHandler; -import com.vaadin.flow.router.internal.BeforeEnterHandler; -import com.vaadin.flow.router.internal.BeforeLeaveHandler; -import com.vaadin.flow.server.BootstrapHandlerTest; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.frontend.MockLogger; -import com.vaadin.flow.shared.Registration; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; -import com.vaadin.tests.util.MockUI; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -public class UITest { - - @Route("") - @Tag(Tag.DIV) - public static class RootNavigationTarget extends Component { - - } - - @Route("foo/bar") - @Tag(Tag.DIV) - public static class FooBarNavigationTarget extends Component { - - } - - @Route(value = ":barParam/bar", layout = FooBarParamParentNavigationTarget.class) - @Tag(Tag.DIV) - public static class FooBarParamNavigationTarget extends Component { - - } - - @RoutePrefix("foo/:fooParam") - @Tag(Tag.DIV) - public static class FooBarParamParentNavigationTarget extends Component - implements RouterLayout { - - } - - @Route("foo-bar") - @Tag(Tag.DIV) - public static class Parameterized extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - - } - - @Tag(Tag.DIV) - public static class ParameterizedNotRoute extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, Integer parameter) { - } - - } - - private static class AttachableComponent extends Component { - public AttachableComponent() { - super(new Element("div")); - } - } - - private static class AttachedElementStateProvider - extends AbstractTextElementStateProvider { - - @Override - public boolean supports(StateNode node) { - return true; - } - - @Override - public Node getParent(StateNode node) { - return null; - } - - @Override - public String getTextContent(StateNode node) { - return null; - } - - @Override - public void setTextContent(StateNode node, String textContent) { - } - - @Override - public void visit(StateNode node, NodeVisitor visitor) { - } - } - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - @Test - public void elementIsBody() { - UI ui = new UI(); - - assertEquals("body", ui.getElement().getTag()); - } - - private static UI createTestUI() { - MockLogger mockLogger = new MockLogger(); - UI ui = new UI() { - @Override - public void doInit(VaadinRequest request, int uiId) { - - } - - @Override - Logger getLogger() { - return mockLogger; - } - }; - - return ui; - } - - private static MockUI createAccessableTestUI() { - // Needs a service to be able to do service.accessSession - return new MockUI( - new MockVaadinSession(new MockVaadinServletService())); - } - - private static void initUI(UI ui, String initialLocation, - ArgumentCaptor statusCodeCaptor) - throws InvalidRouteConfigurationException { - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - VaadinResponse response = Mockito.mock(VaadinResponse.class); - - String pathInfo; - if (initialLocation.isEmpty()) { - pathInfo = null; - } else { - Assert.assertFalse(initialLocation.startsWith("/")); - pathInfo = "/" + initialLocation; - } - Mockito.when(request.getPathInfo()).thenReturn(pathInfo); - - VaadinService service = new MockVaadinServletService() { - @Override - public VaadinContext getContext() { - return new MockVaadinContext(); - } - }; - service.setCurrentInstances(request, response); - - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - - DeploymentConfiguration config = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(config.isProductionMode()).thenReturn(false); - - session.lock(); - session.setConfiguration(config); - - ui.getInternals().setSession(session); - - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(ui.getInternals().getRouter().getRegistry()); - - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - Arrays.asList(RootNavigationTarget.class, - FooBarNavigationTarget.class, Parameterized.class, - FooBarParamNavigationTarget.class) - .forEach(routeConfiguration::setAnnotatedRoute); - }); - - ui.doInit(request, 0); - ui.getInternals().getRouter().initializeUI(ui, - BootstrapHandlerTest.requestToLocation(request)); - - session.unlock(); - - if (statusCodeCaptor != null) { - Mockito.verify(response).setStatus(statusCodeCaptor.capture()); - } - } - - @Test - public void scrollAttribute() { - UI ui = new UI(); - Assert.assertNull( - "'scroll' attribute shouldn't be set for the " - + "UI element which represents 'body' tag", - ui.getElement().getAttribute("scroll")); - } - - @Test - public void testInitialLocation() - throws InvalidRouteConfigurationException { - UI ui = new UI(); - initUI(ui, "", null); - - assertEquals("", ui.getInternals().getActiveViewLocation().getPath()); - } - - @Test - public void locationAfterServerNavigation() - throws InvalidRouteConfigurationException { - UI ui = new UI(); - initUI(ui, "", null); - - ui.navigate("foo/bar"); - - assertEquals("foo/bar", - ui.getInternals().getActiveViewLocation().getPath()); - List chain = ui.getInternals() - .getActiveRouterTargetsChain(); - Assert.assertEquals(1, chain.size()); - MatcherAssert.assertThat(chain.get(0), - CoreMatchers.instanceOf(FooBarNavigationTarget.class)); - } - - @Test - public void navigateWithParameters_delegateToRouter() { - final String route = "params"; - Router router = Mockito.mock(Router.class); - UI ui = new MockUI(router); - - QueryParameters params = QueryParameters - .simple(Collections.singletonMap("test", "indeed")); - - ArgumentCaptor location = ArgumentCaptor - .forClass(Location.class); - - ui.navigate(route, params); - - Mockito.verify(router).navigate(ArgumentMatchers.eq(ui), - location.capture(), - ArgumentMatchers.eq(NavigationTrigger.UI_NAVIGATE)); - - Location value = location.getValue(); - Assert.assertEquals(route, value.getPath()); - Assert.assertEquals(params, value.getQueryParameters()); - } - - @Test - public void navigateWithParameters_afterServerNavigation() - throws InvalidRouteConfigurationException { - UI ui = new UI(); - initUI(ui, "", null); - - Optional newView = ui.navigate( - FooBarParamNavigationTarget.class, - new RouteParameters(new RouteParam("fooParam", "flu"), - new RouteParam("barParam", "beer"))); - - assertEquals(FooBarParamNavigationTarget.class, - newView.get().getClass()); - - assertEquals("foo/flu/beer/bar", - ui.getInternals().getActiveViewLocation().getPath()); - List chain = ui.getInternals() - .getActiveRouterTargetsChain(); - Assert.assertEquals(2, chain.size()); - MatcherAssert.assertThat(chain.get(0), - CoreMatchers.instanceOf(FooBarParamNavigationTarget.class)); - MatcherAssert.assertThat(chain.get(1), CoreMatchers - .instanceOf(FooBarParamParentNavigationTarget.class)); - } - - @Test - public void localeSet_directionUpdated() { - MockUI ui = new MockUI(); - - ui.setDirection(Direction.RIGHT_TO_LEFT); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - List pendingJavaScriptInvocations = ui - .dumpPendingJsInvocations(); - - Assert.assertEquals(1, pendingJavaScriptInvocations.size()); - Assert.assertEquals("rtl", pendingJavaScriptInvocations.get(0) - .getInvocation().getParameters().get(0)); - } - - @Test - public void locationAfterClientNavigation() - throws InvalidRouteConfigurationException { - UI ui = new UI(); - initUI(ui, "", null); - - History history = ui.getPage().getHistory(); - - history.getHistoryStateChangeHandler() - .onHistoryStateChange(new HistoryStateChangeEvent(history, null, - new Location("foo/bar"), NavigationTrigger.HISTORY)); - - assertEquals("foo/bar", - ui.getInternals().getActiveViewLocation().getPath()); - } - - @Test - public void noRouteMatches_404ViewAndCodeReturned() - throws InvalidRouteConfigurationException { - UI ui = new UI(); - - ArgumentCaptor statusCodeCaptor = ArgumentCaptor - .forClass(Integer.class); - - initUI(ui, "baz", statusCodeCaptor); - - Assert.assertEquals(1, ui.getChildren().count()); - Optional errorComponent = ui.getChildren().findFirst(); - MatcherAssert.assertThat(errorComponent.get(), - CoreMatchers.instanceOf(RouteNotFoundError.class)); - assertEquals(Integer.valueOf(404), statusCodeCaptor.getValue()); - } - - @Test - public void addComponent() { - UI ui = new UI(); - Text text = new Text("foo"); - ui.add(text); - ComponentTest.assertChildren(ui, text); - } - - @Test - public void addComponents() { - UI ui = new UI(); - Text text = new Text("foo"); - Html html = new Html("
foobar
"); - ui.add(text, html); - ComponentTest.assertChildren(ui, text, html); - } - - @Test - public void removeComponent() { - UI ui = new UI(); - Text text = new Text("foo"); - ui.add(text); - ui.remove(text); - - ComponentTest.assertChildren(ui); - } - - @Test - public void setLastHeartbeatTimestamp_heartbeatEventIsFired() { - UI ui = new UI(); - initUI(ui, "", null); - - long heartbeatTimestamp = System.currentTimeMillis(); - List events = new ArrayList<>(); - ui.addHeartbeatListener(events::add); - - ui.getInternals().setLastHeartbeatTimestamp(heartbeatTimestamp); - - assertEquals(1, events.size()); - assertEquals(ui, events.get(0).getSource()); - assertEquals(heartbeatTimestamp, events.get(0).getHeartbeatTime()); - } - - @Test - public void setLastHeartbeatTimestamp_multipleHeartbeatListenerRegistered_eachHeartbeatListenerIsCalled() { - UI ui = new UI(); - initUI(ui, "", null); - - List events = new ArrayList<>(); - ui.addHeartbeatListener(events::add); - ui.addHeartbeatListener(events::add); - - ui.getInternals().setLastHeartbeatTimestamp(System.currentTimeMillis()); - - assertEquals(2, events.size()); - } - - @Test - public void setLastHeartbeatTimestamp_heartbeatListenerRemoved_listenerNotRun() { - UI ui = new UI(); - initUI(ui, "", null); - - AtomicReference reference = new AtomicReference<>(); - AtomicInteger runCount = new AtomicInteger(); - - Registration registration = ui.addHeartbeatListener(event -> { - runCount.incrementAndGet(); - reference.get().remove(); // removes the listener on the first - // invocation - }); - reference.set(registration); - - ui.getInternals().setLastHeartbeatTimestamp(System.currentTimeMillis()); - assertEquals("Listener should have been run once", 1, runCount.get()); - - ui.getInternals().setLastHeartbeatTimestamp(System.currentTimeMillis()); - assertEquals( - "Listener should not have been run again since it was removed", - 1, runCount.get()); - } - - @Test - public void setSession_attachEventIsFired() - throws InvalidRouteConfigurationException { - UI ui = new UI(); - List events = new ArrayList<>(); - ui.addAttachListener(events::add); - initUI(ui, "", null); - - assertEquals(1, events.size()); - assertEquals(ui, events.get(0).getSource()); - } - - @Test - public void unsetSession_detachEventIsFired() - throws InvalidRouteConfigurationException { - UI ui = createTestUI(); - List events = new ArrayList<>(); - ui.addDetachListener(events::add); - initUI(ui, "", null); - - ui.getSession().access(() -> ui.getInternals().setSession(null)); - - // Unlock to run pending access tasks - ui.getSession().unlock(); - - assertEquals(1, events.size()); - assertEquals(ui, events.get(0).getSource()); - } - - @Test - public void unsetSession_detachEventIsFiredForUIChildren() - throws InvalidRouteConfigurationException { - UI ui = createTestUI(); - List events = new ArrayList<>(); - initUI(ui, "", null); - - Component childComponent = new AttachableComponent(); - ui.add(childComponent); - childComponent.addDetachListener(events::add); - - ui.getSession().access(() -> ui.getInternals().setSession(null)); - - // Unlock to run pending access tasks - ui.getSession().unlock(); - - assertEquals(1, events.size()); - assertEquals(childComponent, events.get(0).getSource()); - } - - @Test - public void unsetSession_detachEventIsFiredForElements() { - UI ui = createTestUI(); - - List events = new ArrayList<>(); - - ui.getElement().addDetachListener(events::add); - initUI(ui, "", null); - - Component childComponent = new AttachableComponent(); - ui.add(childComponent); - childComponent.getElement().addDetachListener(events::add); - - ui.getSession().access(() -> ui.getInternals().setSession(null)); - - // Unlock to run pending access tasks - ui.getSession().unlock(); - - assertEquals(2, events.size()); - assertEquals(childComponent.getElement(), events.get(0).getSource()); - assertEquals(ui.getElement(), events.get(1).getSource()); - } - - @Test - public void unsetSession_accessErrorHandlerStillWorks() throws IOException { - UI ui = createTestUI(); - initUI(ui, "", null); - - ui.getSession().access(() -> ui.getInternals().setSession(null)); - ui.access(() -> { - Assert.fail("We should never get here because the UI is detached"); - }); - - // Unlock to run pending access tasks - ui.getSession().unlock(); - - String logOutput = ((MockLogger) ui.getLogger()).getLogs(); - String logOutputNoDebug = logOutput.replaceAll("^\\[Debug\\].*", ""); - - Assert.assertFalse( - "No NullPointerException should be logged but got: " - + logOutput, - logOutput.contains("NullPointerException")); - Assert.assertFalse( - "No UIDetachedException should be logged but got: " - + logOutputNoDebug, - logOutputNoDebug.contains("UIDetachedException")); - } - - @Test - public void beforeClientResponse_regularOrder() { - UI ui = createTestUI(); - Component rootComponent = new AttachableComponent(); - ui.add(rootComponent); - - List results = new ArrayList<>(); - - ui.beforeClientResponse(rootComponent, context -> results.add(0)); - ui.beforeClientResponse(rootComponent, context -> results.add(1)); - ui.beforeClientResponse(rootComponent, context -> results.add(2)); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 3 results in the list", - results.size() == 3); - - for (int i = 0; i < results.size(); i++) { - Assert.assertEquals( - "The result at index '" + i + "' should be " + i, i, - results.get(i).intValue()); - } - } - - @Test - public void beforeClientResponse_withInnerRunnables() { - UI ui = createTestUI(); - Component rootComponent = new AttachableComponent(); - ui.add(rootComponent); - - List results = new ArrayList<>(); - - ui.beforeClientResponse(rootComponent, context -> results.add(0)); - ui.beforeClientResponse(rootComponent, context -> { - results.add(1); - ui.beforeClientResponse(rootComponent, context2 -> results.add(3)); - ui.beforeClientResponse(rootComponent, context2 -> results.add(4)); - }); - ui.beforeClientResponse(rootComponent, context -> results.add(2)); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 5 results in the list", - results.size() == 5); - - for (int i = 0; i < results.size(); i++) { - Assert.assertEquals( - "The result at index '" + i + "' should be " + i, i, - results.get(i).intValue()); - } - } - - @Test - public void beforeClientResponse_withUnattachedNodes() { - UI ui = createTestUI(); - Component rootComponent = new AttachableComponent(); - ui.add(rootComponent); - Component emptyComponent = new AttachableComponent(); - - List results = new ArrayList<>(); - - ui.beforeClientResponse(emptyComponent, context -> results.add(0)); - ui.beforeClientResponse(rootComponent, context -> results.add(1)); - ui.beforeClientResponse(emptyComponent, context -> results.add(2)); - ui.beforeClientResponse(rootComponent, context -> results.add(3)); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 2 results in the list", - results.size() == 2); - - Assert.assertEquals("The result at index '0' should be " + 1, 1, - results.get(0).intValue()); - Assert.assertEquals("The result at index '1' should be " + 3, 3, - results.get(1).intValue()); - } - - @Test - public void beforeClientResponse_withAttachedNodesDuringExecution() { - UI ui = createTestUI(); - Component rootComponent = new AttachableComponent(); - ui.add(rootComponent); - AttachableComponent emptyComponent1 = new AttachableComponent(); - AttachableComponent emptyComponent2 = new AttachableComponent(); - - List results = new ArrayList<>(); - - ui.beforeClientResponse(emptyComponent1, context -> { - results.add(0); - ui.add(emptyComponent2); - }); - ui.beforeClientResponse(rootComponent, context -> { - results.add(1); - ui.add(emptyComponent1); - }); - ui.beforeClientResponse(emptyComponent2, context -> results.add(2)); - ui.beforeClientResponse(rootComponent, context -> results.add(3)); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 4 results in the list", - results.size() == 4); - - Assert.assertEquals("The result at index '0' should be 1", 1, - results.get(0).intValue()); - Assert.assertEquals("The result at index '1' should be 3", 3, - results.get(1).intValue()); - Assert.assertEquals("The result at index '2' should be 0", 0, - results.get(2).intValue()); - Assert.assertEquals("The result at index '3' should be 2", 2, - results.get(3).intValue()); - } - - @Test - public void beforeClientResponse_withReattachedNodes() { - UI ui = createTestUI(); - Component root = new AttachableComponent(); - ui.add(root); - ui.getInternals().getStateTree().collectChanges(change -> { - }); - AttachableComponent leaf = new AttachableComponent(); - ui.add(leaf); - - AtomicInteger callCounter = new AtomicInteger(); - - ui.beforeClientResponse(root, context -> { - Assert.assertTrue( - "Root component should be marked as 'clientSideInitialized'", - context.isClientSideInitialized()); - callCounter.incrementAndGet(); - - }); - ui.beforeClientResponse(leaf, context -> { - Assert.assertFalse( - "Leaf component should NOT be marked as 'clientSideInitialized'", - context.isClientSideInitialized()); - callCounter.incrementAndGet(); - }); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - ui.remove(root); - ui.add(root); - ui.beforeClientResponse(root, context -> { - Assert.assertTrue( - "Reattached root component (in the same request) should be marked as 'clientSideInitialized'", - context.isClientSideInitialized()); - callCounter.incrementAndGet(); - }); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - ui.remove(root); - ui.getInternals().getStateTree().collectChanges(change -> { - }); - ui.add(root); - ui.beforeClientResponse(root, context -> { - Assert.assertFalse( - "Reattached root component (in different requests) should NOT be marked as 'clientSideInitialized'", - context.isClientSideInitialized()); - callCounter.incrementAndGet(); - }); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - Assert.assertEquals("There should be 4 invocations", 4, - callCounter.get()); - } - - @Test - public void beforeClientResponse_componentNotAttachedToUi_noException() { - UI ui = createTestUI(); - Component component = new AttachableComponent(); - ui.beforeClientResponse(component, context -> { - }); - } - - @Test() - public void beforeClientResponse_componentBelongsToAnotherUI_throws() { - UI firstUI = createTestUI(); - UI anotherUI = createTestUI(); - Component component = new AttachableComponent(); - anotherUI.add(component); - - IllegalArgumentException exception = Assert.assertThrows( - IllegalArgumentException.class, - () -> firstUI.beforeClientResponse(component, context -> { - })); - - Assert.assertEquals( - "The given component doesn't belong to the UI the task to be executed on", - exception.getMessage()); - } - - @ListenerPriority(5) - private static class BeforeEnterListenerFirst - implements BeforeEnterListener { - @Override - public void beforeEnter(BeforeEnterEvent event) { - } - } - - private static class BeforeEnterListenerSecond - implements BeforeEnterListener { - @Override - public void beforeEnter(BeforeEnterEvent event) { - } - } - - @ListenerPriority(-5) - private static class BeforeEnterListenerThird - implements BeforeEnterListener { - @Override - public void beforeEnter(BeforeEnterEvent event) { - } - } - - @Test - public void before_enter_listener_priority_should_dictate_sort_order() - throws InvalidRouteConfigurationException { - UI ui = createTestUI(); - initUI(ui, "", null); - - ui.addBeforeEnterListener(new BeforeEnterListenerThird()); - ui.addBeforeEnterListener(new BeforeEnterListenerThird()); - ui.addBeforeEnterListener(new BeforeEnterListenerFirst()); - ui.addBeforeEnterListener(new BeforeEnterListenerSecond()); - - final List beforeEnterListeners = ui - .getNavigationListeners(BeforeEnterHandler.class); - - assertEquals(4, beforeEnterListeners.size()); - - assertTrue(beforeEnterListeners - .get(0) instanceof BeforeEnterListenerFirst); - assertTrue(beforeEnterListeners - .get(1) instanceof BeforeEnterListenerSecond); - assertTrue(beforeEnterListeners - .get(2) instanceof BeforeEnterListenerThird); - assertTrue(beforeEnterListeners - .get(3) instanceof BeforeEnterListenerThird); - } - - @ListenerPriority(5) - private static class BeforeLeaveListenerFirst - implements BeforeLeaveListener { - @Override - public void beforeLeave(BeforeLeaveEvent event) { - } - } - - private static class BeforeLeaveListenerSecond - implements BeforeLeaveListener { - @Override - public void beforeLeave(BeforeLeaveEvent event) { - } - } - - @ListenerPriority(-5) - private static class BeforeLeaveListenerThird - implements BeforeLeaveListener { - @Override - public void beforeLeave(BeforeLeaveEvent event) { - } - } - - @Test - public void before_Leave_listener_priority_should_dictate_sort_order() - throws InvalidRouteConfigurationException { - UI ui = createTestUI(); - initUI(ui, "", null); - - ui.addBeforeLeaveListener(new BeforeLeaveListenerFirst()); - ui.addBeforeLeaveListener(new BeforeLeaveListenerThird()); - ui.addBeforeLeaveListener(new BeforeLeaveListenerSecond()); - ui.addBeforeLeaveListener(new BeforeLeaveListenerThird()); - - final List beforeLeaveListeners = ui - .getNavigationListeners(BeforeLeaveHandler.class); - - assertEquals(4, beforeLeaveListeners.size()); - - assertTrue(beforeLeaveListeners - .get(0) instanceof BeforeLeaveListenerFirst); - assertTrue(beforeLeaveListeners - .get(1) instanceof BeforeLeaveListenerSecond); - assertTrue(beforeLeaveListeners - .get(2) instanceof BeforeLeaveListenerThird); - assertTrue(beforeLeaveListeners - .get(3) instanceof BeforeLeaveListenerThird); - } - - @ListenerPriority(5) - private static class AfterNavigationListenerFirst - implements AfterNavigationListener { - @Override - public void afterNavigation(AfterNavigationEvent event) { - } - } - - private static class AfterNavigationListenerSecond - implements AfterNavigationListener { - @Override - public void afterNavigation(AfterNavigationEvent event) { - } - } - - @ListenerPriority(-5) - private static class AfterNavigationListenerThird - implements AfterNavigationListener { - @Override - public void afterNavigation(AfterNavigationEvent event) { - } - } - - @Test - public void after_navigation_listener_priority_should_dictate_sort_order() - throws InvalidRouteConfigurationException { - UI ui = createTestUI(); - initUI(ui, "", null); - - ui.addAfterNavigationListener(new AfterNavigationListenerThird()); - ui.addAfterNavigationListener(new AfterNavigationListenerThird()); - ui.addAfterNavigationListener(new AfterNavigationListenerFirst()); - ui.addAfterNavigationListener(new AfterNavigationListenerSecond()); - - final List AfterNavigationListeners = ui - .getNavigationListeners(AfterNavigationHandler.class); - - assertEquals(4, AfterNavigationListeners.size()); - - assertTrue(AfterNavigationListeners - .get(0) instanceof AfterNavigationListenerFirst); - assertTrue(AfterNavigationListeners - .get(1) instanceof AfterNavigationListenerSecond); - assertTrue(AfterNavigationListeners - .get(2) instanceof AfterNavigationListenerThird); - assertTrue(AfterNavigationListeners - .get(3) instanceof AfterNavigationListenerThird); - } - - @Test(expected = NullPointerException.class) - public void accessLaterRunnable_nullHandler_exception() { - UI ui = createAccessableTestUI(); - - ui.accessLater((SerializableRunnable) null, () -> { - }); - } - - @Test - public void accessLaterRunnable_attachedUnlockedUi_runnableIsRun() { - AtomicInteger runCount = new AtomicInteger(); - - UI ui = createAccessableTestUI(); - CurrentInstance.clearAll(); - - SerializableRunnable wrapped = ui.accessLater(() -> { - assertSame("Current UI should be defined", ui, UI.getCurrent()); - runCount.incrementAndGet(); - }, null); - - assertNull("Should not have a current UI outside the caller", - UI.getCurrent()); - assertEquals("Task should not yet have run", 0, runCount.get()); - - wrapped.run(); - - assertNull("Should not have a current UI outside the caller", - UI.getCurrent()); - assertEquals("Task should have run once", 1, runCount.get()); - } - - @Test(expected = UIDetachedException.class) - public void accessLaterRunnable_detachedUiNoHandler_throws() { - UI ui = createTestUI(); - - SerializableRunnable wrapped = ui.accessLater( - () -> Assert.fail("Action should never run"), null); - wrapped.run(); - } - - @Test - public void accessLaterRunnable_detachedUi_detachHandlerCalled() { - AtomicInteger runCount = new AtomicInteger(); - - UI ui = createTestUI(); - - SerializableRunnable wrapped = ui.accessLater( - () -> Assert.fail("Action should never run"), - runCount::incrementAndGet); - - assertEquals("Handler should not yet have run", 0, runCount.get()); - - wrapped.run(); - - assertEquals("Handler should have run once", 1, runCount.get()); - } - - @Test - public void csrfToken_differentUIs_shouldBeUnique() { - String token1 = new UI().getCsrfToken(); - String token2 = new UI().getCsrfToken(); - - Assert.assertNotEquals("Each UI should have a unique CSRF token", - token1, token2); - } - - @Test - public void csrfToken_sameUI_shouldBeSame() { - UI ui = new UI(); - String token1 = ui.getCsrfToken(); - String token2 = ui.getCsrfToken(); - - Assert.assertEquals( - "getCsrfToken() should always return the same value for the same UI", - token1, token2); - } - - @Test(expected = NullPointerException.class) - public void accessLaterConsumer_nullHandler_exception() { - UI ui = createAccessableTestUI(); - - ui.accessLater((SerializableConsumer) null, () -> { - }); - } - - @Test - public void accessLaterConsumer_attachedUnlockedUi_runnableIsRun() { - AtomicInteger sum = new AtomicInteger(); - - UI ui = createAccessableTestUI(); - CurrentInstance.clearAll(); - - SerializableConsumer wrapped = ui.accessLater(value -> { - assertSame("Current UI should be defined", ui, UI.getCurrent()); - sum.addAndGet(value.intValue()); - }, null); - - assertNull("Should not have a current UI outside the caller", - UI.getCurrent()); - assertEquals("Task should not yet have run", 0, sum.get()); - - wrapped.accept(Integer.valueOf(5)); - - assertNull("Should not have a current UI outside the caller", - UI.getCurrent()); - assertEquals("Task should have run once", 5, sum.get()); - } - - @Test(expected = UIDetachedException.class) - public void accessLaterConsumer_detachedUiNoHandler_throws() { - UI ui = createTestUI(); - - SerializableConsumer wrapped = ui.accessLater( - value -> Assert.fail("Action should never run"), null); - wrapped.accept(null); - } - - @Test - public void accessLaterConsumer_detachedUi_detachHandlerCalled() { - AtomicInteger runCount = new AtomicInteger(); - - UI ui = createTestUI(); - - SerializableConsumer wrapped = ui.accessLater( - value -> Assert.fail("Action should never run"), - runCount::incrementAndGet); - - assertEquals("Handler should not yet have run", 0, runCount.get()); - - wrapped.accept(null); - - assertEquals("Handler should have run once", 1, runCount.get()); - } - - @Test - public void navigate_useParameterizedTarget_noOptionalAnnotation_navigationSucceded() { - AtomicReference loc = new AtomicReference<>(); - UI ui = new UI() { - @Override - public void navigate(String location) { - loc.set(location); - } - }; - initUI(ui, "", null); - - ui.navigate(Parameterized.class, "baz"); - Assert.assertEquals("foo-bar/baz", loc.get()); - } - - @Test - public void navigate_throws_illegal_argument_exception() { - UI ui = new UI(); - initUI(ui, "", null); - - try { - ui.navigate(Parameterized.class); - Assert.fail("IllegalArgumentException expected."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().endsWith("requires a parameter.")); - } - - try { - ui.navigate(Parameterized.class, (String) null); - Assert.fail("IllegalArgumentException expected."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().endsWith("requires a parameter.")); - } - - try { - ui.navigate(Parameterized.class, RouteParameters.empty()); - Assert.fail("IllegalArgumentException expected."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().endsWith("requires a parameter.")); - } - - try { - ui.navigate(Parameterized.class, - new RouteParameters("some", "value")); - Assert.fail("IllegalArgumentException expected."); - } catch (IllegalArgumentException e) { - Assert.assertTrue(e.getMessage().endsWith("requires a parameter.")); - } - } - - @Test - public void navigate_throws_null_pointer_exception() { - UI ui = new UI(); - initUI(ui, "", null); - - try { - ui.navigate((String) null); - Assert.fail("NullPointerException expected."); - } catch (NullPointerException e) { - Assert.assertEquals("Location must not be null", e.getMessage()); - } - - try { - ui.navigate((String) null, QueryParameters.empty()); - Assert.fail("NullPointerException expected."); - } catch (NullPointerException e) { - Assert.assertEquals("Location must not be null", e.getMessage()); - } - - try { - ui.navigate("foo-bar", null); - Assert.fail("NullPointerException expected."); - } catch (NullPointerException e) { - Assert.assertEquals("Query parameters must not be null", - e.getMessage()); - } - } - - @Test - public void navigate_throws_not_found_exception() { - UI ui = new UI(); - initUI(ui, "", null); - - try { - ui.navigate(FooBarParamNavigationTarget.class); - Assert.fail("NotFoundException expected."); - } catch (NotFoundException e) { - } - - try { - ui.navigate(ParameterizedNotRoute.class, 1); - Assert.fail("NotFoundException expected."); - } catch (NotFoundException e) { - } - - try { - ui.navigate(FooBarParamNavigationTarget.class, - new RouteParameters("fooParam", "123")); - Assert.fail("NotFoundException expected."); - } catch (NotFoundException e) { - } - } - - @Test - public void modalComponent_addedAndRemoved_hasModalReturnsCorrectValue() { - final TestFixture fixture = new TestFixture(); - Assert.assertTrue("Fixture should have set a modal component", - fixture.ui.hasModalComponent()); - - fixture.ui.setChildComponentModal(fixture.modalComponent, false); - - Assert.assertFalse( - "Setting modal to false should have removed all modality", - fixture.ui.hasModalComponent()); - } - - @Test - public void modalComponentPresent_getActiveModalComponent_returnsExpectedComponent() { - final TestFixture fixture = new TestFixture(); - Assert.assertEquals("modalComponent should be modal", - fixture.modalComponent, - fixture.ui.getInternals().getActiveModalComponent()); - - fixture.ui.setChildComponentModal(fixture.routingComponent, true); - - Assert.assertEquals( - "routingComponent should override modalComponent as active modal component", - fixture.routingComponent, - fixture.ui.getInternals().getActiveModalComponent()); - - fixture.ui.setChildComponentModal(fixture.routingComponent, false); - - Assert.assertEquals( - "modalComponent should return to active modal component when routingComponent made non modal", - fixture.modalComponent, - fixture.ui.getInternals().getActiveModalComponent()); - - } - - @Test - public void addToModalComponent_newComponentAdded_isAddedCorrectlyAsChild() { - final TestFixture fixture = new TestFixture(); - Component test = new AttachableComponent(); - fixture.ui.addToModalComponent(test); - - final Optional testComponentParent = test.getParent(); - Assert.assertTrue("test component was not attached", - testComponentParent.isPresent()); - Assert.assertEquals( - "test component should have been attached to modalComponent", - fixture.ui.getInternals().getActiveModalComponent(), - testComponentParent.get()); - } - - @Test - public void routingComponentVisible_modalComponentAdded_routingComponentInert() { - final TestFixture fixture = new TestFixture(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - - fixture.collectUiChanges(); // the modal add will be visible - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - fixture.ui.remove(fixture.modalComponent); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - - fixture.ui.addModal(fixture.modalComponent); - fixture.collectUiChanges(); // the modal add will be visible - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void routingComponentAndModalComponentVisible_modalComponentAdded_anotherModalComponentInert() { - final TestFixture fixture = new TestFixture(); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - final AttachableComponent secondModal = new AttachableComponent(); - fixture.ui.addModal(secondModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, true); - verifyInert(secondModal, false); - - fixture.ui.remove(secondModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void modalComponentPresent_modalityChanged_routingComponentNotInert() { - final TestFixture fixture = new TestFixture(); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - fixture.ui.setChildComponentModal(fixture.modalComponent, false); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - - fixture.ui.setChildComponentModal(fixture.modalComponent, true); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void modalComponentsPresent_newComponentAdded_isInert() { - final TestFixture fixture = new TestFixture(); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - final AttachableComponent component = new AttachableComponent(); - fixture.ui.add(component); - - // inert state inherited from UI immediately - verifyInert(component, true); - - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - verifyInert(component, true); - } - - @Test - public void modalComponent_addedAndRemovedBeforeResponse_noInertChanged() { - final TestFixture fixture = new TestFixture(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - - fixture.ui.remove(fixture.modalComponent); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void modalComponentsPresent_componentMoved_notModal() { - final TestFixture fixture = new TestFixture(); - fixture.collectUiChanges(); - - fixture.ui.add(fixture.modalComponent); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void modalComponentPresent_sameModalAddedAgain_modeless() { - final TestFixture fixture = new TestFixture(); - fixture.collectUiChanges(); - - fixture.ui.add(fixture.modalComponent); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void modalComponentPresent_toggleTopModalAgain_noChanges() { - final TestFixture fixture = new TestFixture(); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - - fixture.ui.setChildComponentModal(fixture.modalComponent, true); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void modelessComponentPresent_toggleModelessAgain_noChanges() { - final TestFixture fixture = new TestFixture(); - fixture.ui.setChildComponentModal(fixture.modalComponent, false); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - - fixture.ui.setChildComponentModal(fixture.modalComponent, true); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void twoModalComponents_lowerComponentModelssAndTopMostRemoved_routingComponentNotInert() { - final TestFixture fixture = new TestFixture(); - final AttachableComponent secondModal = new AttachableComponent(); - fixture.ui.addModal(secondModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, true); - verifyInert(secondModal, false); - - // (not a typical use case but tested anyway) - // the change of modality has no effect due to another modal component - // on top - fixture.ui.setChildComponentModal(fixture.modalComponent, false); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, true); - verifyInert(secondModal, false); - - fixture.ui.remove(secondModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, false); - verifyInert(fixture.routingComponent, false); - verifyInert(fixture.modalComponent, false); - } - - @Test - public void twoModalComponents_topComponentMoved_modalComponentSwitches() { - final TestFixture fixture = new TestFixture(); - final AttachableComponent secondModal = new AttachableComponent(); - fixture.ui.addModal(secondModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, true); - verifyInert(secondModal, false); - - fixture.ui.add(secondModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - verifyInert(secondModal, true); - } - - @Test - public void twoModalComponents_lowerComponentModalAgain_topComponentInert() { - final TestFixture fixture = new TestFixture(); - final AttachableComponent secondModal = new AttachableComponent(); - fixture.ui.addModal(secondModal); - fixture.collectUiChanges(); - - fixture.ui.setChildComponentModal(fixture.modalComponent, true); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, false); - verifyInert(secondModal, true); - - fixture.ui.remove(fixture.modalComponent); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(secondModal, false); - } - - @Test - public void threeModalComponents_topComponentRemoved_onlyTopMostNotInert() { - final TestFixture fixture = new TestFixture(); - final AttachableComponent secondModal = new AttachableComponent(); - final AttachableComponent thirdModal = new AttachableComponent(); - fixture.ui.addModal(secondModal); - fixture.ui.addModal(thirdModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, true); - verifyInert(secondModal, true); - verifyInert(thirdModal, false); - - fixture.ui.remove(thirdModal); - fixture.collectUiChanges(); - - verifyInert(fixture.ui, true); - verifyInert(fixture.routingComponent, true); - verifyInert(fixture.modalComponent, true); - verifyInert(secondModal, false); - } - - private void verifyInert(Component component, boolean inert) { - Assert.assertEquals("Invalid inert state", inert, - component.getElement().getNode().isInert()); - } - - private static class TestFixture { - public final UI ui; - public final Component routingComponent; - public final Component modalComponent; - - public TestFixture() { - ui = createTestUI(); - initUI(ui, "", null); - routingComponent = ui.getChildren().findFirst().get(); - - modalComponent = new AttachableComponent(); - ui.addModal(modalComponent); - } - - public void collectUiChanges() { - ui.getInternals().getStateTree().collectChanges(nodeChange -> { - }); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/UnitTest.java b/flow-server/src/test/java/com/vaadin/flow/component/UnitTest.java deleted file mode 100644 index 96611d4001b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/UnitTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Test; - -public class UnitTest { - - @Test - public void getUnit() { - Assert.assertFalse(Unit.getUnit(null).isPresent()); - Assert.assertFalse(Unit.getUnit("").isPresent()); - Assert.assertFalse(Unit.getUnit("10unknown").isPresent()); - - Assert.assertEquals(Unit.PERCENTAGE, Unit.getUnit("100%").get()); - Assert.assertEquals(Unit.PIXELS, Unit.getUnit("100px").get()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/ValueChangeMonitor.java b/flow-server/src/test/java/com/vaadin/flow/component/ValueChangeMonitor.java deleted file mode 100644 index 397669e647c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/ValueChangeMonitor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; - -import com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent; -import com.vaadin.flow.component.HasValue.ValueChangeEvent; - -public class ValueChangeMonitor { - public ValueChangeMonitor(HasValue obserable) { - obserable.addValueChangeListener(event -> { - if (capturedEvent != null) { - Assert.fail("There is already an event. Old event: " - + capturedEvent + ", new event: " + event); - } - - Assert.assertSame(obserable, event.getHasValue()); - - if (event instanceof ComponentValueChangeEvent) { - Assert.assertSame(obserable, - ((ComponentValueChangeEvent) event).getSource()); - } - - capturedEvent = event; - }); - } - - ValueChangeEvent capturedEvent; - - public void discard() { - Assert.assertNotNull("There should be an event", capturedEvent); - capturedEvent = null; - } - - public void assertEvent(boolean fromClient, T oldValue, T newValue) { - Assert.assertNotNull("There should be an event", capturedEvent); - Assert.assertTrue(fromClient == capturedEvent.isFromClient()); - - assertEventValues(capturedEvent, oldValue, newValue); - - discard(); - } - - public void assertNoEvent() { - Assert.assertNull("There should be no event", capturedEvent); - } - - public static void assertEventValues(ValueChangeEvent event, - T oldValue, T newValue) { - Assert.assertEquals(oldValue, event.getOldValue()); - Assert.assertEquals(newValue, event.getValue()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/WebComponentConfigurationFactoryTest.java b/flow-server/src/test/java/com/vaadin/flow/component/WebComponentConfigurationFactoryTest.java deleted file mode 100644 index a2c9e122bf8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/WebComponentConfigurationFactoryTest.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.vaadin.flow.component.WebComponentExporterFactory.DefaultWebComponentExporterFactory; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.component.webcomponent.WebComponentConfiguration; - -public class WebComponentConfigurationFactoryTest { - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - private WebComponentExporter.WebComponentConfigurationFactory factory = new WebComponentExporter.WebComponentConfigurationFactory(); - - @Test - public void create_constructsValidConfiguration() { - WebComponentConfiguration config1 = factory.create( - new DefaultWebComponentExporterFactory( - MyComponentExporter.class).create()); - - WebComponentConfiguration config2 = factory - .create(new MyComponentExporter()); - - Assert.assertNotNull("create() from class should have been successful", - config1); - Assert.assertNotNull( - "create() from instance should have been " + "successful", - config2); - } - - @Test - public void create_instance_throwsOnNullArgument() { - expectedEx.expect(NullPointerException.class); - expectedEx.expectMessage("'exporter'"); - - factory.create(null); - } - - @Test - @SuppressWarnings("unchecked") - public void create_configuration_hashCode() { - WebComponentConfiguration myComponentConfig = factory - .create(new DefaultWebComponentExporterFactory( - MyComponentExporter.class).create()); - WebComponentConfiguration similarConfig1 = factory.create( - new DefaultWebComponentExporterFactory<>(SimilarExporter1.class) - .create()); - WebComponentConfiguration similarConfig2 = factory.create( - new DefaultWebComponentExporterFactory<>(SimilarExporter2.class) - .create()); - WebComponentConfiguration similarConfig3 = factory.create( - new DefaultWebComponentExporterFactory<>(SimilarExporter3.class) - .create()); - - Assert.assertNotEquals( - "Configurations with different tags should have " - + "not have same hashCodes", - myComponentConfig.hashCode(), similarConfig1.hashCode()); - - Assert.assertNotEquals( - "Configurations with same tag, but different " - + "properties should not have same hashCodes", - similarConfig1.hashCode(), similarConfig2.hashCode()); - - Assert.assertEquals("Configurations with same tag and same properties " - + "but different defaults should have the same hashCode", - similarConfig2.hashCode(), similarConfig3.hashCode()); - } - - @Test - @SuppressWarnings("unchecked") - public void create_configuration_equals() { - WebComponentConfiguration myComponentConfig = factory - .create(new DefaultWebComponentExporterFactory<>( - MyComponentExporter.class).create()); - WebComponentConfiguration similarConfig1 = factory.create( - new DefaultWebComponentExporterFactory<>(SimilarExporter1.class) - .create()); - WebComponentConfiguration similarConfig2 = factory.create( - new DefaultWebComponentExporterFactory<>(SimilarExporter2.class) - .create()); - WebComponentConfiguration similarConfig3 = factory.create( - new DefaultWebComponentExporterFactory<>(SimilarExporter3.class) - .create()); - - Assert.assertNotEquals( - "Configurations with different tags should " + "not be equal", - myComponentConfig, similarConfig1); - - Assert.assertNotEquals( - "Configurations with same tag, but different " - + "properties should not be equal", - similarConfig1, similarConfig2); - - // even though the classes are different, they define the same - // embeddable web component - Assert.assertEquals( - "Configurations with same tag and same properties " - + "but different defaults should be equal", - similarConfig2, similarConfig3); - } - - public static class MyComponent extends Component { - - } - - public static class MyComponentExporter - extends WebComponentExporter { - - public MyComponentExporter() { - super("my-component"); - } - - @Override - public void configureInstance( - WebComponent webComponent, - WebComponentExporterTest.MyComponent component) { - - } - } - - public static class NullTagExporter - extends WebComponentExporter { - - public NullTagExporter() { - super(null); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class NoDefaultConstructorExporter - extends WebComponentExporter { - - public NoDefaultConstructorExporter(String tag) { - super(tag); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class SimilarExporter1 - extends WebComponentExporter { - public SimilarExporter1() { - super("tag"); - addProperty("string", "dog"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class SimilarExporter2 - extends WebComponentExporter { - public SimilarExporter2() { - super("tag"); - addProperty("int", 0); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class SimilarExporter3 - extends WebComponentExporter { - public SimilarExporter3() { - super("tag"); - addProperty("int", 1); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/WebComponentExporterTest.java b/flow-server/src/test/java/com/vaadin/flow/component/WebComponentExporterTest.java deleted file mode 100644 index 454d6114f9d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/WebComponentExporterTest.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component; - -import java.util.Set; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.component.webcomponent.WebComponentConfiguration; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.internal.JsonSerializer; -import com.vaadin.flow.server.MockInstantiator; -import com.vaadin.flow.server.webcomponent.PropertyData; -import com.vaadin.flow.server.webcomponent.WebComponentBinding; - -import elemental.json.Json; -import elemental.json.JsonValue; - -import static org.mockito.Mockito.mock; - -public class WebComponentExporterTest { - - private static final String TAG = "my-component"; - - private MyComponentExporter exporter; - private WebComponentConfiguration config; - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Before - @SuppressWarnings("unchecked") - public void setUp() { - exporter = new MyComponentExporter(); - config = (WebComponentConfiguration) new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter); - } - - @Test - public void addProperty_differentTypes() { - exporter.addProperty("int", 1); - exporter.addProperty("string", "string"); - exporter.addProperty("boolean", true); - exporter.addProperty("double", 1.0); - - assertProperty(config, "int", 1); - assertProperty(config, "string", "string"); - assertProperty(config, "boolean", true); - assertProperty(config, "double", 1.0); - - // JsonValue - Bean bean = new Bean(); - bean.setInteger(5); - - JsonValue value = JsonSerializer.toJson(bean); - exporter.addProperty("json", value); - - assertProperty(config, "json", value); - } - - @Test - public void addProperty_propertyWithTheSameNameGetsOverwritten() { - exporter.addProperty("int", 1); - - Assert.assertTrue(config.hasProperty("int")); - - exporter.addProperty("int", 2); - - Assert.assertEquals("Configuration should have one property", 1, - config.getPropertyDataSet().size()); - - assertProperty(config, "int", 2); - } - - @Test - public void configuration_getTag() { - Assert.assertEquals(TAG, config.getTag()); - } - - @Test - public void configuration_getPropertyType_differentTypes() { - exporter.addProperty("int", 1); - exporter.addProperty("string", "string"); - exporter.addProperty("boolean", true); - exporter.addProperty("double", 1.0); - - Assert.assertEquals(Integer.class, config.getPropertyType("int")); - Assert.assertEquals(String.class, config.getPropertyType("string")); - Assert.assertEquals(Boolean.class, config.getPropertyType("boolean")); - Assert.assertEquals(Double.class, config.getPropertyType("double")); - } - - @Test - public void configuration_deliverPropertyUpdate() { - exporter.addProperty("int", 0).onChange(MyComponent::update); - - WebComponentBinding binding = config - .createWebComponentBinding(new MockInstantiator(), - mock(Element.class), Json.createObject()); - - Assert.assertNotNull(binding); - - binding.updateProperty("int", 1); - - Assert.assertEquals("Component should have been updated", 1, - binding.getComponent().getValue()); - } - - @Test - public void configuration_getPropertyDataSet() { - exporter.addProperty("int", 1); - exporter.addProperty("string", "string"); - exporter.addProperty("boolean", true); - exporter.addProperty("double", 1.0); - - Set> set = config.getPropertyDataSet(); - - Assert.assertEquals(4, set.size()); - } - - @Test - public void configuration_getComponentClass() { - Assert.assertEquals("Component class should be MyComponent.class", - MyComponent.class, config.getComponentClass()); - } - - @Test - @SuppressWarnings("unchecked") - public void configuration_createWebComponentBinding() { - exporter = new MyComponentExporter() { - @Override - public void configureInstance( - WebComponent webComponent, - MyComponent component) { - component.flop(); - } - }; - exporter.addProperty("value", 1).onChange(MyComponent::update); - - config = (WebComponentConfiguration) new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter); - - WebComponentBinding binding = config - .createWebComponentBinding(new MockInstantiator(), - mock(Element.class), Json.createObject()); - - Assert.assertNotNull("Binding should not be null", binding); - Assert.assertNotNull("Binding's component should not be null", - binding.getComponent()); - Assert.assertTrue("configureInstance() should have set 'flip' to true", - binding.getComponent().getFlip()); - Assert.assertEquals("value should be set to 1 by default", 1, - binding.getComponent().value); - } - - @Test - @SuppressWarnings("unchecked") - public void configuration_createWebComponentBinding_overridesDefaultValues() { - exporter.addProperty("value", 1).onChange(MyComponent::update); - - config = (WebComponentConfiguration) new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter); - - // attribute: value=2 - WebComponentBinding binding = config - .createWebComponentBinding(new MockInstantiator(), - mock(Element.class), Json.parse("{\"value\":2}")); - - Assert.assertEquals("attribute should have set default value to two", 2, - binding.getComponent().value); - } - - @Test - public void configuration_bindProxy_withoutInstanceConfigurator() { - WebComponentBinding binding = config - .createWebComponentBinding(new MockInstantiator(), - mock(Element.class), Json.createObject()); - - Assert.assertNotNull("Binding should not be null", binding); - Assert.assertNotNull("Binding's component should not be null", - binding.getComponent()); - Assert.assertFalse("'flip' should have been false", - binding.getComponent().getFlip()); - } - - @Test(expected = IllegalStateException.class) - @SuppressWarnings("unchecked") - public void configuration_bindProxy_throwsIfExporterSharesTagWithComponent() { - SharedTagExporter sharedTagExporter = new SharedTagExporter(); - WebComponentConfiguration sharedConfig = (WebComponentConfiguration) new WebComponentExporter.WebComponentConfigurationFactory() - .create(sharedTagExporter); - - sharedConfig.createWebComponentBinding(new MockInstantiator(), - mock(Element.class), Json.createObject()); - } - - @Test - public void configuration_hasProperty() { - exporter.addProperty("int", 1); - exporter.addProperty("string", "string"); - exporter.addProperty("boolean", true); - exporter.addProperty("double", 1.0); - - Assert.assertTrue(config.hasProperty("int")); - Assert.assertTrue(config.hasProperty("string")); - Assert.assertTrue(config.hasProperty("boolean")); - Assert.assertTrue(config.hasProperty("double")); - - Assert.assertFalse(config.hasProperty("does-not-exist")); - } - - @Test - public void configuration_callAddProperty_throws() { - expectedEx.expect(IllegalStateException.class); - expectedEx.expectMessage("'addProperty'"); - - AddPropertyInsideConfigureInstance exporter = new AddPropertyInsideConfigureInstance(); - WebComponentConfiguration config = new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter); - - config.createWebComponentBinding(new MockInstantiator(), - mock(Element.class), Json.createObject()); - } - - @Test(expected = IllegalStateException.class) - public void exporterConstructorThrowsIfNoComponentDefined() { - NoComponentExporter exporter = new NoComponentExporter(); - } - - @Tag("test") - public static class MyComponent extends Component { - private boolean flip = false; - private int value = 0; - - public void flop() { - flip = true; - } - - public void update(int i) { - value = i; - } - - public boolean getFlip() { - return flip; - } - - public int getValue() { - return value; - } - } - - public static class Bean { - protected int integer = 0; - - public Bean() { - } - - public int getInteger() { - return integer; - } - - public void setInteger(int i) { - integer = i; - } - - @Override - public int hashCode() { - return integer; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Bean) { - return integer == ((Bean) obj).integer; - } - return false; - } - } - - public static class MyComponentExporter - extends WebComponentExporter { - - public MyComponentExporter() { - super(TAG); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - } - } - - public static class AddPropertyInsideConfigureInstance - extends WebComponentExporter { - - public AddPropertyInsideConfigureInstance() { - super("foo"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - addProperty("bar", 1); - } - } - - @Tag("shared-tag") - public static class SharedTagComponent extends Component { - } - - private static class SharedTagExporter - extends WebComponentExporter { - - public SharedTagExporter() { - super("shared-tag"); - } - - @Override - public void configureInstance( - WebComponent webComponent, - SharedTagComponent component) { - - } - } - - public static class NoComponentExporter extends WebComponentExporter { - public NoComponentExporter() { - super("tag"); - } - - @Override - public void configureInstance(WebComponent webComponent, - Component component) { - } - } - - private static void assertProperty(WebComponentConfiguration config, - String property, Object value) { - PropertyData data = config.getPropertyDataSet().stream() - .filter(d -> d.getName().equals(property)).findFirst() - .orElse(null); - - Assert.assertNotNull("Property " + property + " should not be null", - data); - Assert.assertEquals(value, data.getDefaultValue()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/WhiteSpaceTest.java b/flow-server/src/test/java/com/vaadin/flow/component/WhiteSpaceTest.java deleted file mode 100644 index d11ae6f7a8f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/WhiteSpaceTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.HasText.WhiteSpace; - -public class WhiteSpaceTest { - - @Test - public void toString_styleValueIsReturned() { - Assert.assertEquals("nowrap", WhiteSpace.NOWRAP.toString()); - Assert.assertEquals("pre-line", WhiteSpace.PRE_LINE.toString()); - } - - @Test - public void forString_enumIsReturned() { - Assert.assertEquals(WhiteSpace.NORMAL, WhiteSpace.forString("normal")); - Assert.assertEquals(WhiteSpace.PRE_WRAP, - WhiteSpace.forString("pre-wrap")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/internal/DependencyTreeCacheTest.java b/flow-server/src/test/java/com/vaadin/flow/component/internal/DependencyTreeCacheTest.java deleted file mode 100644 index 2c2ce688222..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/internal/DependencyTreeCacheTest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component.internal; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.function.SerializableFunction; - -public class DependencyTreeCacheTest { - @Test - public void multipleLevels_allIncluded_noneParsedAgain() { - MockParser parser = new MockParser().addResult("/a", "/b") - .addResult("/b", "/c").addResult("/c"); - - DependencyTreeCache cache = new DependencyTreeCache<>(parser); - Set dependencies = cache.getDependencies("/a"); - - parser.assertConsumed(); - Assert.assertEquals(new HashSet<>(Arrays.asList("/a", "/b", "/c")), - dependencies); - - // Parse again, should not trigger exception because things are parsed - // multiple times - Set dependencies2 = cache.getDependencies("/a"); - Assert.assertEquals(dependencies, dependencies2); - } - - @Test - public void sharedDependency_onlyParsedOnce() { - MockParser parser = new MockParser().addResult("/a", "/b", "/c") - .addResult("/b", "/d").addResult("/c", "/d").addResult("/d"); - - DependencyTreeCache cache = new DependencyTreeCache<>(parser); - Set dependencies = cache.getDependencies("/a"); - - parser.assertConsumed(); - Assert.assertEquals( - new HashSet<>(Arrays.asList("/a", "/b", "/c", "/d")), - dependencies); - } - - @Test - public void concurrentParse_onlyParsedOnce() throws InterruptedException { - MockParser parser = new MockParser(); - parser.addResult("/a", "/b"); - parser.addResult("/b", 100); - - DependencyTreeCache cache = new DependencyTreeCache<>(parser); - - long start = System.currentTimeMillis(); - - Set threadResult = new HashSet<>(); - Thread thread = new Thread(() -> { - threadResult.addAll(cache.getDependencies("/a")); - }); - thread.start(); - - Set dependencies = cache.getDependencies("/a"); - - thread.join(); - - long end = System.currentTimeMillis(); - - Assert.assertEquals(new HashSet<>(Arrays.asList("/a", "/b")), - dependencies); - Assert.assertEquals(dependencies, threadResult); - - long duration = (end - start); - - Assert.assertTrue("Parsing should take less than 200 ms", - duration < 200); - Assert.assertTrue( - "Parsing should take at least 100 ms, was " + duration, - duration >= 100); - } - - @Test - public void parallelParsing_potentialSpeedup() throws InterruptedException { - // Eventually, we should see both a case when the randomization makes - // parsing progress in parallel and a case when it happens sequentially - int maxDuration = Integer.MIN_VALUE; - int minDuration = Integer.MAX_VALUE; - - int iterationCount = 0; - while (minDuration > 75 || maxDuration < 75) { - if (iterationCount++ > 30) { - // Less than 1/10^9 chance that 50/50 randomization will give - // the same result 30 times in a row - Assert.fail( - "Did not observe both slowdown and speedup. Max duration: " - + maxDuration + ", min duration: " - + minDuration); - } - - MockParser parser = new MockParser().addResult("/a", 25, "/b", "/c") - .addResult("/b", 25).addResult("/c", 25); - DependencyTreeCache cache = new DependencyTreeCache<>( - parser); - - Thread thread = new Thread(() -> cache.getDependencies("/a")); - - long start = System.currentTimeMillis(); - - thread.start(); - cache.getDependencies("/a"); - thread.join(); - - long end = System.currentTimeMillis(); - int duration = (int) (end - start); - - Assert.assertTrue( - "Duration should never be less than 50, was " + duration, - duration >= 50); - - maxDuration = Math.max(maxDuration, duration); - minDuration = Math.min(minDuration, duration); - } - } - - @FunctionalInterface - private interface Blocker { - public void block() throws InterruptedException; - } - - private static class MockParser - implements SerializableFunction> { - private static final Supplier> USED_PLACEHOLDER = () -> Collections - .emptySet(); - - private Map>> items = new ConcurrentHashMap<>(); - - @Override - public Collection apply(String path) { - path = path.replaceFirst("^frontend://", ""); - - // Get value and mark it as used - Supplier> supplier = items.put(path, - USED_PLACEHOLDER); - - if (supplier == USED_PLACEHOLDER) { - Assert.fail("Path " + path + " has already been parsed"); - } else if (supplier == null) { - Assert.fail("Parser cannot find " + path); - } - - return supplier.get(); - } - - public MockParser addResult(String path, String... dependencies) { - return addResult(path, null, dependencies); - } - - public MockParser addResult(String path, int duration, - String... dependencies) { - return addResult(path, () -> Thread.sleep(duration), dependencies); - } - - public MockParser addResult(String path, Blocker blocker, - String... dependencies) { - items.put(path, () -> { - if (blocker != null) { - try { - blocker.block(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - return Arrays.asList(dependencies); - }); - return this; - } - - public void assertConsumed() { - items.forEach((path, value) -> Assert.assertSame( - path + " should have been parsed", USED_PLACEHOLDER, - value)); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java b/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java deleted file mode 100644 index be99aa3d248..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java +++ /dev/null @@ -1,693 +0,0 @@ -package com.vaadin.flow.component.internal; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HasComponents; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.component.page.History; -import com.vaadin.flow.component.page.Page; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.impl.BasicElementStateProvider; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.BeforeEnterObserver; -import com.vaadin.flow.router.BeforeLeaveEvent; -import com.vaadin.flow.router.BeforeLeaveObserver; -import com.vaadin.flow.router.InternalServerError; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.QueryParameters; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.RouterLink; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; - -import static com.vaadin.flow.component.internal.JavaScriptBootstrapUI.CLIENT_NAVIGATE_TO; -import static com.vaadin.flow.component.internal.JavaScriptBootstrapUI.SERVER_ROUTING; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class JavaScriptBootstrapUITest { - - private static final String CLIENT_PUSHSTATE_TO = "setTimeout(() => window.history.pushState($0, '', $1))"; - - private MockServletServiceSessionSetup mocks; - private JavaScriptBootstrapUI ui; - - @PageTitle("app-shell-title") - public static class AppShell implements AppShellConfigurator { - } - - @Tag(Tag.H2) - public static class CleanChild extends Component - implements BeforeLeaveObserver { - @Override - public void beforeLeave(BeforeLeaveEvent event) { - } - } - - @Route("clean") - @Tag(Tag.HEADER) - public static class Clean extends Component implements HasComponents { - public Clean() { - add(new CleanChild()); - } - } - - @Tag(Tag.H1) - public static class DirtyChild extends Component - implements BeforeLeaveObserver { - @Override - public void beforeLeave(BeforeLeaveEvent event) { - event.postpone(); - } - } - - @Route("dirty") - @Tag(Tag.SPAN) - public static class Dirty extends Component implements HasComponents { - public Dirty() { - add(new DirtyChild()); - } - } - - @Route("product") - @Tag(Tag.SPAN) - @PageTitle("my-product") - public static class ProductView extends Component implements HasComponents { - public ProductView() { - // this should be ignored - UI.getCurrent().navigate("product"); - setId("productView"); - } - } - - @Route("exception") - @Tag(Tag.DIV) - public static class FailOnException extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - throw new RuntimeException("Failed on an exception"); - } - } - - @Route("forwardToClientSideViewOnBeforeEnter") - @Tag(Tag.DIV) - public static class ForwardToClientSideViewOnBeforeEnter extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.forwardTo("client-view"); - } - } - - @Route("forwardToClientSideViewOnBeforeLeave") - @Tag(Tag.DIV) - public static class ForwardToClientSideViewOnBeforeLeave extends Component - implements BeforeLeaveObserver { - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - event.forwardTo("client-view"); - } - } - - @Route("rerouteToClientSideViewOnReroute") - @Tag(Tag.DIV) - public static class ForwardToClientSideViewOnReroute extends Component - implements BeforeLeaveObserver, BeforeEnterObserver { - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - event.rerouteTo("client-view"); - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteTo("client-view"); - } - } - - @Route("forwardToServerSideViewOnBeforeEnter") - @Tag(Tag.DIV) - public static class ForwardToServerViewOnBeforeEnter extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.forwardTo("clean"); - } - } - - @Before - public void setup() throws Exception { - mocks = new MockServletServiceSessionSetup(); - mocks.getService().getRouter().getRegistry().setRoute("clean", - Clean.class, Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute("clean/1", - Clean.class, Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute("dirty", - Dirty.class, Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute("product", - ProductView.class, Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute("exception", - FailOnException.class, Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute( - "forwardToClientSideViewOnBeforeEnter", - ForwardToClientSideViewOnBeforeEnter.class, - Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute( - "forwardToClientSideViewOnBeforeLeave", - ForwardToClientSideViewOnBeforeLeave.class, - Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute( - "rerouteToClientSideViewOnReroute", - ForwardToClientSideViewOnReroute.class, - Collections.emptyList()); - mocks.getService().getRouter().getRegistry().setRoute( - "forwardToServerSideViewOnBeforeEnter", - ForwardToServerViewOnBeforeEnter.class, - Collections.emptyList()); - ui = new JavaScriptBootstrapUI(); - ui.getInternals().setSession(mocks.getSession()); - - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.FALSE); - - CurrentInstance.setCurrent(ui); - } - - @After - public void cleanup() { - mocks.cleanup(); - } - - @Test - public void should_allow_navigation() { - ui.connectClient("foo", "bar", "/clean", "", null); - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - // Dirty view is allowed after clean view - ui.connectClient("foo", "bar", "/dirty", "", null); - assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - } - - @Test - public void should_navigate_when_endingSlash() { - ui.connectClient("foo", "bar", "/clean/", "", null); - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - } - - @Test - public void getChildren_should_notReturnAnEmptyList() { - ui.connectClient("foo", "bar", "/clean", "", null); - assertEquals(1, ui.getChildren().count()); - } - - @Test - public void addRemoveComponent_clientSideRouting_addsToBody() { - final Element uiElement = ui.getElement(); - - ui.connectClient("foo", "bar", "/clean", "", null); - // router outlet is a virtual child that is not reflected on element - // level - assertEquals(1, ui.getChildren().count()); - assertEquals(0, uiElement.getChildCount()); - assertEquals(0, ui.getElement().getChildCount()); - - final RouterLink routerLink = new RouterLink(); - ui.add(routerLink); - - assertEquals(2, ui.getChildren().count()); - assertEquals(1, ui.getElement().getChildCount()); - assertEquals(1, uiElement.getChildCount()); - - ui.add(new RouterLink()); - - assertEquals(3, ui.getChildren().count()); - assertEquals(2, ui.getElement().getChildCount()); - assertEquals(2, uiElement.getChildCount()); - - ui.remove(routerLink); - - assertEquals(2, ui.getChildren().count()); - assertEquals(1, ui.getElement().getChildCount()); - assertEquals(1, uiElement.getChildCount()); - } - - @Test - public void addRemoveComponent_serverSideRouting_addsDirectlyToUI() { - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.TRUE); - - assertEquals(0, ui.getElement().getChildCount()); - assertEquals(0, ui.getChildren().count()); - - // use any server side route - ui.navigate("product"); - - assertEquals(1, ui.getElement().getChildCount()); - assertEquals(1, ui.getChildren().count()); - - final RouterLink routerLink = new RouterLink(); - ui.add(routerLink); - assertEquals(2, ui.getElement().getChildCount()); - assertEquals(2, ui.getChildren().count()); - - ui.remove(routerLink); - - assertEquals(1, ui.getElement().getChildCount()); - assertEquals(1, ui.getChildren().count()); - } - - @Test - public void addComponent_clientSideRouterAndNavigation_componentsRemain() { - final Element uiElement = ui.getElement(); - // trigger route via client - ui.connectClient("foo", "bar", "/clean", "", null); - final RouterLink routerLink = new RouterLink(); - ui.add(routerLink); - - assertEquals(2, ui.getChildren().count()); - assertEquals(1, ui.getElement().getChildCount()); - assertEquals(1, uiElement.getChildCount()); - - ui.navigate("product"); - - assertEquals(2, ui.getChildren().count()); - assertEquals(1, ui.getElement().getChildCount()); - assertEquals(1, uiElement.getChildCount()); - } - - @Test - public void addComponent_serverSideRouterAndNavigation_componentsRemain() { - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.TRUE); - final Element uiElement = ui.getElement(); - - ui.navigate("clean"); - final RouterLink routerLink = new RouterLink(); - ui.add(routerLink); - - assertEquals(2, ui.getChildren().count()); - assertEquals(2, ui.getElement().getChildCount()); - assertEquals(2, uiElement.getChildCount()); - - ui.navigate("product"); - - assertEquals(2, ui.getChildren().count()); - assertEquals(2, ui.getElement().getChildCount()); - assertEquals(2, uiElement.getChildCount()); - } - - @Test - public void should_prevent_navigation_on_dirty() { - ui.connectClient("foo", "bar", "/dirty", "", null); - assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - // clean view cannot be rendered after dirty - ui.connectClient("foo", "bar", "/clean", "", null); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - // an error route cannot be rendered after dirty - ui.connectClient("foo", "bar", "/errr", "", null); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - } - - @Test - public void should_remove_content_on_leaveNavigation() { - ui.connectClient("foo", "bar", "/clean", "", null); - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - ui.leaveNavigation("/client-view"); - - assertEquals(0, ui.wrapperElement.getChildCount()); - } - - @Test - public void should_keep_content_on_leaveNavigation_postpone() { - ui.connectClient("foo", "bar", "/dirty", "", null); - assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - ui.leaveNavigation("/client-view"); - assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - } - - @Test - public void should_handle_forward_to_client_side_view_on_beforeEnter() { - ui.connectClient("foo", "bar", "/forwardToClientSideViewOnBeforeEnter", - "", null); - - assertEquals("client-view", ui.getForwardToClientUrl()); - } - - @Test - public void should_not_handle_forward_to_client_side_view_on_beforeLeave() { - ui.connectClient("foo", "bar", "/forwardToClientSideViewOnBeforeLeave", - "", null); - - assertNull(ui.getForwardToClientUrl()); - } - - @Test - public void should_not_handle_forward_to_client_side_view_on_reroute() { - ui.connectClient("foo", "bar", "/forwardToClientSideViewOnReroute", "", - null); - - assertNull(ui.getForwardToClientUrl()); - } - - @Test - public void should_handle_forward_to_server_side_view_on_beforeEnter_and_update_url() { - ui.connectClient("foo", "bar", "/forwardToServerSideViewOnBeforeEnter", - "", null); - - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - ui.navigate("product"); - assertEquals("my-product", ui.getInternals().getTitle()); - assertEquals("productView", - ui.getChildren().findFirst().get().getId().get()); - - ui.navigate("forwardToServerSideViewOnBeforeEnter"); - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - } - - @Test - public void should_show_error_page() { - ui.connectClient("foo", "bar", "/err", "", null); - assertEquals(Tag.DIV, ui.wrapperElement.getChild(0).getTag()); - assertTrue(ui.wrapperElement.toString().contains("Available routes:")); - } - - @Test - public void should_initializeUI_when_wrapperElement_null() { - Location location = new Location("foo"); - ui.getInternals().getRouter().initializeUI(ui, location); - assertNull(ui.wrapperElement); - // attached to body - assertTrue(ui.getElement().toString().contains("Available routes:")); - } - - @Test - public void should_navigate_when_server_routing() { - ui.connectClient("foo", "bar", "/clean", "", null); - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.TRUE); - - ui.navigate("dirty"); - assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H1, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - } - - @Test - public void should_not_create_navigation_loop_when_server_routing() { - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.TRUE); - - ui.navigate("product"); - assertTrue(ui.getChildren().findFirst().isPresent()); - assertEquals("productView", - ui.getChildren().findFirst().get().getId().get()); - } - - @Test - public void should_clearLastHandledNavigation_when_navigateToOtherViews() { - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.TRUE); - - ui.navigate("clean"); - assertFalse("Should clear lastHandledNavigation after finishing", - ui.getInternals().hasLastHandledLocation()); - ui.navigate("product"); - assertFalse("Should clear lastHandledNavigation after finishing", - ui.getInternals().hasLastHandledLocation()); - } - - @Test - public void should_invoke_clientRoute_when_navigationHasNotBeenStarted() { - ui = Mockito.spy(ui); - Page page = mockPage(); - - ArgumentCaptor execJs = ArgumentCaptor.forClass(String.class); - ArgumentCaptor execArg = ArgumentCaptor.forClass(String.class); - - ui.navigate("whatever"); - Mockito.verify(page).executeJs(execJs.capture(), execArg.capture()); - - assertEquals(CLIENT_NAVIGATE_TO, execJs.getValue()); - assertEquals("whatever", execArg.getValue()); - } - - @Test - public void should_update_pushState_when_navigationHasBeenAlreadyStarted() { - ui = Mockito.spy(ui); - Page page = mockPage(); - - UIInternals internals = mockUIInternals(); - - Mockito.when(internals.hasLastHandledLocation()).thenReturn(true); - Location lastLocation = new Location("clean"); - Mockito.when(internals.getLastHandledLocation()) - .thenReturn(lastLocation); - StateTree stateTree = Mockito.mock(StateTree.class); - Mockito.when(internals.getStateTree()).thenReturn(stateTree); - Mockito.when(internals.getTitle()).thenReturn(""); - - StateNode stateNode = BasicElementStateProvider - .createStateNode("foo-element"); - Mockito.when(stateTree.getRootNode()).thenReturn(stateNode); - - ArgumentCaptor execJs = ArgumentCaptor.forClass(String.class); - ArgumentCaptor execArg = ArgumentCaptor.forClass(String.class); - - ui.navigate("clean/1"); - Mockito.verify(page).executeJs(execJs.capture(), execArg.capture()); - - assertEquals(CLIENT_PUSHSTATE_TO, execJs.getValue()); - - final List execValues = execArg.getAllValues(); - assertEquals(2, execValues.size()); - assertNull(execValues.get(0)); - assertEquals("clean/1", execArg.getValue()); - } - - @Test - public void should_not_notify_clientRoute_when_navigatingToTheSame() { - ui = Mockito.spy(ui); - Page page = mockPage(); - - UIInternals internals = mockUIInternals(); - - Mockito.when(internals.hasLastHandledLocation()).thenReturn(true); - Location lastLocation = new Location("clean"); - Mockito.when(internals.getLastHandledLocation()) - .thenReturn(lastLocation); - - ui.navigate("clean/"); - Mockito.verify(page, Mockito.never()).executeJs(Mockito.anyString(), - Mockito.anyString()); - } - - @Test - public void server_should_not_doClientRoute_when_navigatingToServer() { - ui.connectClient("foo", "bar", "/clean", "", null); - assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag()); - assertEquals(Tag.H2, - ui.wrapperElement.getChild(0).getChild(0).getTag()); - - ui = Mockito.spy(ui); - Page page = mockPage(); - - ArgumentCaptor execJs = ArgumentCaptor.forClass(String.class); - ArgumentCaptor execArg = ArgumentCaptor.forClass(String.class); - - // Dirty view is allowed after clean view - ui.navigate("dirty"); - // A server navigation happens - assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag()); - Mockito.verify(page).executeJs(execJs.capture(), execArg.capture()); - - assertEquals(CLIENT_PUSHSTATE_TO, execJs.getValue()); - - final List execValues = execArg.getAllValues(); - assertEquals(2, execValues.size()); - assertNull(execValues.get(0)); - assertEquals("dirty", execArg.getValue()); - } - - @Test - public void should_updatePageTitle_when_serverNavigation() { - ui.navigate("empty"); - assertNull(ui.getInternals().getTitle()); - ui.navigate("product"); - assertEquals("my-product", ui.getInternals().getTitle()); - } - - @Test - public void should_removeTitle_when_noAppShellTitle() { - ui.navigate("empty"); - assertNull(ui.getInternals().getTitle()); - ui.navigate("dirty"); - assertEquals("", ui.getInternals().getTitle()); - } - - @Test - public void should_restoreIndexHtmlTitle() { - ui.connectClient("foo", "bar", "empty", "app-shell-title", null); - assertEquals("", ui.getInternals().getTitle()); - ui.connectClient("foo", "bar", "dirty", "app-shell-title", null); - assertEquals("app-shell-title", ui.getInternals().getTitle()); - } - - @Test - public void should_not_share_dynamic_app_title_for_different_UIs() { - String dynamicTitle = UUID.randomUUID().toString(); - ui.connectClient("foo", "bar", "clean", dynamicTitle, null); - assertEquals(dynamicTitle, ui.getInternals().getTitle()); - - String anotherDynamicTitle = UUID.randomUUID().toString(); - JavaScriptBootstrapUI anotherUI = new JavaScriptBootstrapUI(); - anotherUI.getInternals().setSession(mocks.getSession()); - anotherUI.connectClient("foo", "bar", "clean", anotherDynamicTitle, - null); - assertEquals(anotherDynamicTitle, anotherUI.getInternals().getTitle()); - - ui.navigate("dirty"); - assertEquals(dynamicTitle, ui.getInternals().getTitle()); - } - - @Test - public void should_caught_and_show_exception_during_navigation_in_internalServerError() - throws InvalidRouteConfigurationException { - String location = "exception"; - String validationMessage = "Failed on an exception"; - Mockito.when(mocks.getSession().getAttribute(SERVER_ROUTING)) - .thenReturn(Boolean.TRUE); - - ui.navigate(location); - String errorMessage = String.format( - "There was an exception while trying to navigate to '%s' with the exception message '%s'", - location, validationMessage); - assertExceptionComponent(InternalServerError.class, errorMessage); - } - - @Test - public void navigate_firsClientSideRoutingThrows_navigationInProgressIsReset_secondClientSideRoutingWorks() { - VaadinSession session = Mockito.mock(VaadinSession.class); - - VaadinService service = Mockito.mock(VaadinService.class); - Mockito.when(session.getService()).thenReturn(service); - Router router = Mockito.mock(Router.class); - Mockito.when(service.getRouter()).thenReturn(router); - - Mockito.doThrow(RuntimeException.class).when(router) - .resolveNavigationTarget(Mockito.any()); - - JavaScriptBootstrapUI ui = new JavaScriptBootstrapUI(); - - ui.getInternals().setSession(session); - - try { - ui.navigate("foo", QueryParameters.empty()); - } catch (RuntimeException expected) { - router = Mockito.mock(Router.class); - Mockito.when(service.getRouter()).thenReturn(router); - - Mockito.when(router.resolveNavigationTarget(Mockito.any())) - .thenReturn(Optional.empty()); - ui.navigate("foo", QueryParameters.empty()); - - Mockito.verify(router).resolveNavigationTarget(Mockito.any()); - return; - } - // self control: code inside catch should be invoked - Assert.fail(); - } - - private void assertExceptionComponent(Class errorClass, - String... exceptionTexts) { - Optional visibleComponent = ui.getElement().getChild(0) - .getComponent(); - - Assert.assertTrue("No navigation component visible", - visibleComponent.isPresent()); - - Component internalServerError = visibleComponent.get(); - Assert.assertEquals(errorClass, internalServerError.getClass()); - String errorText = internalServerError.getElement().getText(); - for (String exceptionText : exceptionTexts) { - Assert.assertTrue("Expected the error text to contain '" - + exceptionText + "'", errorText.contains(exceptionText)); - } - } - - private Page mockPage() { - Page page = Mockito.mock(Page.class); - Mockito.when(ui.getPage()).thenReturn(page); - - History history = new History(ui); - Mockito.when(page.getHistory()).thenReturn(history); - - return page; - } - - private UIInternals mockUIInternals() { - UIInternals internals = Mockito.mock(UIInternals.class); - Mockito.when(ui.getInternals()).thenReturn(internals); - - Mockito.when(internals.getRouter()) - .thenReturn(mocks.getService().getRouter()); - - return internals; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/internal/PageTest.java b/flow-server/src/test/java/com/vaadin/flow/component/internal/PageTest.java deleted file mode 100644 index 4b323bd27f0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/internal/PageTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component.internal; - -import java.util.Collection; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.Page; -import com.vaadin.flow.component.page.PendingJavaScriptResult; -import com.vaadin.flow.shared.ui.Dependency; -import com.vaadin.tests.util.MockUI; - -@NotThreadSafe -public class PageTest { - private MockUI ui = new MockUI(); - private Page page = ui.getPage(); - - @After - public void tearDown() { - UI.setCurrent(null); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddNullStyleSheet() { - page.addStyleSheet(null); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddNullJavaScript() { - page.addJavaScript(null); - } - - @Test - public void testJavasScriptExecutionCancel() { - Assert.assertEquals(0, countPendingInvocations()); - - PendingJavaScriptResult executeJavaScript = page - .executeJs("window.alert('$0');", "foobar"); - - Assert.assertEquals(1, countPendingInvocations()); - - Assert.assertTrue(executeJavaScript.cancelExecution()); - - Assert.assertEquals(0, countPendingInvocations()); - } - - @Test - public void testJavaScriptExecutionTooLateCancel() { - Assert.assertEquals(0, countPendingInvocations()); - - PendingJavaScriptResult executeJavaScript = page - .executeJs("window.alert('$0');", "foobar"); - - Assert.assertEquals(1, countPendingInvocations()); - - Assert.assertEquals(1, - ui.getInternals().dumpPendingJavaScriptInvocations().size()); - - Assert.assertEquals(0, countPendingInvocations()); - - Assert.assertFalse(executeJavaScript.cancelExecution()); - } - - @Test - public void addDynamicImport_dynamicDependencyIsAvaialbleViaGetPendingSendToClient() { - page.addDynamicImport("foo"); - - DependencyList list = ui.getInternals().getDependencyList(); - Collection dependencies = list.getPendingSendToClient(); - Assert.assertEquals(1, dependencies.size()); - Dependency dependency = dependencies.iterator().next(); - Assert.assertEquals("foo", dependency.getUrl()); - } - - private long countPendingInvocations() { - return ui.getInternals().getPendingJavaScriptInvocations().count(); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/internal/PendingJavaScriptInvocationTest.java b/flow-server/src/test/java/com/vaadin/flow/component/internal/PendingJavaScriptInvocationTest.java deleted file mode 100644 index fe1d8ea2bc0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/internal/PendingJavaScriptInvocationTest.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component.internal; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.internal.UIInternals.JavaScriptInvocation; -import com.vaadin.flow.component.page.PendingJavaScriptResult.JavaScriptException; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.tests.util.SingleCaptureConsumer; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonString; -import elemental.json.JsonValue; - -public class PendingJavaScriptInvocationTest { - private static final JsonString fooJsonString = Json.create("foo"); - - private PendingJavaScriptInvocation invocation; - - private SingleCaptureConsumer jsonSuccessConsumer; - private SingleCaptureConsumer stringSuccessConsumer; - private SingleCaptureConsumer errorConsumer; - - private BiConsumer jsonFutureHandler; - private BiConsumer stringFutureHandler; - - @Before - public void setUp() { - invocation = new PendingJavaScriptInvocation( - new Element("dummy").getNode(), new JavaScriptInvocation("")); - - jsonSuccessConsumer = new SingleCaptureConsumer<>(); - stringSuccessConsumer = new SingleCaptureConsumer<>(); - errorConsumer = new SingleCaptureConsumer<>(); - - jsonFutureHandler = futureHandler(jsonSuccessConsumer, errorConsumer); - stringFutureHandler = futureHandler(stringSuccessConsumer, - errorConsumer); - } - - private static BiConsumer futureHandler( - Consumer successConsumer, Consumer errorConsumer) { - return (successValue, error) -> { - if (error != null) { - Assert.assertEquals(JavaScriptException.class, - error.getClass()); - errorConsumer.accept(error.getMessage()); - } else { - successConsumer.accept(successValue); - } - }; - } - - @Test - public void untypedIgnoreErrors_success() { - invocation.then(jsonSuccessConsumer); - - invocation.complete(fooJsonString); - - assertJsonSuccess(); - } - - @Test - public void untypedIgnoreErrors_fail() { - invocation.then(jsonSuccessConsumer); - - invocation.completeExceptionally(fooJsonString); - - assertNoUpdate(); - } - - @Test - public void untypedCaptureErrors_success() { - invocation.then(jsonSuccessConsumer, errorConsumer); - - invocation.complete(fooJsonString); - - assertJsonSuccess(); - } - - @Test - public void untypedCaptureErrors_fail() { - invocation.then(jsonSuccessConsumer, errorConsumer); - - invocation.completeExceptionally(fooJsonString); - - assertFail(); - } - - @Test - public void untypedFuture_success() { - invocation.toCompletableFuture().whenComplete(jsonFutureHandler); - - invocation.complete(fooJsonString); - - assertJsonSuccess(); - } - - @Test - public void untypedFuture_fail() { - invocation.toCompletableFuture().whenComplete(jsonFutureHandler); - - invocation.completeExceptionally(fooJsonString); - - assertFail(); - } - - @Test - public void typedIgnoreErrors_success() { - invocation.then(String.class, stringSuccessConsumer); - - invocation.complete(fooJsonString); - - assertStringSuccess(); - } - - @Test - public void typedCaptureErrors_fail() { - invocation.then(String.class, stringSuccessConsumer); - - invocation.completeExceptionally(fooJsonString); - - assertNoUpdate(); - } - - @Test - public void typedCaptureErrors_success() { - invocation.then(String.class, stringSuccessConsumer, errorConsumer); - - invocation.complete(fooJsonString); - - assertStringSuccess(); - } - - @Test - public void typedIgnoreErrors_fail() { - invocation.then(String.class, stringSuccessConsumer, errorConsumer); - - invocation.completeExceptionally(fooJsonString); - - assertFail(); - } - - @Test - public void typedFuture_success() { - invocation.toCompletableFuture(String.class) - .whenComplete(stringFutureHandler); - - invocation.complete(fooJsonString); - - assertStringSuccess(); - } - - @Test - public void typedFuture_fail() { - invocation.toCompletableFuture(String.class) - .whenComplete(stringFutureHandler); - - invocation.completeExceptionally(fooJsonString); - - assertFail(); - } - - @Test - public void multipleSuccessHandlers() { - invocation.then(jsonSuccessConsumer, errorConsumer); - invocation.then(String.class, stringSuccessConsumer); - - invocation.complete(fooJsonString); - - Assert.assertSame(fooJsonString, - jsonSuccessConsumer.getCapturedValue()); - Assert.assertEquals("foo", stringSuccessConsumer.getCapturedValue()); - assertNoErrorValue(); - } - - @Test - public void multipleErrorHandlers() { - SingleCaptureConsumer extraErrorHandler = new SingleCaptureConsumer<>(); - - invocation.then(jsonSuccessConsumer, errorConsumer); - invocation.then(String.class, stringSuccessConsumer, extraErrorHandler); - - invocation.completeExceptionally(fooJsonString); - - assertNoStringSuccessValue(); - assertNoJsonSuccessValue(); - - Assert.assertSame("foo", errorConsumer.getCapturedValue()); - Assert.assertSame("foo", extraErrorHandler.getCapturedValue()); - } - - @Test(expected = IllegalStateException.class) - public void thenAfterSend_throws() { - invocation.setSentToBrowser(); - - invocation.then(jsonSuccessConsumer); - } - - @Test - public void subscribeAfterCancel_callFailHandler() { - invocation.cancelExecution(); - - invocation.then(jsonSuccessConsumer, errorConsumer); - - assertFail("Execution canceled"); - } - - @Test - public void susbscribeBeforeCancel_callFailHandler() { - invocation.then(jsonSuccessConsumer, errorConsumer); - - invocation.cancelExecution(); - - assertFail("Execution canceled"); - } - - @Test - public void blockFromInvokingThread_throws() throws Exception { - MockVaadinSession session = new MockVaadinSession(); - session.runWithLock(() -> { - CompletableFuture completableFuture = invocation - .toCompletableFuture(); - - for (Callable action : createBlockingActions( - completableFuture)) { - try { - action.call(); - Assert.fail( - "Blocking on a pending invocation while holding the session lock should throw"); - } catch (IllegalStateException e) { - // This is expected - } - } - - return null; - }); - } - - @Test - public void blockFromSessionThreadAfterCompleting_doesNotThrow() - throws Exception { - MockVaadinSession session = new MockVaadinSession(); - session.runWithLock(() -> { - CompletableFuture completableFuture = invocation - .toCompletableFuture(); - - JsonObject value = Json.createObject(); - invocation.complete(value); - - for (Callable action : createBlockingActions( - completableFuture)) { - JsonValue actionValue = action.call(); - Assert.assertSame(value, actionValue); - } - - return null; - }); - } - - @Test - public void blockFromSessionThreadAfterFailing_doesNotThrow() - throws Exception { - MockVaadinSession session = new MockVaadinSession(); - session.runWithLock(() -> { - CompletableFuture completableFuture = invocation - .toCompletableFuture(); - - String errorMessage = "error message"; - invocation.completeExceptionally(Json.create(errorMessage)); - - for (Callable action : createBlockingActions( - completableFuture)) { - try { - action.call(); - Assert.fail("Execution should have failed"); - } catch (ExecutionException | CompletionException e) { - JavaScriptException cause = (JavaScriptException) e - .getCause(); - Assert.assertEquals(errorMessage, cause.getMessage()); - } - } - return null; - }); - } - - @Test - public void blockFromOtherThread_doesNotThrow() throws Exception { - MockVaadinSession session = new MockVaadinSession(); - VaadinSession.setCurrent(session); - - ExecutorService executor = Executors.newFixedThreadPool(3); - - session.lock(); - try { - CompletableFuture completableFuture = invocation - .toCompletableFuture(); - - List> futures = createBlockingActions( - completableFuture).stream().map(executor::submit) - .collect(Collectors.toList()); - - Assert.assertEquals("All futures should be pending", 0, - futures.stream().filter(Future::isDone).count()); - - JsonObject value = Json.createObject(); - invocation.complete(value); - - executor.shutdown(); - executor.awaitTermination(100, TimeUnit.MILLISECONDS); - - Assert.assertEquals("All futures should be done", futures.size(), - futures.stream().filter(Future::isDone).count()); - - futures.forEach(future -> { - try { - JsonValue futureValue = future.get(); - Assert.assertSame(value, futureValue); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - - } finally { - session.unlock(); - executor.shutdown(); - } - } - - private List> createBlockingActions( - CompletableFuture completableFuture) { - return Arrays.asList(completableFuture::get, - () -> completableFuture.get(1, TimeUnit.HOURS), - completableFuture::join); - } - - private void assertStringSuccess() { - assertNoJsonSuccessValue(); - Assert.assertEquals("foo", stringSuccessConsumer.getCapturedValue()); - assertNoErrorValue(); - } - - private void assertJsonSuccess() { - Assert.assertSame(fooJsonString, - jsonSuccessConsumer.getCapturedValue()); - assertNoStringSuccessValue(); - assertNoErrorValue(); - } - - private void assertFail() { - assertFail("foo"); - } - - private void assertFail(String expectedMessage) { - assertNoJsonSuccessValue(); - assertNoStringSuccessValue(); - Assert.assertSame(expectedMessage, errorConsumer.getCapturedValue()); - } - - private void assertNoUpdate() { - assertNoStringSuccessValue(); - assertNoJsonSuccessValue(); - assertNoErrorValue(); - } - - private void assertNoJsonSuccessValue() { - Assert.assertFalse("Json success consumer should not be invoked", - jsonSuccessConsumer.isCaptured()); - } - - private void assertNoStringSuccessValue() { - Assert.assertFalse("String success consumer should not be invoked", - stringSuccessConsumer.isCaptured()); - } - - private void assertNoErrorValue() { - Assert.assertFalse("Error consumer should not be invoked", - errorConsumer.isCaptured()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/internal/UIInternalsTest.java b/flow-server/src/test/java/com/vaadin/flow/component/internal/UIInternalsTest.java deleted file mode 100644 index e52e8c1380f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/internal/UIInternalsTest.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.vaadin.flow.component.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HasElement; -import com.vaadin.flow.component.PushConfiguration; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.Text; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.di.DefaultInstantiator; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.shared.Registration; -import com.vaadin.flow.shared.communication.PushMode; -import com.vaadin.flow.shared.ui.Transport; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; - -public class UIInternalsTest { - - @Mock - UI ui; - @Mock - VaadinService vaadinService; - - UIInternals internals; - - @Route - @Push - @Tag(Tag.DIV) - public static class RouteTarget extends Component implements RouterLayout { - - } - - @Route(value = "foo", layout = RouteTarget.class) - @Tag(Tag.DIV) - public static class RouteTarget1 extends Component { - - } - - @Tag(Tag.DIV) - static class MainLayout extends Component implements RouterLayout { - static String ID = "main-layout-id"; - - public MainLayout() { - setId(ID); - } - } - - @Tag(Tag.DIV) - @ParentLayout(MainLayout.class) - static class SubLayout extends Component implements RouterLayout { - static String ID = "sub-layout-id"; - - public SubLayout() { - setId(ID); - } - } - - @Tag(Tag.DIV) - @Route(value = "child", layout = SubLayout.class) - static class FirstView extends Component { - static String ID = "child-view-id"; - - public FirstView() { - setId(ID); - } - } - - @Tag(Tag.DIV) - static class AnotherLayout extends Component implements RouterLayout { - static String ID = "another-layout-id"; - - public AnotherLayout() { - setId(ID); - } - } - - @Tag(Tag.DIV) - @Route(value = "another", layout = MainLayout.class) - static class AnotherView extends Component { - static String ID = "another-view-id"; - - public AnotherView() { - setId(ID); - } - } - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - - Mockito.when(ui.getUI()).thenReturn(Optional.of(ui)); - Element body = new Element("body"); - Mockito.when(ui.getElement()).thenReturn(body); - - internals = new UIInternals(ui); - AlwaysLockedVaadinSession session = new AlwaysLockedVaadinSession( - vaadinService); - VaadinContext context = Mockito.mock(VaadinContext.class); - Mockito.when(vaadinService.getContext()).thenReturn(context); - Mockito.when(vaadinService.getInstantiator()) - .thenReturn(new DefaultInstantiator(vaadinService)); - internals.setSession(session); - Mockito.when(ui.getSession()).thenReturn(session); - } - - @Test - public void heartbeatTimestampSet_heartbeatListenersAreCalled() { - List heartbeats = new ArrayList<>(); - Registration registration = internals.addHeartbeatListener( - event -> heartbeats.add(event.getHeartbeatTime())); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis()); - - Assert.assertEquals("Heartbeat listener should have fired", 1, - heartbeats.size()); - - registration.remove(); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis()); - - Assert.assertEquals( - "Heartbeat listener should been removed and no new event recorded", - 1, heartbeats.size()); - } - - @Test - public void heartbeatListenerRemovedFromHeartbeatEvent_noExplosion() { - AtomicReference reference = new AtomicReference<>(); - AtomicInteger runCount = new AtomicInteger(); - - Registration registration = internals.addHeartbeatListener(event -> { - runCount.incrementAndGet(); - reference.get().remove(); - }); - reference.set(registration); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis()); - Assert.assertEquals("Listener should have been run once", 1, - runCount.get()); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis()); - Assert.assertEquals( - "Listener should not have been run again since it was removed", - 1, runCount.get()); - } - - @Test - public void showRouteTarget_clientSideBootstrap() { - PushConfiguration pushConfig = setUpInitialPush(); - - internals.showRouteTarget(Mockito.mock(Location.class), - new RouteTarget(), Collections.emptyList()); - - Mockito.verify(pushConfig, Mockito.never()).setPushMode(Mockito.any()); - } - - @Test - public void showRouteTarget_navigateToAnotherViewWithinSameLayoutHierarchy_detachedRouterLayoutChildrenRemoved() { - MainLayout mainLayout = new MainLayout(); - SubLayout subLayout = new SubLayout(); - FirstView firstView = new FirstView(); - AnotherView anotherView = new AnotherView(); - - List oldLayouts = Arrays.asList(subLayout, mainLayout); - List newLayouts = Collections.singletonList(mainLayout); - - Location location = Mockito.mock(Location.class); - setUpInitialPush(); - - internals.showRouteTarget(location, firstView, oldLayouts); - List activeRouterTargetsChain = internals - .getActiveRouterTargetsChain(); - - // Initial router layouts hierarchy is checked here in order to be - // sure the sub layout and it's child view is in place BEFORE - // navigation and old content cleanup - Assert.assertArrayEquals("Unexpected initial router targets chain", - new HasElement[] { firstView, subLayout, mainLayout }, - activeRouterTargetsChain.toArray()); - - Assert.assertEquals( - "Expected one child element for main layout before navigation", - 1, mainLayout.getElement().getChildren().count()); - @SuppressWarnings("OptionalGetWithoutIsPresent") - Element subLayoutElement = mainLayout.getElement().getChildren() - .findFirst().get(); - Assert.assertEquals("Unexpected sub layout element", SubLayout.ID, - subLayoutElement.getAttribute("id")); - Assert.assertEquals( - "Expected one child element for sub layout before navigation", - 1, subLayoutElement.getChildren().count()); - @SuppressWarnings("OptionalGetWithoutIsPresent") - Element firstViewElement = subLayoutElement.getChildren().findFirst() - .get(); - Assert.assertEquals("Unexpected first view element", FirstView.ID, - firstViewElement.getAttribute("id")); - - // Trigger navigation - internals.showRouteTarget(location, anotherView, newLayouts); - activeRouterTargetsChain = internals.getActiveRouterTargetsChain(); - Assert.assertArrayEquals( - "Unexpected router targets chain after navigation", - new HasElement[] { anotherView, mainLayout }, - activeRouterTargetsChain.toArray()); - - // Check that the old content (sub layout) is detached and it's - // children are also detached - Assert.assertEquals( - "Expected one child element for main layout after navigation", - 1, mainLayout.getElement().getChildren().count()); - @SuppressWarnings("OptionalGetWithoutIsPresent") - Element anotherViewElement = mainLayout.getElement().getChildren() - .findFirst().get(); - Assert.assertEquals("Unexpected another view element", AnotherView.ID, - anotherViewElement.getAttribute("id")); - Assert.assertEquals( - "Expected no child elements for sub layout after navigation", 0, - subLayout.getElement().getChildren().count()); - } - - @Test - public void showRouteTarget_navigateToAnotherLayoutHierarchy_detachedLayoutHierarchyChildrenRemoved() { - MainLayout mainLayout = new MainLayout(); - SubLayout subLayout = new SubLayout(); - FirstView firstView = new FirstView(); - AnotherLayout anotherLayout = new AnotherLayout(); - AnotherView anotherView = new AnotherView(); - - List oldLayouts = Arrays.asList(subLayout, mainLayout); - List newLayouts = Collections - .singletonList(anotherLayout); - - Location location = Mockito.mock(Location.class); - setUpInitialPush(); - - // Initial navigation - internals.showRouteTarget(location, firstView, oldLayouts); - // Navigate to another view outside of the initial router hierarchy - internals.showRouteTarget(location, anotherView, newLayouts); - List activeRouterTargetsChain = internals - .getActiveRouterTargetsChain(); - Assert.assertArrayEquals( - "Unexpected router targets chain after navigation", - new HasElement[] { anotherView, anotherLayout }, - activeRouterTargetsChain.toArray()); - - // Check that both main layout, sub layout and it's child view are - // detached - Assert.assertEquals( - "Expected no child elements for main layout after navigation", - 0, mainLayout.getElement().getChildren().count()); - Assert.assertEquals( - "Expected no child elements for sub layout after navigation", 0, - subLayout.getElement().getChildren().count()); - } - - private PushConfiguration setUpInitialPush() { - DeploymentConfiguration config = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(vaadinService.getDeploymentConfiguration()) - .thenReturn(config); - - PushConfiguration pushConfig = Mockito.mock(PushConfiguration.class); - Mockito.when(ui.getPushConfiguration()).thenReturn(pushConfig); - - Mockito.when(config.getPushMode()).thenReturn(PushMode.DISABLED); - return pushConfig; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/page/ExtendedClientDetailsTest.java b/flow-server/src/test/java/com/vaadin/flow/component/page/ExtendedClientDetailsTest.java deleted file mode 100644 index da39b89156b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/page/ExtendedClientDetailsTest.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component.page; - -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.WebBrowser; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -public class ExtendedClientDetailsTest { - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - @Test - public void initializeWithClientValues_gettersReturnExpectedValues() { - final ExtendedClientDetails details = new ExtendBuilder() - .buildDetails(); - - Assert.assertEquals(2560, details.getScreenWidth()); - Assert.assertEquals(1450, details.getScreenHeight()); - Assert.assertEquals(2400, details.getWindowInnerWidth()); - Assert.assertEquals(1400, details.getWindowInnerHeight()); - Assert.assertEquals(1600, details.getBodyClientWidth()); - Assert.assertEquals(1360, details.getBodyClientHeight()); - Assert.assertEquals(16200000, details.getTimezoneOffset()); - Assert.assertEquals("Asia/Tehran", details.getTimeZoneId()); - Assert.assertEquals(12600000, details.getRawTimezoneOffset()); - Assert.assertEquals(3600000, details.getDSTSavings()); - Assert.assertEquals(true, details.isDSTInEffect()); - Assert.assertEquals(false, details.isTouchDevice()); - Assert.assertEquals(2.0D, details.getDevicePixelRatio(), 0.0); - Assert.assertEquals("ROOT-1234567-0.1234567", details.getWindowName()); - Assert.assertFalse(details.isIPad()); - - // Don't test getCurrentDate() and time delta due to the dependency on - // server-side time - } - - @Test - public void differentNavigatorPlatformDetails_isIPadReturnsExpectedValue() { - ExtendBuilder detailsBuilder = new ExtendBuilder(); - - ExtendedClientDetails details = detailsBuilder.buildDetails(); - Assert.assertFalse("Linux is not an iPad", details.isIPad()); - - detailsBuilder.setNavigatorPlatform("iPad"); - details = detailsBuilder.buildDetails(); - - Assert.assertTrue("'iPad' is an iPad", details.isIPad()); - - // See https://github.com/vaadin/flow/issues/14517 - detailsBuilder.setNavigatorPlatform("MacIntel"); - details = detailsBuilder.buildDetails(); - Assert.assertFalse("MacIntel on non touch device is not an iPad", - details.isIPad()); - - // See https://github.com/vaadin/flow/issues/14517 - detailsBuilder.setTouchDevice("true"); - details = detailsBuilder.buildDetails(); - Assert.assertTrue("MacIntel on touch device is an iPad", - details.isIPad()); - } - - @Test - public void differentNavigatorPlatformDetails_Ipod_isIOSReturnsExpectedValue() { - ExtendedClientDetails details = new ExtendBuilder() - .setNavigatorPlatform("iPod ..").buildDetails(); - - VaadinSession session = Mockito.mock(VaadinSession.class); - CurrentInstance.setCurrent(session); - WebBrowser browser = Mockito.mock(WebBrowser.class); - Mockito.when(session.getBrowser()).thenReturn(browser); - Mockito.when(browser.isIPhone()).thenReturn(false); - - Assert.assertTrue(details.isIOS()); - - CurrentInstance.clearAll(); - } - - @Test - public void isIOS_isIPad_returnsTrue() { - ExtendedClientDetails details = Mockito - .mock(ExtendedClientDetails.class); - Mockito.doCallRealMethod().when(details).isIOS(); - Mockito.when(details.isIPad()).thenReturn(true); - - Assert.assertTrue(details.isIOS()); - } - - @Test - public void isIOS_notIPadIsIPhone_returnsTrue() { - ExtendedClientDetails details = Mockito - .mock(ExtendedClientDetails.class); - Mockito.doCallRealMethod().when(details).isIOS(); - - VaadinSession session = Mockito.mock(VaadinSession.class); - VaadinSession.setCurrent(session); - - WebBrowser browser = Mockito.mock(WebBrowser.class); - Mockito.when(session.getBrowser()).thenReturn(browser); - - Mockito.when(browser.isIPhone()).thenReturn(true); - - Assert.assertTrue(details.isIOS()); - } - - @Test - public void isIOS_notIPad_notIsIPhone_returnsFalse() { - ExtendedClientDetails details = Mockito - .mock(ExtendedClientDetails.class); - Mockito.doCallRealMethod().when(details).isIOS(); - - VaadinSession session = Mockito.mock(VaadinSession.class); - VaadinSession.setCurrent(session); - - WebBrowser browser = Mockito.mock(WebBrowser.class); - Mockito.when(session.getBrowser()).thenReturn(browser); - Mockito.when(browser.isIPhone()).thenReturn(false); - - Assert.assertFalse(details.isIOS()); - } - - /** - * Builder to create modified extended details. Default values apply. - */ - private class ExtendBuilder { - private String screenWidth = "2560"; - private String screenHeight = "1450"; - private String windowInnerWidth = "2400"; - private String windowInnerHeight = "1400"; - private String bodyClientWidth = "1600"; - private String bodyClientHeight = "1360"; - private String timezoneOffset = "-270"; // minutes from UTC - private String rawTimezoneOffset = "-210"; // minutes from UTC without - // DST - private String dstSavings = "60"; // dist shift amount - private String dstInEffect = "true"; - private String timeZoneId = "Asia/Tehran"; - private String clientServerTimeDelta = "1555000000000"; // Apr 11 2019 - private String touchDevice = "false"; - private String devicePixelRatio = "2.0"; - private String windowName = "ROOT-1234567-0.1234567"; - private String navigatorPlatform = "Linux i686"; - - public ExtendedClientDetails buildDetails() { - return new ExtendedClientDetails(screenWidth, screenHeight, - windowInnerWidth, windowInnerHeight, bodyClientWidth, - bodyClientHeight, timezoneOffset, rawTimezoneOffset, - dstSavings, dstInEffect, timeZoneId, clientServerTimeDelta, - touchDevice, devicePixelRatio, windowName, - navigatorPlatform); - } - - public ExtendBuilder setScreenWidth(String screenWidth) { - this.screenWidth = screenWidth; - return this; - } - - public ExtendBuilder setScreenHeight(String screenHeight) { - this.screenHeight = screenHeight; - return this; - } - - public ExtendBuilder setWindowInnerWidth(String windowInnerWidth) { - this.windowInnerWidth = windowInnerWidth; - return this; - } - - public ExtendBuilder setWindowInnerHeight(String windowInnerHeight) { - this.windowInnerHeight = windowInnerHeight; - return this; - } - - public ExtendBuilder setBodyClientWidth(String bodyClientWidth) { - this.bodyClientWidth = bodyClientWidth; - return this; - } - - public ExtendBuilder setBodyClientHeight(String bodyClientHeight) { - this.bodyClientHeight = bodyClientHeight; - return this; - } - - public ExtendBuilder setTimezoneOffset(String timezoneOffset) { - this.timezoneOffset = timezoneOffset; - return this; - } - - public ExtendBuilder setRawTimezoneOffset(String rawTimezoneOffset) { - this.rawTimezoneOffset = rawTimezoneOffset; - return this; - } - - public ExtendBuilder setDstSavings(String dstSavings) { - this.dstSavings = dstSavings; - return this; - } - - public ExtendBuilder setDstInEffect(String dstInEffect) { - this.dstInEffect = dstInEffect; - return this; - } - - public ExtendBuilder setTimeZoneId(String timeZoneId) { - this.timeZoneId = timeZoneId; - return this; - } - - public ExtendBuilder setClientServerTimeDelta( - String clientServerTimeDelta) { - this.clientServerTimeDelta = clientServerTimeDelta; - return this; - } - - public ExtendBuilder setTouchDevice(String touchDevice) { - this.touchDevice = touchDevice; - return this; - } - - public ExtendBuilder setDevicePixelRatio(String devicePixelRatio) { - this.devicePixelRatio = devicePixelRatio; - return this; - } - - public ExtendBuilder setWindowName(String windowName) { - this.windowName = windowName; - return this; - } - - public ExtendBuilder setNavigatorPlatform(String navigatorPlatform) { - this.navigatorPlatform = navigatorPlatform; - return this; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/page/HistoryTest.java b/flow-server/src/test/java/com/vaadin/flow/component/page/HistoryTest.java deleted file mode 100644 index 8dfc17f1afb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/page/HistoryTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component.page; - -import java.io.Serializable; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.UI; - -import elemental.json.Json; -import elemental.json.JsonString; - -public class HistoryTest { - - private class TestUI extends UI { - @Override - public Page getPage() { - return page; - } - } - - private class TestPage extends Page { - - private String expression; - - private Serializable[] parameters; - - public TestPage(UI ui) { - super(ui); - } - - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... parameters) { - this.expression = expression; - this.parameters = parameters; - return null; - } - } - - private UI ui = new TestUI(); - private TestPage page = new TestPage(ui); - private History history; - - @Before - public void setup() { - history = new History(ui); - } - - @Test - public void pushState_locationWithQueryParameters_queryParametersRetained() { - history.pushState(Json.create("{foo:bar;}"), "context/view?param=4"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.pushState($0, '', $1))", - page.expression); - Assert.assertEquals("push state not included", "{foo:bar;}", - ((JsonString) page.parameters[0]).getString()); - Assert.assertEquals("invalid location", "context/view?param=4", - page.parameters[1]); - - history.pushState(Json.create("{foo:bar;}"), "context/view/?param=4"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.pushState($0, '', $1))", - page.expression); - Assert.assertEquals("push state not included", "{foo:bar;}", - ((JsonString) page.parameters[0]).getString()); - Assert.assertEquals("invalid location", "context/view/?param=4", - page.parameters[1]); - } - - @Test - public void pushState_locationWithFragment_fragmentRetained() { - history.pushState(null, "context/view#foobar"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.pushState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("fragment not retained", "context/view#foobar", - page.parameters[1]); - - history.pushState(null, "context/view/#foobar"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.pushState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("fragment not retained", "context/view/#foobar", - page.parameters[1]); - } - - @Test // #11628 - public void pushState_locationWithQueryParametersAndFragment_QueryParametersAndFragmentRetained() { - history.pushState(null, "context/view?foo=bar#foobar"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.pushState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("invalid location", "context/view?foo=bar#foobar", - page.parameters[1]); - - history.pushState(null, "context/view/?foo=bar#foobar"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.pushState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("invalid location", "context/view/?foo=bar#foobar", - page.parameters[1]); - } - - @Test // #11628 - public void replaceState_locationWithQueryParametersAndFragment_QueryParametersAndFragmentRetained() { - history.replaceState(null, "context/view?foo=bar#foobar"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.replaceState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("invalid location", "context/view?foo=bar#foobar", - page.parameters[1]); - - history.replaceState(null, "context/view/?foo=bar#foobar"); - - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.replaceState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("invalid location", "context/view/?foo=bar#foobar", - page.parameters[1]); - } - - @Test // #11628 - public void replaceState_locationEmpty_pushesPeriod() { - history.replaceState(null, ""); - Assert.assertEquals("push state JS not included", - "setTimeout(() => window.history.replaceState($0, '', $1))", - page.expression); - Assert.assertEquals(null, page.parameters[0]); - Assert.assertEquals("location should be '.'", ".", page.parameters[1]); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/page/PageTest.java b/flow-server/src/test/java/com/vaadin/flow/component/page/PageTest.java deleted file mode 100644 index afd65071121..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/page/PageTest.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component.page; - -import java.io.Serializable; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.Page.ExecutionCanceler; -import com.vaadin.flow.function.SerializableConsumer; -import com.vaadin.flow.internal.JsonUtils; -import com.vaadin.flow.shared.Registration; -import com.vaadin.flow.shared.ui.Dependency; -import com.vaadin.flow.shared.ui.LoadMode; -import com.vaadin.tests.util.MockUI; - -import elemental.json.Json; -import elemental.json.JsonValue; - -public class PageTest { - - private class TestUI extends UI { - @Override - public Page getPage() { - return page; - } - } - - private class TestPage extends Page { - - private int count = 0; - - private String expression; - - private Serializable firstParam; - - public TestPage(UI ui) { - super(ui); - } - - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... parameters) { - this.expression = expression; - firstParam = parameters[0]; - count++; - return null; - } - } - - private UI ui = new TestUI(); - - private TestPage page = new TestPage(ui); - - private BrowserWindowResizeListener listener = event -> { - }; - - @Test(expected = NullPointerException.class) - - public void addNullAsAListener_trows() { - page.addBrowserWindowResizeListener(null); - } - - @Test - public void addListener_executeInitJs() { - page.addBrowserWindowResizeListener(listener); - - MatcherAssert.assertThat(page.expression, - CoreMatchers.allOf(CoreMatchers.containsString("init"), - CoreMatchers.containsString("resize"))); - - Assert.assertTrue(page.firstParam instanceof Component); - } - - @Test - public void addTwoListeners_jsIsExecutedOnce() { - page.addBrowserWindowResizeListener(listener); - page.addBrowserWindowResizeListener(event -> { - }); - - Assert.assertEquals(1, page.count); - } - - @Test - public void addTwoListeners_unregisterOneListener_jsListenerIsNotRemoved() { - page.addBrowserWindowResizeListener(listener); - Registration registration = page - .addBrowserWindowResizeListener(event -> { - }); - - registration.remove(); - - Assert.assertEquals(1, page.count); - - // remove the same listener one more time - registration.remove(); - - Assert.assertEquals(1, page.count); - } - - @Test - public void addTwoListeners_unregisterTwoListeners_jsListenerIsRemoved() { - Registration registration1 = page - .addBrowserWindowResizeListener(listener); - Registration registration2 = page - .addBrowserWindowResizeListener(event -> { - }); - - registration1.remove(); - registration2.remove(); - - Assert.assertEquals(2, page.count); - - Assert.assertEquals("$0.resizeRemove()", page.expression); - - Assert.assertTrue(page.firstParam instanceof Component); - } - - @Test - public void addListener_unregisterListener_addListener_jsListenerIsRemovedAndInitialized() { - Registration registration = page - .addBrowserWindowResizeListener(listener); - - registration.remove(); - // remove several times - registration.remove(); - - Assert.assertEquals(2, page.count); - - Assert.assertEquals("$0.resizeRemove()", page.expression); - - page.addBrowserWindowResizeListener(listener); - - Assert.assertEquals(3, page.count); - - MatcherAssert.assertThat(page.expression, - CoreMatchers.allOf(CoreMatchers.containsString("init"), - CoreMatchers.containsString("resize"))); - - Assert.assertTrue(page.firstParam instanceof Component); - } - - @Test - public void retrieveExtendedClientDetails_twice_theSecondResultComesDifferentBeforeCachedValueIsSet() { - // given - final UI mockUI = new MockUI(); - List invocations = new ArrayList<>(); - final Page page = new Page(mockUI) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... params) { - super.executeJs(expression, params); - - return new PendingJavaScriptResult() { - - @Override - public boolean cancelExecution() { - return false; - } - - @Override - public boolean isSentToBrowser() { - return false; - } - - @Override - public void then( - SerializableConsumer resultHandler, - SerializableConsumer errorHandler) { - final HashMap params = new HashMap<>(); - params.put("v-sw", "2560"); - params.put("v-sh", "1450"); - params.put("v-tzo", "-270"); - params.put("v-rtzo", "-210"); - params.put("v-dstd", "60"); - params.put("v-dston", "true"); - params.put("v-tzid", "Asia/Tehran"); - params.put("v-curdate", "1555000000000"); - params.put("v-td", "false"); - if (invocations.isEmpty()) { - params.put("v-wn", "ROOT-1234567-0.1234567"); - } else { - params.put("v-wn", "foo"); - } - invocations.add(() -> resultHandler.accept( - JsonUtils.createObject(params, Json::create))); - } - }; - } - }; - final AtomicInteger callbackInvocations = new AtomicInteger(); - final Page.ExtendedClientDetailsReceiver receiver = details -> { - callbackInvocations.incrementAndGet(); - }; - - // when - page.retrieveExtendedClientDetails(receiver); - page.retrieveExtendedClientDetails(receiver); - - // then : before cached value is set the second retrieve is requested - invocations.forEach(Runnable::run); - - Assert.assertEquals(2, callbackInvocations.get()); - - Assert.assertEquals("ROOT-1234567-0.1234567", mockUI.getInternals() - .getExtendedClientDetails().getWindowName()); - } - - @Test - public void retrieveExtendedClientDetails_twice_jsOnceAndCallbackTwice() { - // given - final UI mockUI = new MockUI(); - final Page page = new Page(mockUI) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... params) { - super.executeJs(expression, params); - - return new PendingJavaScriptResult() { - - @Override - public boolean cancelExecution() { - return false; - } - - @Override - public boolean isSentToBrowser() { - return false; - } - - @Override - public void then( - SerializableConsumer resultHandler, - SerializableConsumer errorHandler) { - final HashMap params = new HashMap<>(); - params.put("v-sw", "2560"); - params.put("v-sh", "1450"); - params.put("v-tzo", "-270"); - params.put("v-rtzo", "-210"); - params.put("v-dstd", "60"); - params.put("v-dston", "true"); - params.put("v-tzid", "Asia/Tehran"); - params.put("v-curdate", "1555000000000"); - params.put("v-td", "false"); - params.put("v-wn", "ROOT-1234567-0.1234567"); - resultHandler.accept( - JsonUtils.createObject(params, Json::create)); - } - }; - } - }; - final AtomicInteger callbackInvocations = new AtomicInteger(); - final Page.ExtendedClientDetailsReceiver receiver = details -> { - callbackInvocations.incrementAndGet(); - }; - - // when - page.retrieveExtendedClientDetails(receiver); - page.retrieveExtendedClientDetails(receiver); - - // then - final int jsInvocations = mockUI.getInternals() - .dumpPendingJavaScriptInvocations().size(); - Assert.assertEquals(1, jsInvocations); - Assert.assertEquals(2, callbackInvocations.get()); - } - - @Test - public void fetchCurrentUrl_consumerReceivesCorrectURL() { - // given - final UI mockUI = new MockUI(); - final Page page = new Page(mockUI) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... params) { - super.executeJs(expression, params); - Assert.assertEquals( - "Expected javascript for fetching location is wrong.", - "return window.location.href", expression); - - return new PendingJavaScriptResult() { - - @Override - public boolean cancelExecution() { - return false; - } - - @Override - public boolean isSentToBrowser() { - return false; - } - - @Override - public void then( - SerializableConsumer resultHandler, - SerializableConsumer errorHandler) { - resultHandler.accept( - Json.create("http://localhost:8080/home")); - } - }; - } - }; - final AtomicReference callbackInvocations = new AtomicReference<>(); - final SerializableConsumer receiver = details -> { - callbackInvocations.compareAndSet(null, details); - }; - - // when - page.fetchCurrentURL(receiver); - - // then - Assert.assertEquals("Returned URL was wrong", - "http://localhost:8080/home", - callbackInvocations.get().toString()); - } - - @Test - public void fetchCurrentUrl_passNullCallback_throwsNullPointerException() { - Assert.assertThrows(NullPointerException.class, () -> { - final UI mockUI = new MockUI(); - Page page = new Page(mockUI); - page.fetchCurrentURL(null); - }); - } - - @Test - public void addJsModule_accepts_onlyExternalAndStartingSlash() { - List urls = new LinkedList<>(); - urls.add("http://sample.com/mod.js"); - urls.add("https://sample.com/mod.js"); - urls.add("//sample.com/mod.js"); - urls.add("/mod.js"); - - for (String url : urls) { - page.addJsModule(url); - } - - Collection pendingSendToClient = ui.getInternals() - .getDependencyList().getPendingSendToClient(); - - Assert.assertEquals("There should be 4 dependencies added.", 4, - pendingSendToClient.size()); - - for (Dependency dependency : pendingSendToClient) { - Assert.assertEquals("Dependency should be a JSModule", - Dependency.Type.JS_MODULE, dependency.getType()); - Assert.assertEquals("JS module dependency should be EAGER", - LoadMode.EAGER, dependency.getLoadMode()); - - Assert.assertTrue( - "Dependency " + dependency.getUrl() - + " is not found in the source list.", - urls.contains(dependency.getUrl())); - - urls.remove(dependency.getUrl()); - } - - Assert.assertEquals("Not all urls were added as dependencies", 0, - urls.size()); - } - - @Test - public void addJsModule_rejects_files() { - try { - page.addJsModule("mod.js"); - - Assert.fail( - "Adding a file without starting \"/\" is not to be allowed."); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void executeJavaScript_delegatesToExecJs() { - AtomicReference invokedExpression = new AtomicReference<>(); - AtomicReference invokedParams = new AtomicReference<>(); - - Page page = new Page(new MockUI()) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... parameters) { - String oldExpression = invokedExpression.getAndSet(expression); - Assert.assertNull("There should be no old expression", - oldExpression); - - Serializable[] oldParams = invokedParams.getAndSet(parameters); - Assert.assertNull("There should be no old params", oldParams); - - return null; - } - }; - - ExecutionCanceler executionCanceler = page.executeJavaScript("foo", 1, - true); - - Assert.assertNull(executionCanceler); - - Assert.assertEquals("foo", invokedExpression.get()); - Assert.assertEquals(Integer.valueOf(1), invokedParams.get()[0]); - Assert.assertEquals(Boolean.TRUE, invokedParams.get()[1]); - } - - @Test - public void open_openInSameWindow_closeTheClientApplication() { - AtomicReference capture = new AtomicReference<>(); - List params = new ArrayList<>(); - Page page = new Page(new MockUI()) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable[] parameters) { - capture.set(expression); - params.addAll(Arrays.asList(parameters)); - return Mockito.mock(PendingJavaScriptResult.class); - } - }; - - page.setLocation("foo"); - - // self check - Assert.assertEquals("_self", params.get(1)); - - MatcherAssert.assertThat(capture.get(), CoreMatchers - .startsWith("if ($1 == '_self') this.stopApplication();")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/polymertemplate/EventHandler.java b/flow-server/src/test/java/com/vaadin/flow/component/polymertemplate/EventHandler.java deleted file mode 100644 index 16f739cb4b1..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/polymertemplate/EventHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.component.polymertemplate; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.vaadin.flow.dom.DisabledUpdateMode; - -/** - * - * This class here is for testing purpose: it's impossible to test polymer - * templates related code which has not been moved to a separate module. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.METHOD }) -public @interface EventHandler { - - DisabledUpdateMode value() default DisabledUpdateMode.ONLY_WHEN_ENABLED; -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/polymertemplate/RepeatIndex.java b/flow-server/src/test/java/com/vaadin/flow/component/polymertemplate/RepeatIndex.java deleted file mode 100644 index e40a0d93e26..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/polymertemplate/RepeatIndex.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component.polymertemplate; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This class here is for testing purpose: it's impossible to test polymer - * templates related code which has not been moved to a separate module. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.PARAMETER }) -public @interface RepeatIndex { -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/webcomponent/WebComponentTest.java b/flow-server/src/test/java/com/vaadin/flow/component/webcomponent/WebComponentTest.java deleted file mode 100644 index b900907afa2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/webcomponent/WebComponentTest.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component.webcomponent; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.server.webcomponent.PropertyConfigurationImpl; -import com.vaadin.flow.server.webcomponent.WebComponentBinding; - -import elemental.json.Json; -import elemental.json.JsonValue; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -public class WebComponentTest { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private WebComponent webComponent; - - @Before - public void init() { - WebComponentBinding componentBinding = new WebComponentBinding<>( - mock(Component.class)); - webComponent = new WebComponent<>(componentBinding, new Element("tag")); - } - - @Test - public void fireEvent_throwsWhenNameIsNull() { - exception.expect(NullPointerException.class); - exception.expectMessage("eventName"); - webComponent.fireEvent(null); - } - - @Test - public void fireEvent_doesNotThrowOnNullObjectData() { - webComponent.fireEvent("name", null); - } - - @Test - public void fireEvent_throwsWhenOptionsIsNull() { - exception.expect(NullPointerException.class); - exception.expectMessage("options"); - webComponent.fireEvent("name", null, null); - } - - @Test - public void setProperty_throwsOnNullPropertyConfiguration() { - exception.expect(NullPointerException.class); - exception.expectMessage("propertyConfiguration"); - webComponent.setProperty(null, "value"); - } - - @Test - public void setProperty_throwsOnUnknownProperty() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage( - "WebComponent does not have a property identified"); - - WebComponentBinding binding = new WebComponentBinding<>( - mock(Component.class)); - - WebComponent webComponent = new WebComponent<>(binding, - new Element("tag")); - - PropertyConfigurationImpl configuration = new PropertyConfigurationImpl<>( - Component.class, "property", String.class, "value"); - - webComponent.setProperty(configuration, "newValue"); - } - - @Test - public void setProperty_throwsWhenGivenWrongPropertyTypeAsParameter() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Property 'property' of type " - + "'java.lang.Integer' cannot be assigned value of type " - + "'java.lang.String'!"); - - PropertyConfigurationImpl intConfiguration = new PropertyConfigurationImpl<>( - Component.class, "property", Integer.class, 0); - - WebComponentBinding binding = new WebComponentBinding<>( - mock(Component.class)); - binding.bindProperty(intConfiguration, false, null); - - WebComponent webComponent = new WebComponent<>(binding, - new Element("tag")); - - PropertyConfigurationImpl stringConfiguration = new PropertyConfigurationImpl<>( - Component.class, "property", String.class, "value"); - - webComponent.setProperty(stringConfiguration, "newValue"); - } - - @Test - public void setProperty_attemptsToWriteSupportedTypes() { - Element element = spy(new Element("tag")); - - // configurations - PropertyConfigurationImpl intConfiguration = new PropertyConfigurationImpl<>( - Component.class, "int", Integer.class, 0); - PropertyConfigurationImpl doubleConfiguration = new PropertyConfigurationImpl<>( - Component.class, "double", Double.class, 0.0); - PropertyConfigurationImpl stringConfiguration = new PropertyConfigurationImpl<>( - Component.class, "string", String.class, ""); - PropertyConfigurationImpl booleanConfiguration = new PropertyConfigurationImpl<>( - Component.class, "boolean", Boolean.class, false); - PropertyConfigurationImpl jsonConfiguration = new PropertyConfigurationImpl<>( - Component.class, "json", JsonValue.class, Json.createNull()); - - // binding - WebComponentBinding binding = new WebComponentBinding<>( - mock(Component.class)); - binding.bindProperty(intConfiguration, false, null); - binding.bindProperty(doubleConfiguration, false, null); - binding.bindProperty(stringConfiguration, false, null); - binding.bindProperty(booleanConfiguration, false, null); - binding.bindProperty(jsonConfiguration, false, null); - - // test - WebComponent webComponent = new WebComponent<>(binding, - element); - - webComponent.setProperty(intConfiguration, 1); - verify(element, Mockito.times(1)).executeJs( - ArgumentMatchers.anyString(), ArgumentMatchers.any(), - ArgumentMatchers.any()); - webComponent.setProperty(doubleConfiguration, 1.0); - verify(element, Mockito.times(2)).executeJs( - ArgumentMatchers.anyString(), ArgumentMatchers.any(), - ArgumentMatchers.any()); - webComponent.setProperty(stringConfiguration, "asd"); - verify(element, Mockito.times(3)).executeJs( - ArgumentMatchers.anyString(), ArgumentMatchers.any(), - ArgumentMatchers.any()); - webComponent.setProperty(booleanConfiguration, true); - verify(element, Mockito.times(4)).executeJs( - ArgumentMatchers.anyString(), ArgumentMatchers.any(), - ArgumentMatchers.any()); - // JsonValue has a different number of arguments - webComponent.setProperty(jsonConfiguration, Json.create(true)); - verify(element, Mockito.times(5)).executeJs( - ArgumentMatchers.anyString(), ArgumentMatchers.any()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/component/webcomponent/WebComponentWrapperTest.java b/flow-server/src/test/java/com/vaadin/flow/component/webcomponent/WebComponentWrapperTest.java deleted file mode 100644 index 267588c2daa..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/component/webcomponent/WebComponentWrapperTest.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.component.webcomponent; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.MockInstantiator; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.webcomponent.WebComponentBinding; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; - -import elemental.json.Json; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class WebComponentWrapperTest { - - private static final String MSG_PROPERTY = "message"; - private static final String INT_PROPERTY = "integer-value"; - private static final String BOOLEAN_PROPERTY = "boolean-value"; - - private Element element; - private MyComponent component; - private WebComponentBinding binding; - private WebComponentExporter exporter; - private WebComponentWrapper wrapper; - - @Before - public void init() { - element = new Element("tag"); - exporter = new MyComponentExporter(); - - // make component available and bind properties to it - binding = (WebComponentBinding) new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter).createWebComponentBinding( - new MockInstantiator(), element, Json.createObject()); - wrapper = new WebComponentWrapper(element, binding); - component = binding.getComponent(); - } - - @Test - public void wrappedMyComponent_syncSetsCorrectValuesToFields() { - wrapper.sync(MSG_PROPERTY, Json.create("MyMessage")); - - Assert.assertEquals("Message field should have updated with new value", - "MyMessage", component.message); - - wrapper.sync(INT_PROPERTY, Json.create(10)); - - Assert.assertEquals( - "IntegerValue field should contain a matching integer value", - 10, component.integerValue); - } - - @Test - public void wrappedComponentPropertyListener_listenerFiredWithCorrectValuesOnSync() { - wrapper.sync(MSG_PROPERTY, Json.create("one")); - wrapper.sync(INT_PROPERTY, Json.create(2)); - wrapper.sync(MSG_PROPERTY, Json.create("three")); - wrapper.sync(INT_PROPERTY, Json.create(4)); - - // 3, since creation sets the initial value - Assert.assertEquals("Three string messages should have come through", 3, - component.oldMessages.size()); - - // 3, since creation sets the initial value - Assert.assertEquals("Three integer messages should have come through", - 3, component.oldIntegers.size()); - - Assert.assertEquals("String messages arrived in correct order", - Arrays.asList("", "one", "three"), component.oldMessages); - - Assert.assertEquals("Integer messages arrived in correct order", - Arrays.asList(0, 2, 4), component.oldIntegers); - - } - - @Test - public void exportingExtendedComponent_inheritedFieldsAreAvailableAndOverridden() { - WebComponentBinding binding = constructWrapperAndGetBinding( - new MyExtensionExporter(), null, null); - - MyExtension component = binding.getComponent(); - - wrapper.sync(MSG_PROPERTY, Json.create("one")); - wrapper.sync(INT_PROPERTY, Json.create(2)); - wrapper.sync(MSG_PROPERTY, Json.create("three")); - wrapper.sync(INT_PROPERTY, Json.create(4)); - - // 3, since creation sets the initial value - Assert.assertEquals("Three string messages should have come through", 3, - component.oldMessages.size()); - - // 3, since creation sets the initial value - Assert.assertEquals("Three integer messages should have come through", - 3, component.oldIntegers.size()); - - Assert.assertEquals("String messages arrived in correct order", - Arrays.asList("Extended ", "Extended one", "Extended three"), - component.oldMessages); - - Assert.assertEquals("Integer messages arrived in correct order", - Arrays.asList(0, 2, 4), component.oldIntegers); - } - - @Test - public void extendedExporter_propertiesAreOverwrittenAndAvailable() { - WebComponentBinding binding = constructWrapperAndGetBinding( - new ExtendedExporter(), null, null); - - MyComponent component = binding.getComponent(); - - wrapper.sync(MSG_PROPERTY, Json.create("one")); - wrapper.sync(INT_PROPERTY, Json.create(2)); - wrapper.sync(MSG_PROPERTY, Json.create("three")); - wrapper.sync(INT_PROPERTY, Json.create(4)); - wrapper.sync(BOOLEAN_PROPERTY, Json.create(true)); - - // 3, since creation sets the initial value - Assert.assertEquals("Three string messages should have come through", 3, - component.oldMessages.size()); - - // 3, since creation sets the initial value - Assert.assertEquals("Three integer messages should have come through", - 3, component.oldIntegers.size()); - - Assert.assertEquals("String messages arrived in correct order", - Arrays.asList("Default", "one", "three"), - component.oldMessages); - - Assert.assertEquals("Integer messages arrived in correct order", - Arrays.asList(0, 2, 4), component.oldIntegers); - - Assert.assertTrue("Boolean property should have been set to true", - component.booleanValue); - } - - @Test - public void disconnectReconnect_componentIsNotCleaned() { - Element element = new Element("tag"); - WebComponentUI ui = constructWebComponentUI(element); - constructWrapperAndGetBinding(new MyComponentExporter(), element, ui); - UIInternals internals = ui.getInternals(); - - wrapper.disconnected(); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis()); - - Assert.assertTrue("Wrapper should still be connected on the server", - wrapper.getParent().isPresent()); - - wrapper.reconnect(); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis() + 1200); - - Assert.assertTrue("Wrapper should stay connected on the server", - wrapper.getParent().isPresent()); - } - - @Test - public void disconnectOnClient_componentIsCleaned() { - Element element = new Element("tag"); - WebComponentUI ui = constructWebComponentUI(element); - constructWrapperAndGetBinding(new MyComponentExporter(), element, ui); - UIInternals internals = ui.getInternals(); - - wrapper.disconnected(); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis()); - - Assert.assertTrue("Wrapper should still be connected on the server", - wrapper.getParent().isPresent()); - - internals.setLastHeartbeatTimestamp(System.currentTimeMillis() + 1200); - - Assert.assertFalse( - "Wrapper should have been disconnected also on the server", - wrapper.getParent().isPresent()); - } - - /** - * @param exporter - * exporter of the correct type, defines C - * @param element - * nullable root element - * @param ui - * nullable WebComponentUI - * @param - * type of the exported component - * @return web component wrapper - */ - private WebComponentBinding constructWrapperAndGetBinding( - WebComponentExporter exporter, Element element, - WebComponentUI ui) { - if (element == null) { - element = new Element("tag"); - } - WebComponentBinding binding = (WebComponentBinding) new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter).createWebComponentBinding( - new MockInstantiator(), element, Json.createObject()); - wrapper = new WebComponentWrapper(element, binding) { - @Override - public Optional getUI() { - return Optional.of(ui); - } - }; - return binding; - } - - private static WebComponentUI constructWebComponentUI( - Element wrapperElement) { - WebComponentUI ui = mock(WebComponentUI.class); - when(ui.getUI()).thenReturn(Optional.of(ui)); - Element body = new Element("body"); - when(ui.getElement()).thenReturn(body); - - UIInternals internals = new UIInternals(ui); - internals.setSession( - new AlwaysLockedVaadinSession(mock(VaadinService.class))); - when(ui.getInternals()).thenReturn(internals); - - Component parent = new Parent(); - parent.getElement().appendVirtualChild(wrapperElement); - - VaadinSession session = mock(VaadinSession.class); - DeploymentConfiguration configuration = mock( - DeploymentConfiguration.class); - - when(ui.getSession()).thenReturn(session); - when(session.getConfiguration()).thenReturn(configuration); - when(configuration.getWebComponentDisconnect()).thenReturn(1); - - return ui; - } - - @Tag("my-component") - public static class MyComponent extends Component { - ArrayList oldMessages = new ArrayList<>(); - ArrayList oldIntegers = new ArrayList<>(); - protected String message; - int integerValue; - boolean booleanValue; - - public MyComponent() { - super(new Element("div")); - } - - public void setMessage(String message) { - oldMessages.add(message); - this.message = message; - } - - public void setIntegerValue(int integerValue) { - this.oldIntegers.add(integerValue); - this.integerValue = integerValue; - } - - public void setBooleanValue(boolean value) { - booleanValue = value; - } - } - - public static class MyExtension extends MyComponent { - @Override - public void setMessage(String message) { - super.setMessage("Extended " + message); - } - } - - @Tag("div") - public static class Parent extends Component { - } - - public static class MyComponentExporter - extends WebComponentExporter { - - public MyComponentExporter() { - this("my-component"); - } - - // extension point - protected MyComponentExporter(String tag) { - super(tag); - addProperty(MSG_PROPERTY, "").onChange(MyComponent::setMessage); - addProperty(INT_PROPERTY, 0).onChange(MyComponent::setIntegerValue); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - } - } - - public static class MyExtensionExporter - extends WebComponentExporter { - - public MyExtensionExporter() { - super("extended-component"); - addProperty(MSG_PROPERTY, "").onChange(MyExtension::setMessage); - addProperty(INT_PROPERTY, 0).onChange(MyExtension::setIntegerValue); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyExtension component) { - } - } - - public static class ExtendedExporter extends MyComponentExporter { - public ExtendedExporter() { - super("my-component-extended"); - - addProperty(MSG_PROPERTY, "Default") - .onChange(MyComponent::setMessage); - - addProperty(BOOLEAN_PROPERTY, false) - .onChange(MyComponent::setBooleanValue); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - super.configureInstance(webComponent, component); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/di/AppShellPredicateImplTest.java b/flow-server/src/test/java/com/vaadin/flow/di/AppShellPredicateImplTest.java deleted file mode 100644 index ac571e0e657..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/di/AppShellPredicateImplTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.di; - -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.di.LookupInitializer.AppShellPredicateImpl; -import com.vaadin.flow.server.startup.AppShellPredicate; - -public class AppShellPredicateImplTest { - - private AppShellPredicate predicate = new AppShellPredicateImpl(); - - private static class TestAppShellPredicateConfig - implements AppShellConfigurator { - - } - - @Test - public void isShell_isAppShellConfigurator_returnsTrue() { - Assert.assertTrue(predicate.isShell(TestAppShellPredicateConfig.class)); - } - - @Test - public void isShell_isNotAppShellConfigurator_returnsFalse() { - Assert.assertFalse(predicate.isShell(List.class)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/di/DefaultInstantiatorTest.java b/flow-server/src/test/java/com/vaadin/flow/di/DefaultInstantiatorTest.java deleted file mode 100644 index 2e4b50ca4d0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/di/DefaultInstantiatorTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.di; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; - -public class DefaultInstantiatorTest { - - @Tag(Tag.A) - public static class TestComponent extends Component { - - } - - @Test - public void createComponent_dontDependOnGetOrCreate() { - DefaultInstantiator instantiator = Mockito - .mock(DefaultInstantiator.class); - - Mockito.when(instantiator.createComponent(Mockito.any())) - .thenCallRealMethod(); - - TestComponent component = instantiator - .createComponent(TestComponent.class); - - Assert.assertNotNull(component); - - Mockito.verify(instantiator, Mockito.times(0)) - .getOrCreate(Mockito.any()); - } - - @Test - public void getOrCreate_lookupHasObject_returnObjectFromLookup() { - VaadinService service = Mockito.mock(VaadinService.class); - Lookup lookup = mockLookup(service); - - DefaultInstantiator instantiator = new DefaultInstantiator(service); - - Mockito.when(lookup.lookup(List.class)).thenReturn(new ArrayList<>()); - - List list = instantiator.getOrCreate(List.class); - Assert.assertTrue(list instanceof ArrayList); - } - - @Test - public void getOrCreate_lookupHasNoObject_createNewObject() { - VaadinService service = Mockito.mock(VaadinService.class); - mockLookup(service); - - DefaultInstantiator instantiator = new DefaultInstantiator(service); - - TestComponent component = instantiator.getOrCreate(TestComponent.class); - Assert.assertNotNull(component); - } - - private Lookup mockLookup(VaadinService service) { - VaadinContext context = Mockito.mock(VaadinContext.class); - Mockito.when(service.getContext()).thenReturn(context); - - Lookup lookup = Mockito.mock(Lookup.class); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(lookup); - return lookup; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/di/LookupInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/di/LookupInitializerTest.java deleted file mode 100644 index 5838a95c6ca..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/di/LookupInitializerTest.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.di; - -import jakarta.servlet.ServletException; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.di.LookupInitializer.AppShellPredicateImpl; -import com.vaadin.flow.di.LookupInitializer.ResourceProviderImpl; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.function.VaadinApplicationInitializationBootstrap; -import com.vaadin.flow.router.DefaultRoutePathProvider; -import com.vaadin.flow.router.RoutePathProvider; -import com.vaadin.flow.server.StaticFileHandler; -import com.vaadin.flow.server.StaticFileHandlerFactory; -import com.vaadin.flow.server.StaticFileServer; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.startup.AppShellPredicate; -import com.vaadin.flow.server.startup.ApplicationConfigurationFactory; -import com.vaadin.flow.server.startup.DefaultApplicationConfigurationFactory; -import com.vaadin.flow.server.startup.testdata.AnotherTestInstantiatorFactory; -import com.vaadin.flow.server.startup.testdata.OneMoreTestInstantiatorFactory; -import com.vaadin.flow.server.startup.testdata.TestInstantiatorFactory; -import com.vaadin.flow.server.startup.testdata.TestResourceProvider; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class LookupInitializerTest { - - private LookupInitializer initializer = new LookupInitializer(); - - @Test(expected = IllegalStateException.class) - public void createLookup_instantiatorsAreProvidedAsAService_lookupThrows() - throws ServletException { - // Java standard SPI is used to register several instantiators via - // META-INF/services - Lookup lookup = initializer.createLookup(null, new HashMap<>()); - - lookup.lookup(InstantiatorFactory.class); - } - - @Test(expected = IllegalStateException.class) - public void createLookup_instantiatorsAreProvidedAsScannedClasses_multipleInstantiatorInstances_lookupThrows() - throws ServletException { - Lookup lookup = initializer.createLookup(null, - Collections.singletonMap(InstantiatorFactory.class, - Arrays.asList(TestInstantiatorFactory.class, - AnotherTestInstantiatorFactory.class))); - - lookup.lookup(InstantiatorFactory.class); - } - - @Test - public void initialize_noResourcePorvider_defaultResourceProviderIsCreated() - throws ServletException, IOException { - AtomicReference capture = new AtomicReference<>(); - initializer.initialize(null, new HashMap<>(), capture::set); - - Lookup lookup = capture.get(); - assertResourceProvider(lookup.lookup(ResourceProvider.class)); - } - - @Test - public void initialize_noStaticFileHandlerFactory_defaultStaticFileHandlerFactoryCreated() - throws ServletException { - AtomicReference capture = new AtomicReference<>(); - initializer.initialize(null, new HashMap<>(), capture::set); - - Lookup lookup = capture.get(); - StaticFileHandlerFactory factory = lookup - .lookup(StaticFileHandlerFactory.class); - - VaadinService service = Mockito.mock(VaadinService.class); - DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - ClassLoader loader = Mockito.mock(ClassLoader.class); - Mockito.when(service.getClassLoader()).thenReturn(loader); - - StaticFileHandler handler = factory.createHandler(service); - Assert.assertNotNull(handler); - Assert.assertEquals(StaticFileServer.class, handler.getClass()); - } - - @Test - public void initialize_StaticFileHandlerFactoryIdDelegatedToEnsureService() - throws ServletException { - Map mock = Mockito.mock(Map.class); - AtomicBoolean factoryIsPassed = new AtomicBoolean(); - initializer = new LookupInitializer() { - - @Override - protected void ensureService( - Map, Collection>> services, - Class serviceType, Class serviceImpl) { - Assert.assertSame(mock, services); - if (StaticFileHandlerFactory.class.equals(serviceType)) { - factoryIsPassed.set(true); - } - } - }; - - AtomicReference capture = new AtomicReference<>(); - - initializer.initialize(null, mock, capture::set); - - Assert.assertTrue(factoryIsPassed.get()); - } - - @Test - public void initialize_hasOneTimeInitializerPredicate_predicateReturnsTrue() - throws ServletException, IOException { - AtomicReference capture = new AtomicReference<>(); - initializer.initialize(null, new HashMap<>(), capture::set); - - Lookup lookup = capture.get(); - OneTimeInitializerPredicate predicate = lookup - .lookup(OneTimeInitializerPredicate.class); - Assert.assertNotNull(predicate); - Assert.assertTrue(predicate.runOnce()); - } - - @Test - public void ensureResourceProvider_defaultImplClassIsStoredAsAService() { - HashMap, Collection>> map = new HashMap<>(); - initializer.ensureService(map, ResourceProvider.class, - ResourceProviderImpl.class); - - Collection> collection = map.get(ResourceProvider.class); - Assert.assertEquals(1, collection.size()); - Class clazz = collection.iterator().next(); - Assert.assertEquals(ResourceProviderImpl.class, clazz); - } - - @Test - public void ensureResourceProvider_defaultImplClassIsProvided_defaultImplIsStoredAsAService() { - HashMap, Collection>> map = new HashMap<>(); - map.put(ResourceProvider.class, - Collections.singletonList(ResourceProviderImpl.class)); - initializer.ensureService(map, ResourceProvider.class, - ResourceProviderImpl.class); - - Collection> collection = map.get(ResourceProvider.class); - Assert.assertEquals(1, collection.size()); - Class clazz = collection.iterator().next(); - Assert.assertEquals(ResourceProviderImpl.class, clazz); - } - - @Test - public void ensureRoutePathResolver_defaultImplClassIsStoredAsAService() { - HashMap, Collection>> map = new HashMap<>(); - initializer.ensureService(map, RoutePathProvider.class, - DefaultRoutePathProvider.class); - - Collection> collection = map.get(RoutePathProvider.class); - Assert.assertEquals(1, collection.size()); - Class clazz = collection.iterator().next(); - Assert.assertEquals(DefaultRoutePathProvider.class, clazz); - } - - @Test - public void ensureRoutePathResolver_defaultImplClassIsProvided_defaultImplIsStoredAsAService() { - HashMap, Collection>> map = new HashMap<>(); - map.put(RoutePathProvider.class, - Collections.singletonList(DefaultRoutePathProvider.class)); - initializer.ensureService(map, RoutePathProvider.class, - DefaultRoutePathProvider.class); - - Collection> collection = map.get(RoutePathProvider.class); - Assert.assertEquals(1, collection.size()); - Class clazz = collection.iterator().next(); - Assert.assertEquals(DefaultRoutePathProvider.class, clazz); - } - - @Test - public void ensureApplicationConfigurationFactories_defaultFactoryOnly_defaultFactoryIsReturned() - throws ServletException { - HashMap, Collection>> map = new HashMap<>(); - map.put(ApplicationConfigurationFactory.class, Collections - .singletonList(DefaultApplicationConfigurationFactory.class)); - initializer.ensureService(map, ApplicationConfigurationFactory.class, - DefaultApplicationConfigurationFactory.class); - - Collection> factories = map - .get(ApplicationConfigurationFactory.class); - Assert.assertEquals(1, factories.size()); - Assert.assertEquals(DefaultApplicationConfigurationFactory.class, - factories.iterator().next()); - } - - @Test - public void ensureApplicationConfigurationFactories_noAvailableFactory_defaultFactoryIsReturned() - throws ServletException { - HashMap, Collection>> map = new HashMap<>(); - map.put(ApplicationConfigurationFactory.class, Collections.emptyList()); - initializer.ensureService(map, ApplicationConfigurationFactory.class, - DefaultApplicationConfigurationFactory.class); - - Collection> collection = map - .get(ApplicationConfigurationFactory.class); - Assert.assertEquals(1, collection.size()); - Class clazz = collection.iterator().next(); - Assert.assertEquals(DefaultApplicationConfigurationFactory.class, - clazz); - } - - @SuppressWarnings("rawtypes") - @Test - public void createLookup_createLookupIsInvoked_lookupcontainsProvidedServices() - throws ServletException { - HashMap, Collection>> map = new HashMap<>(); - map.put(List.class, Arrays.asList(ArrayList.class, LinkedList.class)); - map.put(ResourceProvider.class, - Collections.singletonList(TestResourceProvider.class)); - - Lookup lookup = initializer.createLookup(null, map); - - ResourceProvider resourceProvider = lookup - .lookup(ResourceProvider.class); - Assert.assertEquals(TestResourceProvider.class, - resourceProvider.getClass()); - - Collection lists = lookup.lookupAll(List.class); - Assert.assertEquals(2, lists.size()); - - Iterator iterator = lists.iterator(); - List next = iterator.next(); - Assert.assertEquals(ArrayList.class, next.getClass()); - - next = iterator.next(); - Assert.assertEquals(LinkedList.class, next.getClass()); - } - - @Test - public void createLookup_instantiatorsAreProvidedAsScannedClassAndAsAService_lookupReturnsTheProviderInstance_lookupAllReturnsAllInstances() - throws ServletException { - HashMap, Collection>> map = new HashMap<>(); - map.put(InstantiatorFactory.class, - Collections.singleton(TestInstantiatorFactory.class)); - - Lookup lookup = initializer.createLookup(null, map); - - InstantiatorFactory factory = lookup.lookup(InstantiatorFactory.class); - Assert.assertNotNull(factory); - Assert.assertEquals(TestInstantiatorFactory.class, factory.getClass()); - - Collection factories = lookup - .lookupAll(InstantiatorFactory.class); - - Assert.assertEquals(3, factories.size()); - - Iterator iterator = factories.iterator(); - Assert.assertEquals(TestInstantiatorFactory.class, - iterator.next().getClass()); - - Set> factoryClasses = new HashSet<>(); - factoryClasses.add(iterator.next().getClass()); - factoryClasses.add(iterator.next().getClass()); - - Assert.assertTrue( - factoryClasses.contains(AnotherTestInstantiatorFactory.class)); - Assert.assertTrue( - factoryClasses.contains(OneMoreTestInstantiatorFactory.class)); - } - - @Test - public void resourceProviderImpl_returnsClassPathResources() - throws IOException { - assertResourceProvider(new ResourceProviderImpl()); - } - - @SuppressWarnings("unchecked") - @Test - public void initialize_callEnsureMethodsAndBootstrap() - throws ServletException { - LookupInitializer initializer = Mockito.spy(LookupInitializer.class); - Map, Collection>> services = Mockito - .mock(HashMap.class); - VaadinApplicationInitializationBootstrap bootstrap = Mockito - .mock(VaadinApplicationInitializationBootstrap.class); - initializer.initialize(null, services, bootstrap); - - Mockito.verify(initializer).ensureService(services, - ResourceProvider.class, ResourceProviderImpl.class); - Mockito.verify(initializer).ensureService(services, - ApplicationConfigurationFactory.class, - DefaultApplicationConfigurationFactory.class); - Mockito.verify(initializer).ensureService(services, - AppShellPredicate.class, AppShellPredicateImpl.class); - Mockito.verify(bootstrap).bootstrap(Mockito.any()); - } - - @Test - public void ensureService_noServiceProvided_defaultIsUsed() { - Map, Collection>> services = new HashMap<>(); - initializer.ensureService(services, List.class, ArrayList.class); - - Assert.assertEquals(1, services.size()); - Collection> collection = services.get(List.class); - Assert.assertEquals(1, collection.size()); - Assert.assertEquals(ArrayList.class, collection.iterator().next()); - } - - @Test - public void ensureService_defaultServiceProvided_defaultIsUsed() { - Map, Collection>> services = new HashMap<>(); - services.put(List.class, Collections.singleton(ArrayList.class)); - initializer.ensureService(services, List.class, ArrayList.class); - - Assert.assertEquals(1, services.size()); - Collection> collection = services.get(List.class); - Assert.assertEquals(1, collection.size()); - Assert.assertEquals(ArrayList.class, collection.iterator().next()); - } - - @Test(expected = IllegalStateException.class) - public void ensureService_severalServicesProvided_throws() { - Map, Collection>> services = new HashMap<>(); - services.put(List.class, Arrays.asList(Vector.class, LinkedList.class)); - initializer.ensureService(services, List.class, ArrayList.class); - } - - private void assertResourceProvider(ResourceProvider resourceProvider) - throws IOException { - Assert.assertEquals(ResourceProviderImpl.class, - resourceProvider.getClass()); - // ======== resourceProvider.getApplicationResource(s)(String) - URL applicationResource = resourceProvider - .getApplicationResource("resource-provider/some-resource.json"); - - Assert.assertNotNull(applicationResource); - - List resources = resourceProvider.getApplicationResources( - "resource-provider/some-resource.json"); - - Assert.assertEquals(1, resources.size()); - - Assert.assertNotNull(resources.get(0)); - - URL nonExistent = resourceProvider - .getApplicationResource("resource-provider/non-existent.txt"); - - Assert.assertNull(nonExistent); - - // =========== resourceProvider.getClientResource - - URL clientResource = resourceProvider - .getClientResource("resource-provider/some-resource.json"); - - Assert.assertNotNull(clientResource); - - InputStream stream = resourceProvider.getClientResourceAsStream( - "resource-provider/some-resource.json"); - - String content = IOUtils.readLines(stream, StandardCharsets.UTF_8) - .stream().collect(Collectors.joining("\n")); - JsonObject object = Json.parse(content); - Assert.assertTrue(object.getBoolean("client-resource")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/di/LookupTest.java b/flow-server/src/test/java/com/vaadin/flow/di/LookupTest.java deleted file mode 100644 index bb9382f919a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/di/LookupTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.di; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -public class LookupTest { - - @Test(expected = NullPointerException.class) - public void of_nullServiceObject_throws() { - Lookup.of(null); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Test(expected = IllegalArgumentException.class) - public void of_serviceNotExtendingType_throws() { - String service = ""; - Class type = List.class; - Lookup.of(service, type); - } - - @Test - public void of_serviceIsFoundByProvidedTypes_serviceIsNotFoundByNotProvidedTypes() { - ArrayList service = new ArrayList(); - Lookup lookup = Lookup.of(service, Collection.class); - Assert.assertEquals(service, lookup.lookup(Collection.class)); - Assert.assertEquals(1, lookup.lookupAll(Collection.class).size()); - Assert.assertEquals(service, - lookup.lookupAll(Collection.class).iterator().next()); - Assert.assertNull(lookup.lookup(List.class)); - Assert.assertEquals(0, lookup.lookupAll(List.class).size()); - } - - @Test - public void compose_bothLookupsHasService_resultingLookupReturnsServiceFromFirstLookup() { - ArrayList service = new ArrayList(); - Lookup lookup1 = Lookup.of(service, Collection.class); - Lookup lookup2 = Lookup.of(new LinkedList(), Collection.class); - - Lookup compose = Lookup.compose(lookup1, lookup2); - Assert.assertSame(service, compose.lookup(Collection.class)); - } - - @Test - public void compose_firstLookupHasNoService_resultingLookupReturnsServiceFromSecondLookup() { - Lookup lookup1 = Lookup.of(new LinkedList(), List.class); - ArrayList service = new ArrayList(); - Lookup lookup2 = Lookup.of(service, Collection.class); - - Lookup compose = Lookup.compose(lookup1, lookup2); - Assert.assertSame(service, compose.lookup(Collection.class)); - } - - @Test - public void compose_differentServicesForSameType_resultingLookupAllReturnsAllServices() { - LinkedList service1 = new LinkedList(); - Lookup lookup1 = Lookup.of(service1, List.class); - ArrayList service2 = new ArrayList(); - Lookup lookup2 = Lookup.of(service2, List.class, Collection.class); - - Lookup compose = Lookup.compose(lookup1, lookup2); - @SuppressWarnings("rawtypes") - Collection lookupAll = compose.lookupAll(List.class); - Assert.assertEquals(2, lookupAll.size()); - Assert.assertTrue(lookupAll.contains(service1)); - Assert.assertTrue(lookupAll.contains(service2)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/AbstractNodeTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/AbstractNodeTest.java deleted file mode 100644 index 1522d0ed279..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/AbstractNodeTest.java +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import com.googlecode.gentyref.GenericTypeReflector; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; - -public abstract class AbstractNodeTest { - - @Test(expected = IllegalArgumentException.class) - public void insertWithNullParameter() { - Node parent = createParentNode(); - parent.insertChild(0, (Element[]) null); - } - - @Test(expected = IllegalArgumentException.class) - public void insertNullChild() { - Node parent = createParentNode(); - parent.insertChild(0, new Element[] { null }); - } - - @Test - public void appendChildren() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1, child2); - - assertChildren(parent, child1, child2); - } - - protected void assertChildren(Node parent, Element... children) { - Assert.assertEquals(children.length, parent.getChildCount()); - for (int i = 0; i < children.length; i++) { - assertChild(parent, i, children[i]); - } - } - - protected void assertChild(Node parent, int index, Element child) { - Assert.assertEquals(child, parent.getChild(index)); - } - - @Test - public void insertChildFirst() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1); - parent.insertChild(0, child2); - - assertChildren(parent, child2, child1); - } - - @Test - public void insertChildMiddle() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2); - parent.insertChild(1, child3); - - assertChildren(parent, child1, child3, child2); - } - - @Test - public void insertChildAsLast() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2); - parent.insertChild(2, child3); - - assertChildren(parent, child1, child2, child3); - } - - @Test(expected = IllegalArgumentException.class) - public void insertChildAfterLast() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2); - parent.insertChild(3, child3); - } - - @Test - public void removeChildFirst() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(child1); - - assertChildren(parent, child2, child3); - } - - @Test - public void removeChildFirstIndex() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(0); - - assertChildren(parent, child2, child3); - } - - @Test - public void removeChildrenFirst() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(child1, child2); - - assertChildren(parent, child3); - } - - @Test - public void removeChildMiddle() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(child2); - - assertChildren(parent, child1, child3); - } - - @Test - public void removeChildMiddleIndex() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(1); - - assertChildren(parent, child1, child3); - } - - @Test - public void removeChildrenMiddle() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - Element child4 = new Element("child4"); - parent.appendChild(child1, child2, child3, child4); - parent.removeChild(child2, child3); - - assertChildren(parent, child1, child4); - } - - @Test - public void removeChildLast() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(child3); - - assertChildren(parent, child1, child2); - } - - @Test - public void removeChildLastIndex() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - parent.appendChild(child1, child2, child3); - parent.removeChild(2); - - assertChildren(parent, child1, child2); - } - - @Test - public void removeChildrenLast() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - Element child4 = new Element("child4"); - parent.appendChild(child1, child2, child3, child4); - parent.removeChild(child3, child4); - - assertChildren(parent, child1, child2); - } - - @Test - public void removeAllChildren() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - Element child4 = new Element("child4"); - parent.appendChild(child1, child2, child3, child4); - parent.removeAllChildren(); - - assertChildren(parent); - } - - @Test - public void removeAllChildrenEmpty() { - Node parent = createParentNode(); - parent.removeAllChildren(); - - assertChildren(parent); - } - - @Test - public void testGetChildren() { - Node parent = createParentNode(); - - Element child1 = ElementFactory.createDiv(); - Element child2 = ElementFactory.createDiv(); - Element child3 = ElementFactory.createDiv(); - - parent.appendChild(child1, child2, child3); - - List children = parent.getChildren() - .collect(Collectors.toList()); - Assert.assertEquals(Arrays.asList(child1, child2, child3), children); - } - - @Test - public void testGetChildren_empty() { - Node parent = createParentNode(); - - Assert.assertEquals(0, parent.getChildren().count()); - } - - @Test(expected = IllegalArgumentException.class) - public void removeNonChild() { - Node parent = createParentNode(); - Element otherElement = new Element("other"); - parent.removeChild(otherElement); - } - - @Test - public void getChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - Element child3 = new Element("child3"); - Element child4 = new Element("child4"); - parent.appendChild(child1, child2, child3, child4); - Assert.assertEquals(child1, parent.getChild(0)); - Assert.assertEquals(child2, parent.getChild(1)); - Assert.assertEquals(child3, parent.getChild(2)); - Assert.assertEquals(child4, parent.getChild(3)); - } - - @Test(expected = IllegalArgumentException.class) - public void getNegativeChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1, child2); - parent.getChild(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void getAfterLastChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1, child2); - parent.getChild(2); - } - - @Test - public void appendChild() { - Node parent = createParentNode(); - Element child = new Element("child"); - parent.appendChild(child); - - assertChildren(parent, child); - } - - @Test(expected = IllegalArgumentException.class) - public void appendNullChild() { - Node parent = createParentNode(); - parent.appendChild((Element[]) null); - } - - @Test(expected = IllegalArgumentException.class) - public void replaceNullChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - parent.appendChild(child1); - parent.setChild(0, null); - } - - @Test(expected = IllegalArgumentException.class) - public void removeNullChild() { - Node parent = createParentNode(); - parent.removeChild((Element[]) null); - } - - @Test(expected = IllegalArgumentException.class) - public void replaceBeforeFirstChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1); - parent.setChild(-1, child2); - } - - @Test - public void setForEmptyParent() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - parent.setChild(0, child1); - assertChildren(parent, child1); - } - - @Test - public void replaceAfterLastChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1); - parent.setChild(1, child2); - assertChildren(parent, child1, child2); - } - - @Test(expected = IllegalArgumentException.class) - public void replaceAfterAfterLastChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1); - parent.setChild(2, child2); - } - - @Test - public void replaceChildWithItself() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - parent.appendChild(child1); - - parent.getNode().clearChanges(); - - parent.setChild(0, child1); - - AtomicInteger changesCausedBySetChild = new AtomicInteger(0); - parent.getNode().getFeature(ElementChildrenList.class) - .collectChanges(change -> { - changesCausedBySetChild.incrementAndGet(); - }); - Assert.assertEquals(0, changesCausedBySetChild.get()); - } - - @Test(expected = IllegalArgumentException.class) - public void removeChildBeforeFirst() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - parent.appendChild(child1); - parent.removeChild(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void removeChildAfterLast() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - parent.appendChild(child1); - parent.removeChild(1); - } - - @Test - public void appendAttachedChild() { - Node parent = createParentNode(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - - Element target = ElementFactory.createDiv(); - - target.appendChild(child); - - Assert.assertEquals(child.getParent(), target); - - checkIsNotChild(parent, child); - } - - @Test - public void indexOfChild_firstChild() { - Node parent = createParentNode(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - - Assert.assertEquals(0, parent.indexOfChild(child)); - } - - @Test - public void indexOfChild_childInTheMiddle() { - Node parent = createParentNode(); - Element child1 = ElementFactory.createDiv(); - Element child2 = ElementFactory.createAnchor(); - Element child3 = ElementFactory.createButton(); - parent.appendChild(child1, child2, child3); - - Assert.assertEquals(1, parent.indexOfChild(child2)); - } - - @Test - public void indexOfChild_notAChild() { - Node parent = createParentNode(); - Element child = ElementFactory.createDiv(); - - Assert.assertEquals(-1, parent.indexOfChild(child)); - } - - @Test - public void appendFirstChildToOwnParent() { - Node parent = createParentNode(); - Element child1 = ElementFactory.createDiv(); - Element child2 = ElementFactory.createDiv(); - parent.appendChild(child1, child2); - - parent.appendChild(child1); - assertChildren(parent, child2, child1); - } - - @Test - public void appendLastChildToOwnParent() { - Node parent = createParentNode(); - Element child1 = ElementFactory.createDiv(); - Element child2 = ElementFactory.createDiv(); - parent.appendChild(child1, child2); - - parent.appendChild(child2); - assertChildren(parent, child1, child2); - } - - @Test - public void appendManyChildrenToOwnParent() { - Node parent = createParentNode(); - Element child1 = ElementFactory.createDiv(); - Element child2 = ElementFactory.createDiv(); - parent.appendChild(child1, child2); - - parent.appendChild(child2, child1); - // Order should be changed - assertChildren(parent, child2, child1); - } - - @Test - public void appendExistingAndNewChildren() { - Node parent = createParentNode(); - Element child1 = ElementFactory.createDiv(); - Element child2 = ElementFactory.createDiv(); - parent.appendChild(child1); - - parent.appendChild(child2, child1); - - assertChildren(parent, child2, child1); - } - - @Test - public void insertAttachedChild() { - Node parent = createParentNode(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - - Element target = ElementFactory.createDiv(); - target.appendChild(ElementFactory.createAnchor()); - - target.insertChild(0, child); - - Assert.assertEquals(child.getParent(), target); - - checkIsNotChild(parent, child); - } - - @Test - public void setAttachedChild() { - Node parent = createParentNode(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - - Element target = ElementFactory.createDiv(); - target.appendChild(ElementFactory.createAnchor()); - - target.setChild(0, child); - - Assert.assertEquals(child.getParent(), target); - - checkIsNotChild(parent, child); - } - - @Test - public void removeFromParent() { - Node parent = createParentNode(); - Element otherElement = new Element("other"); - parent.appendChild(otherElement); - Assert.assertEquals(parent, otherElement.getParentNode()); - otherElement.removeFromParent(); - Assert.assertNull(otherElement.getParentNode()); - } - - @Test - public void replaceFirstChild() { - Node parent = createParentNode(); - Element child1 = new Element("child1"); - Element child2 = new Element("child2"); - parent.appendChild(child1); - parent.setChild(0, child2); - Assert.assertNull(child1.getParentNode()); - Assert.assertEquals(parent, child2.getParentNode()); - } - - protected void checkIsNotChild(Node parent, Element child) { - Assert.assertNotEquals(child.getParentNode(), parent); - Assert.assertFalse( - parent.getChildren().anyMatch(el -> el.equals(child))); - } - - protected void assertMethodsReturnType(Class> clazz, - Set ignore) { - for (Method method : clazz.getMethods()) { - if (method.getDeclaringClass().equals(Object.class)) { - continue; - } - if (!Modifier.isPublic(method.getModifiers())) { - continue; - } - if (Modifier.isStatic(method.getModifiers())) { - continue; - } - if (method.isBridge()) { - continue; - } - if (method.getName().startsWith("get") - || method.getName().startsWith("has") - || method.getName().startsWith("is") - || ignore.contains(method.getName())) { - // Ignore - } else { - // Setters and such - Type returnType = GenericTypeReflector - .getExactReturnType(method, clazz); - Assert.assertEquals( - "Method " + method.getName() - + " has invalid return type", - clazz, returnType); - } - } - } - - @SuppressWarnings("rawtypes") - protected abstract Node createParentNode(); -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/BasicElementStateProviderTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/BasicElementStateProviderTest.java deleted file mode 100644 index ece7987d409..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/BasicElementStateProviderTest.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.vaadin.flow.dom; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.NodeVisitor.ElementType; -import com.vaadin.flow.dom.impl.BasicElementStateProvider; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; -import com.vaadin.flow.internal.nodefeature.ElementData; -import com.vaadin.flow.internal.nodefeature.NodeFeature; -import com.vaadin.flow.internal.nodefeature.NodeProperties; -import com.vaadin.flow.internal.nodefeature.ShadowRootData; -import com.vaadin.flow.internal.nodefeature.VirtualChildrenList; -import com.vaadin.flow.server.VaadinRequest; - -public class BasicElementStateProviderTest { - - @Test - public void supportsSelfCreatedNode() { - BasicElementStateProvider provider = BasicElementStateProvider.get(); - StateNode node = BasicElementStateProvider.createStateNode("foo"); - Assert.assertTrue(provider.supports(node)); - } - - @Test - public void doesNotSupportEmptyNode() { - BasicElementStateProvider provider = BasicElementStateProvider.get(); - Assert.assertFalse(provider.supports(new StateNode())); - } - - @Test - public void supportsUIRootNode() { - BasicElementStateProvider provider = BasicElementStateProvider.get(); - UI ui = new UI() { - - @Override - protected void init(VaadinRequest request) { - - } - }; - StateNode rootNode = ui.getInternals().getStateTree().getRootNode(); - Assert.assertTrue(provider.supports(rootNode)); - - } - - @Test - public void getParent_parentNodeIsNull_parentIsNull() { - Element div = ElementFactory.createDiv(); - Assert.assertNull( - BasicElementStateProvider.get().getParent(div.getNode())); - } - - @Test - public void getParent_parentNodeIsNotNull_parentIsNotNull() { - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - Assert.assertEquals(parent, - BasicElementStateProvider.get().getParent(child.getNode())); - } - - @Test - public void getParent_parentNodeIsShadowRootNode_parentIsShadowRoot() { - ShadowRoot parent = ElementFactory.createDiv().attachShadow(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - Assert.assertEquals(parent, - BasicElementStateProvider.get().getParent(child.getNode())); - } - - @Test - public void createStateNode_stateNodeHasRequiredElementDataFeature() { - StateNode stateNode = BasicElementStateProvider.createStateNode("div"); - Assert.assertTrue(stateNode.isReportedFeature(ElementData.class)); - } - - @Test - public void visitOnlyNode_hasDescendants_nodeVisitedAndNoDescendantsVisited() { - TestNodeVisitor visitor = new TestNodeVisitor(false); - - Map, ElementType> map = new HashMap<>(); - - Element subject = createHierarchy(map); - - BasicElementStateProvider.get().visit(subject.getNode(), visitor); - - Assert.assertEquals(1, visitor.getVisited().size()); - Assert.assertEquals(subject, - visitor.getVisited().keySet().iterator().next()); - Assert.assertEquals(ElementType.REGULAR, - visitor.getVisited().values().iterator().next()); - } - - @Test - public void visitOnlyNode_hasDescendants_nodeAndDescendatnsAreVisited() { - TestNodeVisitor visitor = new TestNodeVisitor(true); - - Map, ElementType> map = new HashMap<>(); - - Element subject = createHierarchy(map); - - BasicElementStateProvider.get().visit(subject.getNode(), visitor); - - Assert.assertTrue(map.size() > 1); - - Assert.assertEquals( - "The collected descendants doesn't match expected descendatns", - map, visitor.getVisited()); - } - - @Test - public void visitNode_noChildren_featuresNotInitialized() { - Element element = ElementFactory.createDiv(); - - assertNoChildFeatures(element); - - element.accept(new TestNodeVisitor(true)); - - assertNoChildFeatures(element); - } - - public static void assertNoChildFeatures(Element element) { - Assert.assertFalse("Node should not have a children list feature", - isFeatureInitialized(element, ElementChildrenList.class)); - Assert.assertFalse( - "Node should not have a virtual children list feature", - isFeatureInitialized(element, VirtualChildrenList.class)); - Assert.assertFalse("Node should not have a shadow root feature", - isFeatureInitialized(element, ShadowRootData.class)); - } - - @Test - public void setVisible() { - Element element = ElementFactory.createDiv(); - - Assert.assertTrue( - element.getNode().getFeature(ElementData.class).isVisible()); - - BasicElementStateProvider.get().setVisible(element.getNode(), true); - - Assert.assertTrue( - element.getNode().getFeature(ElementData.class).isVisible()); - - BasicElementStateProvider.get().setVisible(element.getNode(), false); - - Assert.assertFalse( - element.getNode().getFeature(ElementData.class).isVisible()); - - } - - private static boolean isFeatureInitialized(Element element, - Class featureType) { - return element.getNode().getFeatureIfInitialized(featureType) - .isPresent(); - } - - private Element createHierarchy(Map, ElementType> map) { - Element root = ElementFactory.createDiv(); - - map.put(root, ElementType.REGULAR); - - ShadowRoot shadowRoot = root.attachShadow(); - - map.put(shadowRoot, null); - - Element shadowChild = ElementFactory.createAnchor(); - Element shadowVirtualChild = ElementFactory.createBr(); - shadowRoot.appendChild(shadowChild); - shadowRoot.appendVirtualChild(shadowVirtualChild); - - map.put(shadowChild, ElementType.REGULAR); - map.put(shadowVirtualChild, ElementType.VIRTUAL); - - Element child = ElementFactory.createDiv(); - - root.appendChild(child); - - map.put(child, ElementType.REGULAR); - - Element virtualChild = ElementFactory.createDiv(); - - root.appendVirtualChild(virtualChild); - - map.put(virtualChild, ElementType.VIRTUAL); - - Element virtualGrandChild = ElementFactory.createDiv(); - - child.getStateProvider().appendVirtualChild(child.getNode(), - virtualGrandChild, NodeProperties.INJECT_BY_ID, "id"); - - map.put(virtualGrandChild, ElementType.VIRTUAL_ATTACHED); - - return root; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/BasicTextElementStateProviderTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/BasicTextElementStateProviderTest.java deleted file mode 100644 index ce31b3e5e0b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/BasicTextElementStateProviderTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.dom.impl.BasicTextElementStateProvider; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.nodefeature.TextNodeMap; - -public class BasicTextElementStateProviderTest { - - @Test - public void createStateNode_stateNodeHasRequiredElementDataFeature() { - StateNode stateNode = BasicTextElementStateProvider - .createStateNode("foo"); - Assert.assertTrue(stateNode.isReportedFeature(TextNodeMap.class)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/DisabledUpdateModeTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/DisabledUpdateModeTest.java deleted file mode 100644 index 87325f39efe..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/DisabledUpdateModeTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import static com.vaadin.flow.dom.DisabledUpdateMode.ALWAYS; -import static com.vaadin.flow.dom.DisabledUpdateMode.ONLY_WHEN_ENABLED; - -import org.junit.Assert; -import org.junit.Test; - -public class DisabledUpdateModeTest { - - @Test - public void permissiveOrdering() { - assertMostPermissive(ALWAYS, ALWAYS, ALWAYS); - assertMostPermissive(ALWAYS, ALWAYS, ONLY_WHEN_ENABLED); - assertMostPermissive(ALWAYS, ALWAYS, null); - - assertMostPermissive(ONLY_WHEN_ENABLED, ONLY_WHEN_ENABLED, - ONLY_WHEN_ENABLED); - assertMostPermissive(ONLY_WHEN_ENABLED, ONLY_WHEN_ENABLED, null); - - assertMostPermissive(null, null, null); - } - - private static void assertMostPermissive(DisabledUpdateMode expectedResult, - DisabledUpdateMode first, DisabledUpdateMode second) { - - Assert.assertEquals(expectedResult, - DisabledUpdateMode.mostPermissive(first, second)); - Assert.assertEquals(expectedResult, - DisabledUpdateMode.mostPermissive(second, first)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/ElementFactoryTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/ElementFactoryTest.java deleted file mode 100644 index 9b48c1c15b1..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/ElementFactoryTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -public class ElementFactoryTest { - - private Map methodToTag = new HashMap<>(); - - { - methodToTag.put("anchor", "a"); - methodToTag.put("horizontalrule", "hr"); - methodToTag.put("preformatted", "pre"); - methodToTag.put("paragraph", "p"); - methodToTag.put("emphasis", "em"); - methodToTag.put("listitem", "li"); - methodToTag.put("unorderedlist", "ul"); - for (int i = 1; i <= 6; i++) { - methodToTag.put("heading" + i, "h" + i); - } - } - - @Test - public void automatedTest() throws Exception { - for (Method method : ElementFactory.class.getMethods()) { - testMethod(method); - } - } - - @Test - public void createAnchor() { - String href = "hrefhref"; - String textContent = "textContent"; - - assertElement("", - ElementFactory.createAnchor(href)); - assertElement("textContent", - ElementFactory.createAnchor(href, textContent)); - assertElement("textContent", - ElementFactory.createRouterLink(href, textContent)); - } - - @Test - public void createTextInput() { - String type = "typetype"; - - assertElement("", - ElementFactory.createInput(type)); - } - - private void assertElement(String expectedOuterHtml, Element createAnchor) { - String actualHtml = getOuterHtml(createAnchor); - Assert.assertEquals(expectedOuterHtml, actualHtml); - } - - private String getOuterHtml(Element e) { - StringBuilder sb = new StringBuilder(); - sb.append("<"); - sb.append(e.getTag()); - String attrs = e.getAttributeNames().sorted() - .map(name -> name + "='" + e.getAttribute(name) + "'") - .collect(Collectors.joining(" ")); - if (!attrs.isEmpty()) { - sb.append(" ").append(attrs); - } - sb.append(">"); - sb.append(e.getTextRecursively()); - sb.append(""); - - return sb.toString(); - } - - private boolean isSimpleCreateMethod(Method method) { - if (!method.getName().startsWith("create")) { - return false; - } - - return method.getParameterTypes().length == 0; - } - - private void testMethod(Method method) throws Exception { - if (isTestedSeparately(method)) { - return; - } else if (isSimpleCreateMethod(method)) { - Element element = (Element) method.invoke(null); - String expectedTag = tagNameFromMethod(method); - - assertElement("<" + expectedTag + ">", - element); - } else if (isTextContentMethod(method)) { - Element element = (Element) method.invoke(null, "textContent"); - String expectedTag = tagNameFromMethod(method); - - assertElement( - "<" + expectedTag + ">textContent", - element); - } else { - Assert.fail("Untested method: " + method.getName() + "(" - + Stream.of(method.getParameterTypes()) - .map(Class::getSimpleName) - .collect(Collectors.joining(",")) - + ")"); - } - } - - private boolean isTestedSeparately(Method method) { - if (method.getName().equals("createAnchor") - && method.getParameterTypes().length > 0) { - return true; - } - if (method.getName().equals("createRouterLink") - && method.getParameterTypes().length > 0) { - return true; - } - if (method.getName().equals("createInput") - && method.getParameterTypes().length > 0) { - return true; - } - - return false; - } - - private boolean isTextContentMethod(Method method) { - // Quite broad assumption - exceptions are handled as separate tests - Class[] parameterTypes = method.getParameterTypes(); - return parameterTypes.length == 1 && parameterTypes[0] == String.class; - } - - private String tagNameFromMethod(Method method) { - String tagFromMethod = method.getName().replace("create", "") - .toLowerCase(Locale.ENGLISH); - if (methodToTag.containsKey(tagFromMethod)) { - return methodToTag.get(tagFromMethod); - } else { - return tagFromMethod; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java deleted file mode 100644 index 19669da3a7c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/ElementTest.java +++ /dev/null @@ -1,2537 +0,0 @@ -package com.vaadin.flow.dom; - -import java.io.ByteArrayInputStream; -import java.io.Serializable; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Html; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.PendingJavaScriptInvocation; -import com.vaadin.flow.component.internal.UIInternals.JavaScriptInvocation; -import com.vaadin.flow.component.page.PendingJavaScriptResult; -import com.vaadin.flow.dom.impl.BasicElementStateProvider; -import com.vaadin.flow.internal.NullOwner; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.nodefeature.ComponentMapping; -import com.vaadin.flow.internal.nodefeature.ElementAttributeMap; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; -import com.vaadin.flow.internal.nodefeature.ElementListenersTest; -import com.vaadin.flow.internal.nodefeature.ElementPropertyMap; -import com.vaadin.flow.internal.nodefeature.ElementStylePropertyMap; -import com.vaadin.flow.internal.nodefeature.VirtualChildrenList; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.StreamResource; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.JsonConstants; -import com.vaadin.flow.shared.Registration; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; -import com.vaadin.tests.util.MockUI; -import com.vaadin.tests.util.TestUtil; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; -import elemental.json.JsonValue; -import elemental.json.impl.JreJsonObject; - -@NotThreadSafe -public class ElementTest extends AbstractNodeTest { - - @Test - public void createElementWithTag() { - Element e = ElementFactory.createDiv(); - Assert.assertEquals(Tag.DIV, e.getTag()); - Assert.assertFalse(e.hasAttribute("is")); - Assert.assertFalse(e.isTextNode()); - } - - @Test(expected = IllegalArgumentException.class) - public void createElementWithInvalidTag() { - new Element("
"); - } - - @Test(expected = IllegalArgumentException.class) - public void createElementWithEmptyTag() { - new Element(""); - } - - @Test(expected = IllegalArgumentException.class) - public void createElementWithNullTag() { - new Element(null); - } - - @Test - public void elementsUpdateSameData() { - Element te = new Element("testelem"); - Element e = Element.get(te.getNode()); - - // Elements must be equal but not necessarily the same - Assert.assertEquals(te, e); - - te.setAttribute("foo", "bar"); - Assert.assertEquals("bar", e.getAttribute("foo")); - - e.setAttribute("baz", "123"); - Assert.assertEquals("123", te.getAttribute("baz")); - } - - @Test(expected = IllegalArgumentException.class) - public void getElementFromInvalidNode() { - StateNode node = new StateNode(ElementPropertyMap.class); - Element.get(node); - } - - @Test - public void publicElementMethodsShouldReturnElement() { - Set ignore = new HashSet<>(); - ignore.add("toString"); - ignore.add("hashCode"); - ignore.add("equals"); - - // Returns EventRegistrationHandle - ignore.add("addEventListener"); - ignore.add("addAttachListener"); - ignore.add("addDetachListener"); - ignore.add("addPropertyChangeListener"); - - // Returns index of child element - ignore.add("indexOfChild"); - // Component wrapper - ignore.add("as"); - // Possibly returns a remover or a wrapped return value in the future - ignore.add("callFunction"); - ignore.add("executeJavaScript"); - // Returns a future-ish thing with access to the return value - ignore.add("callJsFunction"); - ignore.add("executeJs"); - - // ignore shadow root methods - ignore.add("attachShadow"); - ignore.add("getShadowRoot"); - - assertMethodsReturnType(Element.class, ignore); - } - - @Test - public void publicElementStyleMethodsShouldReturnElement() { - Set ignore = new HashSet<>(); - ignore.add("toString"); - ignore.add("hashCode"); - ignore.add("equals"); - - for (Method m : Style.class.getDeclaredMethods()) { - if (!Modifier.isPublic(m.getModifiers())) { - continue; - } - if (Modifier.isStatic(m.getModifiers())) { - continue; - } - if (m.getName().startsWith("get") || m.getName().startsWith("has") - || m.getName().startsWith("is") - || ignore.contains(m.getName())) { - // Ignore - } else { - // Setters and such - Class returnType = m.getReturnType(); - Assert.assertEquals( - "Method " + m.getName() + " has invalid return type", - Style.class, returnType); - } - } - - } - - @Test - public void stringAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", "bar"); - Assert.assertEquals("bar", e.getAttribute("foo")); - } - - @Test - public void setEmptyAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", ""); - Assert.assertEquals("", e.getAttribute("foo")); - } - - @Test - public void setBooleanAttribute() { - Element e = ElementFactory.createDiv(); - - e.setAttribute("foo", true); - Assert.assertEquals("", e.getAttribute("foo")); - Assert.assertTrue(e.hasAttribute("foo")); - - e.setAttribute("foo", false); - Assert.assertEquals(null, e.getAttribute("foo")); - Assert.assertFalse(e.hasAttribute("foo")); - } - - @Test(expected = IllegalArgumentException.class) - public void setNullAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", (String) null); - } - - @Test(expected = IllegalArgumentException.class) - public void getNullAttribute() { - Element e = ElementFactory.createDiv(); - e.getAttribute(null); - } - - @Test(expected = IllegalArgumentException.class) - public void hasNullAttribute() { - Element e = ElementFactory.createDiv(); - e.hasAttribute(null); - } - - @Test(expected = IllegalArgumentException.class) - public void removeNullAttribute() { - Element e = ElementFactory.createDiv(); - e.removeAttribute(null); - } - - @Test(expected = IllegalArgumentException.class) - public void setInvalidAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("\"foo\"", "bar"); - } - - @Test - public void hasDefinedAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", "bar"); - Assert.assertTrue(e.hasAttribute("foo")); - } - - @Test - public void doesNotHaveUndefinedAttribute() { - Element e = ElementFactory.createDiv(); - Assert.assertFalse(e.hasAttribute("foo")); - } - - @Test - public void doesNotHaveRemovedAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", "bar"); - e.removeAttribute("foo"); - Assert.assertFalse(e.hasAttribute("foo")); - } - - @Test - public void removeNonExistingAttributeIsNoOp() { - Element e = ElementFactory.createDiv(); - Assert.assertFalse(e.hasAttribute("foo")); - e.removeAttribute("foo"); - Assert.assertFalse(e.hasAttribute("foo")); - } - - @Test - public void attributesWhenNoneDefined() { - Element e = ElementFactory.createDiv(); - Assert.assertEquals(0, e.getAttributeNames().count()); - } - - @Test - public void attributesNames() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", "bar"); - Assert.assertArrayEquals(new String[] { "foo" }, - e.getAttributeNames().toArray()); - } - - @Test - public void attributesNamesAfterRemoved() { - Element e = ElementFactory.createDiv(); - e.setAttribute("foo", "bar"); - e.setAttribute("bar", "baz"); - e.removeAttribute("foo"); - Assert.assertArrayEquals(new String[] { "bar" }, - e.getAttributeNames().toArray()); - } - - @Test - public void setGetAttributeValueCaseSensitive() { - Element e = new Element(Tag.SPAN); - e.setAttribute("foo", "bAr"); - Assert.assertEquals("bAr", e.getAttribute("foo")); - e.setAttribute("foo", "BAR"); - Assert.assertEquals("BAR", e.getAttribute("foo")); - } - - @Test - public void setGetAttributeNameCaseInsensitive() { - Element e = new Element(Tag.SPAN); - e.setAttribute("foo", "bar"); - e.setAttribute("FOO", "baz"); - - Assert.assertEquals("baz", e.getAttribute("foo")); - Assert.assertEquals("baz", e.getAttribute("FOO")); - } - - @Test - public void hasAttributeNamesCaseInsensitive() { - Element e = new Element(Tag.SPAN); - e.setAttribute("fooo", "bar"); - Assert.assertTrue(e.hasAttribute("fOoO")); - } - - @Test - public void getAttributeNamesLowerCase() { - Element e = new Element(Tag.SPAN); - e.setAttribute("FOO", "bar"); - e.setAttribute("Baz", "bar"); - - Set attributeNames = e.getAttributeNames() - .collect(Collectors.toSet()); - Assert.assertTrue(attributeNames.contains("foo")); - Assert.assertFalse(attributeNames.contains("FOO")); - Assert.assertTrue(attributeNames.contains("baz")); - Assert.assertFalse(attributeNames.contains("Baz")); - } - - @Test - public void removeDetachedFromParent() { - Element otherElement = new Element("other"); - Assert.assertNull(otherElement.getParent()); - otherElement.removeFromParent(); // No op - Assert.assertNull(otherElement.getParent()); - } - - @Test - public void getDetachedParent() { - Element otherElement = new Element("other"); - Assert.assertNull(otherElement.getParent()); - Assert.assertNull(otherElement.getParentNode()); - } - - @Test(expected = IllegalArgumentException.class) - public void addNullEventListener() { - Element e = ElementFactory.createDiv(); - e.addEventListener("foo", null); - } - - @Test(expected = IllegalArgumentException.class) - public void addEventListenerForNullType() { - Element e = ElementFactory.createDiv(); - e.addEventListener(null, ignore -> { - }); - } - - @Test - public void equalsSelf() { - Element e = ElementFactory.createDiv(); - Assert.assertTrue(e.equals(e)); - } - - @Test - public void notEqualsNull() { - Element e = ElementFactory.createDiv(); - Assert.assertFalse(e.equals(null)); - } - - @Test - public void notEqualsString() { - Element e = ElementFactory.createDiv(); - Assert.assertFalse(e.equals(Tag.DIV)); - } - - @Test - public void listenerReceivesEvents() { - Element e = ElementFactory.createDiv(); - AtomicInteger listenerCalls = new AtomicInteger(0); - DomEventListener myListener = event -> listenerCalls.incrementAndGet(); - - e.addEventListener("click", myListener); - Assert.assertEquals(0, listenerCalls.get()); - e.getNode().getFeature(ElementListenerMap.class) - .fireEvent(new DomEvent(e, "click", Json.createObject())); - Assert.assertEquals(1, listenerCalls.get()); - } - - @Test - public void getPropertyDefaults() { - Element element = ElementFactory.createDiv(); - - element.setProperty("null", null); - element.setProperty("empty", ""); - - Assert.assertEquals("d", element.getProperty("null", "d")); - Assert.assertEquals("d", element.getProperty("notThere", "d")); - Assert.assertNotEquals("d", element.getProperty("empty", "d")); - - Assert.assertTrue(element.getProperty("null", true)); - Assert.assertFalse(element.getProperty("null", false)); - Assert.assertTrue(element.getProperty("notThere", true)); - Assert.assertFalse(element.getProperty("notThere", false)); - Assert.assertFalse(element.getProperty("empty", true)); - Assert.assertFalse(element.getProperty("empty", false)); - - Assert.assertEquals(0.1, element.getProperty("null", 0.1), 0); - Assert.assertEquals(0.1, element.getProperty("notThere", 0.1), 0); - Assert.assertNotEquals(0.1, element.getProperty("empty", 0.1), 0); - - Assert.assertEquals(42, element.getProperty("null", 42)); - Assert.assertEquals(42, element.getProperty("notThere", 42)); - Assert.assertNotEquals(42, element.getProperty("empty", 42)); - } - - @Test - public void getPropertyStringConversions() { - assertPropertyString(null, null); - assertPropertyString("foo", "foo"); - assertPropertyString("", ""); - assertPropertyString("45.6e1", "45.6e1"); - assertPropertyString("true", Boolean.TRUE); - assertPropertyString("false", Boolean.FALSE); - assertPropertyString(String.valueOf(143534123423.243e23), - Double.valueOf(143534123423.243e23)); - assertPropertyString("42", Double.valueOf(42)); - - assertPropertyString(null, Json.createNull()); - assertPropertyString("{}", Json.createObject()); - } - - private static void assertPropertyString(String expected, Object value) { - Element element = createPropertyAssertElement(value); - - Assert.assertEquals(expected, element.getProperty("property")); - } - - @Test - public void testPropertyBooleanConversions() { - assertPropertyBoolean(true, Boolean.TRUE); - assertPropertyBoolean(false, Boolean.FALSE); - - assertPropertyBoolean(true, "true"); - assertPropertyBoolean(true, "false"); - assertPropertyBoolean(false, ""); - - assertPropertyBoolean(true, Double.valueOf(1)); - assertPropertyBoolean(true, Double.valueOf(3.14)); - assertPropertyBoolean(false, Double.valueOf(0)); - assertPropertyBoolean(false, Double.valueOf(Double.NaN)); - - assertPropertyBoolean(false, Json.createNull()); - assertPropertyBoolean(false, Json.create(false)); - assertPropertyBoolean(true, Json.create(true)); - assertPropertyBoolean(true, Json.createObject()); - } - - private static void assertPropertyBoolean(boolean expected, Object value) { - Element element = createPropertyAssertElement(value); - - // !expected -> default value will always fail - boolean actual = element.getProperty("property", !expected); - - if (expected) { - Assert.assertTrue(actual); - } else { - Assert.assertFalse(actual); - } - } - - @Test - public void testPropertyDoubleConversions() { - assertPropertyDouble(1, Double.valueOf(1)); - assertPropertyDouble(.1, Double.valueOf(.1)); - assertPropertyDouble(Double.NaN, Double.valueOf(Double.NaN)); - - assertPropertyDouble(1, "1"); - assertPropertyDouble(.1, ".1"); - assertPropertyDouble(12.34e56, "12.34e56"); - assertPropertyDouble(Double.NaN, "foo"); - - assertPropertyDouble(1, Boolean.TRUE); - assertPropertyDouble(0, Boolean.FALSE); - - assertPropertyDouble(.1, Json.create(.1)); - assertPropertyDouble(1, Json.create(true)); - assertPropertyDouble(0, Json.create(false)); - assertPropertyDouble(.1, Json.create(".1")); - assertPropertyDouble(Double.NaN, Json.create("foo")); - assertPropertyDouble(Double.NaN, Json.createObject()); - } - - private static void assertPropertyDouble(double expected, Object value) { - Element element = createPropertyAssertElement(value); - - int delta = 0; - double defaultValue = 1234d; - - if (defaultValue == expected) { - throw new IllegalArgumentException( - "Expecting the default value might cause unintended results"); - } - - Assert.assertEquals(expected, - element.getProperty("property", defaultValue), delta); - } - - @Test - public void testPropertyIntConversions() { - assertPropertyInt(1, Double.valueOf(1)); - assertPropertyInt(1, Double.valueOf(1.9)); - assertPropertyInt(0, Double.valueOf(Double.NaN)); - assertPropertyInt(Integer.MAX_VALUE, Double.valueOf(12.34e56)); - - assertPropertyInt(1, "1"); - assertPropertyInt(1, "1.9"); - assertPropertyInt(Integer.MAX_VALUE, "12.34e56"); - assertPropertyInt(0, "foo"); - - assertPropertyInt(1, Boolean.TRUE); - assertPropertyInt(0, Boolean.FALSE); - - assertPropertyInt(1, Json.create(1)); - assertPropertyInt(1, Json.create(1.9)); - assertPropertyInt(1, Json.create(true)); - assertPropertyInt(0, Json.create(false)); - assertPropertyInt(1, Json.create("1")); - assertPropertyInt(0, Json.create("foo")); - assertPropertyInt(0, Json.createObject()); - } - - private static void assertPropertyInt(int expected, Object value) { - Element element = createPropertyAssertElement(value); - - int defaultValue = 1234; - - if (defaultValue == expected) { - throw new IllegalArgumentException( - "Expecting the default value might cause unintended results"); - } - - Assert.assertEquals(expected, - element.getProperty("property", defaultValue)); - } - - public static class SimpleBean { - private String string = "value"; - private int number = 1; - private float flt = 2.3f; - private double dbl = 4.56; - - public String getString() { - return string; - } - - public int getNumber() { - return number; - } - - public float getFlt() { - return flt; - } - - public double getDbl() { - return dbl; - } - } - - @Test - public void propertyRawValues() { - Element element = ElementFactory.createDiv(); - - element.setProperty("p", "v"); - Assert.assertEquals("v", element.getPropertyRaw("p")); - - element.setProperty("p", true); - Assert.assertEquals(Boolean.TRUE, element.getPropertyRaw("p")); - - element.setProperty("p", 3.14); - Assert.assertEquals(Double.valueOf(3.14), element.getPropertyRaw("p")); - - element.setPropertyJson("p", Json.createObject()); - Assert.assertEquals(JreJsonObject.class, - element.getPropertyRaw("p").getClass()); - - element.setPropertyBean("p", new SimpleBean()); - JsonObject json = (JsonObject) element.getPropertyRaw("p"); - Assert.assertEquals("value", json.getString("string")); - Assert.assertEquals(1.0, json.getNumber("number"), 0.0); - Assert.assertEquals(2.3, json.getNumber("flt"), 0.0); - Assert.assertEquals(4.56, json.getNumber("dbl"), 0.0); - - List list = new ArrayList<>(); - SimpleBean bean1 = new SimpleBean(); - bean1.string = "bean1"; - SimpleBean bean2 = new SimpleBean(); - bean2.string = "bean2"; - list.add(bean1); - list.add(bean2); - element.setPropertyList("p", list); - JsonArray jsonArray = (JsonArray) element.getPropertyRaw("p"); - Assert.assertEquals("bean1", - jsonArray.getObject(0).getString("string")); - Assert.assertEquals("bean2", - jsonArray.getObject(1).getString("string")); - - Map map = new HashMap<>(); - map.put("one", bean1); - map.put("two", bean2); - element.setPropertyMap("p", map); - JsonObject jsonObject = (JsonObject) element.getPropertyRaw("p"); - Assert.assertEquals("bean1", - jsonObject.getObject("one").getString("string")); - Assert.assertEquals("bean2", - jsonObject.getObject("two").getString("string")); - } - - @Test - public void addAndRemoveProperty() { - Element element = ElementFactory.createDiv(); - - Assert.assertFalse(element.hasProperty("foo")); - element.removeProperty("foo"); - Assert.assertFalse(element.hasProperty("foo")); - - element.setProperty("foo", "bar"); - Assert.assertTrue(element.hasProperty("foo")); - element.setProperty("foo", null); - Assert.assertTrue(element.hasProperty("foo")); - - element.removeProperty("foo"); - Assert.assertFalse(element.hasProperty("foo")); - } - - @Test - public void propertyNames() { - Element element = ElementFactory.createDiv(); - - Assert.assertEquals(0, element.getPropertyNames().count()); - - element.setProperty("foo", "bar"); - Assert.assertEquals(Collections.singleton("foo"), - element.getPropertyNames().collect(Collectors.toSet())); - - element.removeProperty("foo"); - Assert.assertEquals(0, element.getPropertyNames().count()); - } - - private static Element createPropertyAssertElement(Object value) { - Element element = ElementFactory.createDiv(); - - if (value instanceof Number && !(value instanceof Double)) { - throw new IllegalArgumentException( - "Double is the only accepted numeric type"); - } - - if (value instanceof JsonValue) { - element.setPropertyJson("property", (JsonValue) value); - } else if (value instanceof Serializable) { - BasicElementStateProvider.get().setProperty(element.getNode(), - "property", (Serializable) value, true); - } else if (value == null) { - element.setProperty("property", null); - } else { - throw new IllegalArgumentException( - "Invalid value type: " + value.getClass()); - } - - return element; - } - - @Test - public void testGetTextContent() { - Element child = new Element("child"); - child.appendChild(Element.createText("bar")); - - Element element = ElementFactory.createDiv(); - - element.appendChild(Element.createText("foo")); - element.appendChild(child); - - Assert.assertEquals("foobar", element.getTextRecursively()); - } - - @Test - public void testSetTextContent() { - Element element = ElementFactory.createDiv(); - element.setText("foo"); - - Assert.assertEquals("foo", element.getTextRecursively()); - Assert.assertEquals(1, element.getChildCount()); - Assert.assertTrue(element.getChild(0).isTextNode()); - } - - @Test - public void testSetTextContentRemovesOldContent() { - Element child = new Element("child"); - Element element = ElementFactory.createDiv(); - element.appendChild(child); - - element.setText("foo"); - - Assert.assertNull(child.getParent()); - Assert.assertEquals("foo", element.getTextRecursively()); - } - - @Test - public void testSetTextReplacesOldTextNode() { - Element element = ElementFactory.createDiv(); - Element text = Element.createText("foo"); - element.appendChild(text); - - element.setText("bar"); - - Assert.assertEquals(element, text.getParent()); - Assert.assertEquals("bar", text.getTextRecursively()); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetTextContentPropertyThrows() { - Element element = new Element("element"); - element.setProperty("textContent", "foo"); - } - - @Test(expected = IllegalArgumentException.class) - public void setOuterHtmlProperty_throws() { - Element element = new Element("element"); - element.setProperty("outerHTML", "
"); - } - - @Test - public void setInnerHtmlProeprty_setValueAndRemoveAllChildren() { - Element element = new Element("element"); - element.appendChild(ElementFactory.createAnchor(), - ElementFactory.createDiv()); - element.setProperty("innerHTML", "
"); - - Assert.assertEquals(0, element.getChildCount()); - Assert.assertEquals("
", element.getProperty("innerHTML")); - } - - @Test - public void testGetTextContentProperty() { - Element element = ElementFactory.createDiv(); - element.setText("foo"); - - Assert.assertFalse(element.hasProperty("textContent")); - Assert.assertNull(element.getProperty("textContent")); - } - - @Test - // Because that's how it works in browsers - public void clearTextContentRemovesChild() { - Element element = ElementFactory.createDiv(); - element.setText("foo"); - - Assert.assertEquals(1, element.getChildCount()); - - element.setText(""); - - Assert.assertEquals(0, element.getChildCount()); - } - - @Test - public void newElementClasses() { - Element element = ElementFactory.createDiv(); - - Assert.assertFalse(element.hasAttribute("class")); - Assert.assertEquals(Collections.emptySet(), element.getClassList()); - } - - @Test - public void addElementClasses() { - Element element = ElementFactory.createDiv(); - - element.getClassList().add("foo"); - - Assert.assertEquals(Collections.singleton("foo"), - element.getClassList()); - Assert.assertTrue(element.hasAttribute("class")); - - Assert.assertEquals(Collections.singleton("class"), - element.getAttributeNames().collect(Collectors.toSet())); - Assert.assertTrue(element.hasAttribute("class")); - Assert.assertEquals("foo", element.getAttribute("class")); - - element.getClassList().add("bar"); - - Assert.assertEquals("foo bar", element.getAttribute("class")); - } - - @Test - public void testSetClassAttribute() { - Element element = ElementFactory.createDiv(); - - // Get instance right away to see that changes are live - Set classList = element.getClassList(); - - element.setAttribute("class", " foo bar "); - - Assert.assertEquals(2, classList.size()); - Assert.assertTrue(classList.contains("foo")); - Assert.assertTrue(classList.contains("bar")); - - Assert.assertNull("class should not be stored as a regular attribute", - element.getNode().getFeature(ElementAttributeMap.class) - .get("class")); - } - - @Test - public void testSetEmptyClassAttribute() { - Element element = new Element(Tag.DIV); - - // Get instance right away to see that changes are live - Set classList = element.getClassList(); - - element.setAttribute("class", ""); - - Assert.assertEquals(0, classList.size()); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddEmptyClassname() { - Element element = new Element(Tag.DIV); - - // Get instance right away to see that changes are live - Set classList = element.getClassList(); - - classList.add(""); - } - - @Test - public void testRemoveClassName() { - Element element = ElementFactory.createDiv(); - - element.setAttribute("class", "foo bar"); - - element.getClassList().remove("foo"); - - Assert.assertEquals("bar", element.getAttribute("class")); - - element.getClassList().remove("bar"); - - Assert.assertNull(element.getAttribute("class")); - Assert.assertFalse(element.hasAttribute("class")); - - Assert.assertEquals(0, element.getAttributeNames().count()); - } - - @Test - public void testRemoveClassAttribute() { - Element element = ElementFactory.createDiv(); - - Set classList = element.getClassList(); - - classList.add("foo"); - - element.removeAttribute("class"); - - Assert.assertEquals(Collections.emptySet(), classList); - } - - @Test - public void addExistingClass_noop() { - Element element = ElementFactory.createDiv(); - - element.setAttribute("class", "foo"); - - element.getClassList().add("foo"); - - Assert.assertEquals(Collections.singleton("foo"), - element.getClassList()); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddClassWithSpaces_throws() { - ElementFactory.createDiv().getClassList().add("foo bar"); - } - - @Test - public void testRemoveClassWithSpaces() { - ClassList cl = ElementFactory.createDiv().getClassList(); - cl.add("foo"); - cl.add("bar"); - cl.remove("foo bar"); - Assert.assertEquals(2, cl.size()); - } - - @Test - public void testContainsClassWithSpaces() { - ClassList cl = ElementFactory.createDiv().getClassList(); - cl.add("foo"); - cl.add("bar"); - - Assert.assertFalse(cl.contains("foo bar")); - } - - @Test - public void classListSetAdd() { - Element e = new Element(Tag.DIV); - Assert.assertTrue(e.getClassList().set("foo", true)); - Assert.assertEquals("foo", e.getAttribute("class")); - Assert.assertFalse(e.getClassList().set("foo", true)); - Assert.assertEquals("foo", e.getAttribute("class")); - } - - @Test - public void classListSetRemove() { - Element e = new Element(Tag.DIV); - e.setAttribute("class", "foo bar"); - Assert.assertTrue(e.getClassList().set("foo", false)); - Assert.assertEquals("bar", e.getAttribute("class")); - Assert.assertFalse(e.getClassList().set("foo", false)); - Assert.assertEquals("bar", e.getAttribute("class")); - } - - @Test(expected = IllegalArgumentException.class) - public void testClassListProperty_throws() { - ElementFactory.createDiv().setProperty("classList", "foo"); - } - - @Test(expected = IllegalArgumentException.class) - public void testClassNameProperty_throws() { - ElementFactory.createDiv().setProperty("className", "foo"); - } - - public void setStyle() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.set("foo", "bar"); - Assert.assertEquals("bar", s.get("foo")); - } - - @Test - public void getUnsetStyle() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - Assert.assertNull(s.get("foo")); - } - - @Test(expected = IllegalArgumentException.class) - public void getNullStyle() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.get(null); - } - - @Test - public void replaceStyle() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.set("foo", "bar"); - s.set("foo", "baz"); - Assert.assertEquals("baz", s.get("foo")); - } - - @Test - public void removeSingleStyle() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.set("foo", "bar"); - s.remove("foo"); - Assert.assertEquals(null, s.get("foo")); - } - - @Test - public void emptyStyleAsAttribute() { - Element e = ElementFactory.createDiv(); - Assert.assertFalse(e.hasAttribute("style")); - Assert.assertNull(e.getAttribute("style")); - } - - @Test(expected = IllegalArgumentException.class) - public void semicolonInStyle() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.set("border", "1 px solid black;"); - } - - @Test - public void getSingleStyleAsAttribute() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.set("border", "1px solid black"); - Assert.assertTrue(e.hasAttribute("style")); - Assert.assertEquals("border:1px solid black", e.getAttribute("style")); - } - - @Test - public void getMultipleStylesAsAttribute() { - Element e = ElementFactory.createDiv(); - Style s = e.getStyle(); - s.set("border", "1px solid black"); - s.set("margin", "1em"); - Assert.assertTrue(e.hasAttribute("style")); - assertEqualsOne( - new String[] { "border:1px solid black;margin:1em", - "margin:1em;border:1px solid black" }, - e.getAttribute("style")); - } - - @Test - public void setSingleStyleAsAttribute() { - Element e = ElementFactory.createDiv(); - String style = "width:12em"; - e.setAttribute("style", style); - Assert.assertEquals(style, e.getAttribute("style")); - - } - - @Test - public void setStyleAttributeMultipleTimes() { - Element e = ElementFactory.createDiv(); - e.setAttribute("style", "width:12em"); - e.setAttribute("style", "height:12em"); - Assert.assertEquals("height:12em", e.getAttribute("style")); - - } - - @Test - public void setMultipleStylesAsAttribute() { - Element e = ElementFactory.createDiv(); - String style = "width:12em;height:2em"; - e.setAttribute("style", style); - Assert.assertEquals(style, e.getAttribute("style")); - - } - - @Test - public void setComplexStylesAsAttribute() { - testStyleAttribute( - "background:rgb(0,255,0) url(http://foo.bar/smiley.gif) no-repeat fixed center"); - testStyleAttribute("content:\"content: bar\""); - testStyleAttribute("width:12px;content:\"content: bar\";height:12px"); - testStyleAttribute("width:calc(100% - 80px)"); - testStyleAttribute("width:var(--widthB)"); - testStyleAttribute("color:var(--mainColor)"); - // Reduced calc does not work (http://cssnext.io/features/#reduced-calc) - // testStyleAttribute("font-size:calc(var(--fontSize) * 2)"); - } - - private void testStyleAttribute(String style) { - Element e = ElementFactory.createDiv(); - e.setAttribute("style", style); - Assert.assertEquals(style, e.getAttribute("style")); - } - - @Test(expected = IllegalArgumentException.class) - public void setInvalidStyleAsAttribute() { - Element e = ElementFactory.createDiv(); - e.setAttribute("style", "width:"); - } - - @Test(expected = IllegalArgumentException.class) - public void setInvalidStyleAsAttribute2() { - Element e = ElementFactory.createDiv(); - e.setAttribute("style", "width"); - } - - @Test - public void setVendorSpecificStylesProperty() { - Element e = ElementFactory.createDiv(); - String style = "-moz-user-input:inherit"; - e.setAttribute("style", style); - Assert.assertEquals("inherit", e.getStyle().get("mozUserInput")); - Assert.assertEquals(style, e.getAttribute("style")); - } - - @Test - public void setVendorSpecificStylesValue() { - Element e = ElementFactory.createDiv(); - String style = "display:-moz-box"; - e.setAttribute("style", style); - Assert.assertEquals("-moz-box", e.getStyle().get("display")); - Assert.assertEquals(style, e.getAttribute("style")); - - } - - @Test - public void setStyleAttributeTrailingSemicolon() { - Element e = ElementFactory.createDiv(); - String style = "width:12em"; - e.setAttribute("style", style + ";"); - Assert.assertEquals(style, e.getAttribute("style")); - } - - private void assertEqualsOne(String[] expected, String actual) { - for (String string : expected) { - if (string.equals(actual)) { - return; - } - } - String expectedString = Arrays.stream(expected) - .collect(Collectors.joining("> or <")); - Assert.fail( - "expected: <" + expectedString + "> but was <" + actual + ">"); - - } - - @Test(expected = IllegalArgumentException.class) - public void setEmptyStyleName() { - Element e = ElementFactory.createDiv(); - e.getStyle().set("", "foo"); - } - - @Test(expected = IllegalArgumentException.class) - public void setStyleNameExtraWhitespace() { - Element e = ElementFactory.createDiv(); - e.getStyle().set(" color", "red"); - } - - @Test(expected = IllegalArgumentException.class) - public void setStyleNameColon() { - Element e = ElementFactory.createDiv(); - e.getStyle().set("color:", "red"); - } - - @Test - public void setStyleValueExtraWhitespace() { - Element e = ElementFactory.createDiv(); - e.getStyle().set("color", "red "); - Assert.assertEquals("color:red", e.getAttribute("style")); - Assert.assertEquals("red", e.getStyle().get("color")); - } - - @Test - public void removeStyles() { - Element element = ElementFactory.createDiv(); - - element.getStyle().set("zIndex", "12"); - element.getStyle().set("background", "blue"); - - element.getStyle().remove("background"); - - Assert.assertEquals("z-index:12", element.getAttribute("style")); - - element.getStyle().remove("zIndex"); - - Assert.assertNull(element.getAttribute("style")); - Assert.assertFalse(element.hasAttribute("style")); - - Assert.assertEquals(0, element.getStyle().getNames().count()); - } - - @Test - public void removeStyleAttribute() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - - style.set("border", "1px solid green"); - - element.removeAttribute("style"); - - Assert.assertEquals(0, style.getNames().count()); - } - - @Test - public void validStyleWithSemicolon() { - Element element = ElementFactory.createDiv(); - String validStyle = "background: url('foo;bar')"; - Style style = element.getStyle(); - style.set("background", validStyle); - Assert.assertEquals(validStyle, style.get("background")); - } - - @Test - public void dashSeparatedSetStyle() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("border-color", "blue"); - Assert.assertEquals("blue", style.get("border-color")); - } - - @Test - public void dashSeparatedGetStyle() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("borderColor", "blue"); - style.set("border-foo", "bar"); - Assert.assertEquals("blue", style.get("border-color")); - Assert.assertEquals("bar", style.get("border-foo")); - } - - @Test - public void dashSeparatedHasStyle() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("borderColor", "blue"); - style.set("border-foo", "bar"); - Assert.assertTrue(style.has("border-color")); - Assert.assertTrue(style.has("border-foo")); - } - - @Test - public void dashSeparatedRemoveStyle() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("borderColor", "blue"); - style.set("border-foo", "bar"); - style.remove("border-color"); - style.remove("border-foo"); - - Assert.assertFalse(style.has("border-color")); - Assert.assertFalse(style.has("border-foo")); - } - - @Test - public void styleGetNamesDashAndCamelCase() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("borderColor", "blue"); - style.set("border-foo", "bar"); - - List styles = style.getNames().collect(Collectors.toList()); - Assert.assertEquals(2, styles.size()); - Assert.assertTrue(styles.contains("border-color")); - Assert.assertTrue(styles.contains("border-foo")); - } - - @Test - public void nullStyleValue() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("borderColor", "blue"); - style.set("borderColor", null); - List styles = style.getNames().collect(Collectors.toList()); - Assert.assertFalse(styles.contains("borderColor")); - } - - @Test - public void sendPropertyInCorrectFormatToClient() { - assertClientStyleKey("--some-variable", "--some-variable"); - assertClientStyleKey("-webkit-border", "-webkit-border"); - assertClientStyleKey("background-color", "background-color"); - assertClientStyleKey("color", "color"); - - assertClientStyleKey("-webkit-border", "webkitBorder"); - assertClientStyleKey("background-color", "backgroundColor"); - } - - private void assertClientStyleKey(String sentToClient, - String setUsingStyleApi) { - Element element = ElementFactory.createDiv(); - StateNode stateNode = element.getNode(); - ElementStylePropertyMap map = stateNode - .getFeature(ElementStylePropertyMap.class); - - Style style = element.getStyle(); - style.set(setUsingStyleApi, "foo"); - Assert.assertEquals("foo", style.get(setUsingStyleApi)); - Assert.assertEquals(sentToClient, map.getPropertyNames().toArray()[0]); - Assert.assertEquals("foo", map.getProperty(sentToClient)); - - } - - @Test - public void customPropertyStyle() { - Element element = ElementFactory.createDiv(); - Style style = element.getStyle(); - style.set("--some-variable", "foo"); - Assert.assertEquals("foo", style.get("--some-variable")); - } - - @Test - public void useCustomPropertyStyle() { - Element element = ElementFactory.createDiv(); - - Style style = element.getStyle(); - style.set("color", "var(--some-var)"); - Assert.assertEquals("var(--some-var)", style.get("color")); - } - - @Test - public void listenersFiredInRegisteredOrder() { - Element element = ElementFactory.createDiv(); - List eventOrder = new ArrayList<>(); - - for (int i = 0; i < 10; i++) { - final int j = i; - element.addEventListener("click", e -> { - eventOrder.add(j); - }); - } - fireEvent(element, "click"); - Assert.assertArrayEquals(new Object[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, - eventOrder.toArray()); - } - - private void fireEvent(Element element, String eventType) { - element.getNode().getFeature(ElementListenerMap.class).fireEvent( - new DomEvent(element, eventType, Json.createObject())); - - } - - @Test - public void eventsWhenListenerIsRegisteredManyTimes() { - AtomicInteger invocations = new AtomicInteger(0); - - DomEventListener listener = e -> { - invocations.incrementAndGet(); - }; - Element element = ElementFactory.createDiv(); - element.addEventListener("click", listener); - element.addEventListener("click", listener); - - fireEvent(element, "click"); - - Assert.assertEquals(2, invocations.get()); - } - - @Test(expected = IllegalStateException.class) - public void addAsOwnChild() { - Element element = ElementFactory.createDiv(); - element.appendChild(element); - } - - @Test(expected = IllegalStateException.class) - public void addAsChildOfChild() { - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - - child.appendChild(parent); - } - - @Override - protected void checkIsNotChild(Node parent, Element child) { - Assert.assertNotEquals(child.getParent(), parent); - - super.checkIsNotChild(parent, child); - } - - @Test - public void testGetOwnTextContent() { - Element element = ElementFactory.createDiv(); - element.setText("foo"); - element.appendChild(ElementFactory.createDiv() - .appendChild(ElementFactory.createSpan("span contents"))); - element.appendChild(ElementFactory.createStrong("strong contents")); - element.appendChild(Element.createText("Another text node")); - - Assert.assertEquals("fooAnother text node", element.getText()); - Assert.assertEquals("foospan contentsstrong contentsAnother text node", - element.getTextRecursively()); - } - - @Test - public void setResourceAttribute_elementIsNotAttached_elementHasAttribute() { - UI.setCurrent(createUI()); - Element element = ElementFactory.createDiv(); - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - - Assert.assertTrue(element.hasAttribute("foo")); - - Assert.assertTrue(element.getAttribute("foo").endsWith(resName)); - } - - @Test - public void setResourceAttribute_elementIsNotAttachedAndHasAttribute_elementHasAttribute() { - UI.setCurrent(createUI()); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", "bar"); - - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - - Assert.assertTrue(element.hasAttribute("foo")); - - Assert.assertTrue(element.getAttribute("foo").endsWith(resName)); - } - - @Test - public void setResourceAttributeSeveralTimes_elementIsNotAttached_elementHasAttribute() { - UI.setCurrent(createUI()); - Element element = ElementFactory.createDiv(); - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - - Assert.assertTrue(element.hasAttribute("foo")); - - resName = "resource1"; - resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - - Assert.assertTrue(element.hasAttribute("foo")); - - Assert.assertTrue(element.getAttribute("foo").endsWith(resName)); - } - - @Test(expected = IllegalArgumentException.class) - public void setResourceAttribute_nullValue() { - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", (StreamResource) null); - } - - @Test(expected = IllegalArgumentException.class) - public void setResourceAttribute_classAttribute() { - Element element = ElementFactory.createDiv(); - element.setAttribute("class", Mockito.mock(StreamResource.class)); - } - - @Test(expected = IllegalArgumentException.class) - public void setResourceAttribute_nullAttribute() { - Element element = ElementFactory.createDiv(); - element.setAttribute(null, Mockito.mock(StreamResource.class)); - } - - @Test - public void setResourceAttribute_elementIsAttached_elementHasAttribute() { - UI ui = createUI(); - UI.setCurrent(ui); - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - ui.getElement().setAttribute("foo", resource); - - Assert.assertTrue(ui.getElement().hasAttribute("foo")); - Assert.assertTrue( - ui.getElement().getAttribute("foo").endsWith(resName)); - } - - @Test - public void setResourceAttribute_elementIsAttached_setAnotherResource() - throws URISyntaxException { - UI ui = createUI(); - UI.setCurrent(ui); - StreamResource resource = createEmptyResource("resource1"); - ui.getElement().setAttribute("foo", resource); - - String uri = ui.getElement().getAttribute("foo"); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertTrue(res.isPresent()); - - String resName = "resource2"; - ui.getElement().setAttribute("foo", createEmptyResource(resName)); - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertFalse(res.isPresent()); - - Assert.assertTrue(ui.getElement().hasAttribute("foo")); - Assert.assertTrue( - ui.getElement().getAttribute("foo").endsWith(resName)); - } - - @Test - public void setResourceAttribute_elementIsAttached_setRawAttribute() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - StreamResource resource = createEmptyResource("resource"); - ui.getElement().setAttribute("foo", resource); - - String uri = ui.getElement().getAttribute("foo"); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertTrue(res.isPresent()); - res = null; - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - ui.getElement().setAttribute("foo", "bar"); - - TestUtil.isGarbageCollected(ref); - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - - Assert.assertFalse(res.isPresent()); - Assert.assertTrue(ui.getElement().hasAttribute("foo")); - Assert.assertTrue(ui.getElement().getAttribute("foo").equals("bar")); - } - - @Test - public void setResourceAttribute_elementIsAttached_removeAttribute() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - StreamResource resource = createEmptyResource("resource"); - ui.getElement().setAttribute("foo", resource); - - String uri = ui.getElement().getAttribute("foo"); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertTrue(res.isPresent()); - res = null; - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - ui.getElement().removeAttribute("foo"); - TestUtil.isGarbageCollected(ref); - - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertFalse(res.isPresent()); - Assert.assertFalse(ui.getElement().hasAttribute("foo")); - Assert.assertNull(ui.getElement().getAttribute("foo")); - } - - @Test - public void setResourceAttribute_attachElement_resourceIsRegistered() - throws URISyntaxException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - ui.getElement().appendChild(element); - - Assert.assertTrue(element.hasAttribute("foo")); - - String uri = element.getAttribute("foo"); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertTrue(res.isPresent()); - } - - @Test - public void setResourceAttribute_attachElement_setAnotherResource() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource1"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - String resName = "resource2"; - element.setAttribute("foo", createEmptyResource(resName)); - - ui.getElement().appendChild(element); - - Assert.assertTrue(element.hasAttribute("foo")); - - String uri = element.getAttribute("foo"); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertTrue(res.isPresent()); - Assert.assertTrue(uri.endsWith(resName)); - - // allow GC to collect element and all its (detach) listeners - element = null; - - TestUtil.isGarbageCollected(ref); - } - - @Test - public void setResourceAttribute_attachElement_setRawAttribute() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - element.setAttribute("foo", "bar"); - - TestUtil.isGarbageCollected(ref); - - ui.getElement().appendChild(element); - - Assert.assertTrue(element.hasAttribute("foo")); - Assert.assertEquals("bar", element.getAttribute("foo")); - } - - @Test - public void setResourceAttribute_attachElement_removeAttribute() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - element.removeAttribute("foo"); - - ui.getElement().appendChild(element); - - TestUtil.isGarbageCollected(ref); - - Assert.assertFalse(element.hasAttribute("foo")); - - Assert.assertNull(element.getAttribute("foo")); - } - - @Test - public void setResourceAttribute_attachElement_setAnotherResourceAfterAttaching() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource1"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - ui.getElement().appendChild(element); - - String resName = "resource2"; - element.setAttribute("foo", createEmptyResource(resName)); - - Assert.assertTrue(element.hasAttribute("foo")); - - TestUtil.isGarbageCollected(ref); - - Assert.assertNull(ref.get()); - - String uri = element.getAttribute("foo"); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, new URI(uri)); - Assert.assertTrue(res.isPresent()); - Assert.assertTrue(uri.endsWith(resName)); - } - - @Test - public void setResourceAttribute_attachElement_setRawAttributeAfterAttaching() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - ui.getElement().appendChild(element); - - element.setAttribute("foo", "bar"); - - TestUtil.isGarbageCollected(ref); - - Assert.assertNull(ref.get()); - - Assert.assertTrue(element.hasAttribute("foo")); - - Assert.assertEquals("bar", element.getAttribute("foo")); - } - - @Test - public void setResourceAttribute_attachElement_removeAttributeAfterAttaching() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - - StreamResource resource = createEmptyResource("resource"); - Element element = ElementFactory.createDiv(); - element.setAttribute("foo", resource); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - ui.getElement().appendChild(element); - - element.removeAttribute("foo"); - - TestUtil.isGarbageCollected(ref); - - Assert.assertNull(ref.get()); - - Assert.assertFalse(element.hasAttribute("foo")); - - Assert.assertNull(element.getAttribute("foo")); - } - - @Test - public void setResourceAttribute_detachElement_resourceIsUnregistered() - throws URISyntaxException, InterruptedException { - UI ui = createUI(); - UI.setCurrent(ui); - Element element = ElementFactory.createDiv(); - ui.getElement().appendChild(element); - - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - String attribute = element.getAttribute("foo"); - - WeakReference ref = new WeakReference<>(resource); - resource = null; - - URI uri = new URI(attribute); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertTrue(res.isPresent()); - - ui.getElement().removeAllChildren(); - - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertFalse(res.isPresent()); - - Assert.assertTrue(element.hasAttribute("foo")); - Assert.assertNotNull(element.getAttribute("foo")); - Assert.assertTrue(element.getAttribute("foo").endsWith(resName)); - - element.setAttribute("foo", "bar"); - Assert.assertTrue(element.hasAttribute("foo")); - Assert.assertEquals("bar", element.getAttribute("foo")); - - TestUtil.isGarbageCollected(ref); - } - - @Test - public void setResourceAttribute_detachAndReattachElement_resourceReregistered() - throws URISyntaxException { - UI ui = createUI(); - UI.setCurrent(ui); - Element element = ElementFactory.createDiv(); - ui.getElement().appendChild(element); - - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - String attribute = element.getAttribute("foo"); - - URI uri = new URI(attribute); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertTrue(res.isPresent()); - - ui.getElement().removeAllChildren(); - - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertFalse(res.isPresent()); - - ui.getElement().appendChild(element); - - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertTrue(res.isPresent()); - } - - @Test - public void setResourceAttribute_attachAndDetachAndReattachElement_resourceReregistered() - throws URISyntaxException { - UI ui = createUI(); - UI.setCurrent(ui); - Element element = ElementFactory.createDiv(); - - String resName = "resource"; - StreamResource resource = createEmptyResource(resName); - element.setAttribute("foo", resource); - String attribute = element.getAttribute("foo"); - - ui.getElement().appendChild(element); - - URI uri = new URI(attribute); - Optional res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertTrue(res.isPresent()); - - ui.getElement().removeAllChildren(); - - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertFalse(res.isPresent()); - - ui.getElement().appendChild(element); - - res = ui.getSession().getResourceRegistry() - .getResource(StreamResource.class, uri); - Assert.assertTrue(res.isPresent()); - } - - @Test(expected = UnsupportedOperationException.class) - public void setResourceAttribute_elementIsText_operationIsNotSupported() { - Element.createText("").setAttribute("foo", - Mockito.mock(StreamResource.class)); - } - - @Test - public void testAttachListener_parentAttach_childListenersTriggered() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - Element grandChild = ElementFactory.createDiv(); - - AtomicInteger childTriggered = new AtomicInteger(); - AtomicInteger grandChildTriggered = new AtomicInteger(); - - Registration registrationHandle = child.addAttachListener(event -> { - childTriggered.addAndGet(1); - }); - child.addAttachListener(event -> { - Assert.assertEquals(child, event.getSource()); - }); - grandChild.addAttachListener(event -> { - grandChildTriggered.addAndGet(1); - }); - grandChild.addAttachListener(event -> { - Assert.assertEquals(grandChild, event.getSource()); - }); - - parent.appendChild(child); - child.appendChild(grandChild); - - Assert.assertEquals(childTriggered.get(), 0); - Assert.assertEquals(grandChildTriggered.get(), 0); - - body.appendChild(parent); - - Assert.assertEquals(childTriggered.get(), 1); - Assert.assertEquals(grandChildTriggered.get(), 1); - - body.removeAllChildren(); - parent.removeAllChildren(); - - body.appendChild(parent); - parent.appendChild(child); - - Assert.assertEquals(childTriggered.get(), 2); - Assert.assertEquals(grandChildTriggered.get(), 2); - - registrationHandle.remove(); - - body.removeAllChildren(); - body.appendChild(child); - - Assert.assertEquals(childTriggered.get(), 2); - Assert.assertEquals(grandChildTriggered.get(), 3); - } - - @Test - public void testDetachListener_parentDetach_childListenersTriggered() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - Element grandChild = ElementFactory.createDiv(); - - AtomicInteger triggered = new AtomicInteger(); - - Registration registrationHandle = child.addDetachListener(event -> { - triggered.addAndGet(1); - Assert.assertEquals(child, event.getSource()); - }); - - grandChild.addDetachListener(event -> { - triggered.addAndGet(1); - Assert.assertEquals(grandChild, event.getSource()); - }); - - child.appendChild(grandChild); - parent.appendChild(child); - body.appendChild(parent); - - Assert.assertEquals(triggered.get(), 0); - - body.removeAllChildren(); - Assert.assertEquals(triggered.get(), 2); - - body.appendChild(parent); - body.removeAllChildren(); - - Assert.assertEquals(triggered.get(), 4); - - body.appendChild(parent); - registrationHandle.remove(); - - body.removeAllChildren(); - - Assert.assertEquals(triggered.get(), 5); - } - - @Test - public void testAttachListener_eventOrder_childFirst() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - - AtomicBoolean parentAttached = new AtomicBoolean(); - AtomicBoolean childAttached = new AtomicBoolean(); - - child.addAttachListener(event -> { - childAttached.set(true); - Assert.assertFalse(parentAttached.get()); - }); - parent.addAttachListener(event -> { - parentAttached.set(true); - Assert.assertTrue(childAttached.get()); - }); - - body.appendChild(parent); - - Assert.assertTrue(parentAttached.get()); - Assert.assertTrue(childAttached.get()); - } - - @Test - public void testDetachListener_eventOrder_childFirst() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - parent.appendChild(child); - body.appendChild(parent); - - AtomicBoolean parentDetached = new AtomicBoolean(); - AtomicBoolean childDetached = new AtomicBoolean(); - - child.addDetachListener(event -> { - childDetached.set(true); - Assert.assertFalse(parentDetached.get()); - }); - parent.addDetachListener(event -> { - parentDetached.set(true); - Assert.assertTrue(childDetached.get()); - }); - - body.removeAllChildren(); - - Assert.assertTrue(parentDetached.get()); - Assert.assertTrue(childDetached.get()); - } - - @Test - public void testAttachDetach_elementMoved_bothEventsTriggered() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - - parent.appendChild(child); - body.appendChild(parent); - - AtomicBoolean attached = new AtomicBoolean(); - AtomicBoolean detached = new AtomicBoolean(); - - child.addAttachListener(event -> { - attached.set(true); - Assert.assertTrue(detached.get()); - }); - child.addDetachListener(event -> { - detached.set(true); - Assert.assertFalse(attached.get()); - }); - - body.appendChild(child); - - Assert.assertTrue(attached.get()); - Assert.assertTrue(detached.get()); - } - - @Test - public void testAttachEvent_stateTreeCanFound() { - Element body = new UI().getElement(); - Element child = ElementFactory.createDiv(); - - AtomicInteger attached = new AtomicInteger(); - - child.addAttachListener(event -> { - Assert.assertNotNull(event.getSource().getNode().getOwner()); - Assert.assertNotEquals(NullOwner.get(), - event.getSource().getNode().getOwner()); - }); - child.addAttachListener(event -> attached.incrementAndGet()); - - body.appendChild(child); - Assert.assertEquals(1, attached.get()); - } - - @Test - public void testDetachEvent_stateTreeCanFound() { - Element body = new UI().getElement(); - Element child = ElementFactory.createDiv(); - body.appendChild(child); - - AtomicInteger detached = new AtomicInteger(); - - child.addDetachListener(event -> { - Assert.assertNotNull(event.getSource().getNode().getOwner()); - Assert.assertNotEquals(NullOwner.get(), - event.getSource().getNode().getOwner()); - }); - child.addDetachListener(event -> detached.incrementAndGet()); - - body.removeAllChildren(); - - Assert.assertEquals(1, detached.get()); - } - - @Test - public void testRemoveFromTree_inDetachListener_removedFromParent() { - Element body = new UI().getElement(); - Element child = ElementFactory.createDiv(); - body.appendChild(child); - - child.addDetachListener(event -> child.removeFromTree()); - - body.removeAllChildren(); - - Assert.assertEquals(null, child.getParent()); - } - - @Test - public void testRemoveFromTree_isVirtualChild_removedFromParent() { - Element body = new UI().getElement(); - Element child = ElementFactory.createDiv(); - - body.getNode().getFeature(VirtualChildrenList.class) - .append(child.getNode(), ""); - - Assert.assertTrue(child.isVirtualChild()); - - child.removeFromTree(); - - Assert.assertFalse(child.isVirtualChild()); - Assert.assertEquals(0, - body.getNode().getFeature(VirtualChildrenList.class).size()); - } - - private StreamResource createEmptyResource(String resName) { - return new StreamResource(resName, - () -> new ByteArrayInputStream(new byte[0])); - } - - @SuppressWarnings("serial") - private UI createUI() { - VaadinSession session = new AlwaysLockedVaadinSession( - new MockVaadinServletService()); - UI ui = new UI() { - @Override - public VaadinSession getSession() { - return session; - } - }; - return ui; - } - - @Test - public void insertAtCurrentPositionNoOp() { - // Must have an UI to get attach events - UI ui = new UI(); - Element parent = ui.getElement(); - Element child = ElementFactory.createDiv(); - - parent.appendChild(child); - - child.addDetachListener( - e -> Assert.fail("Child should not be detached")); - parent.insertChild(0, child); - } - - @Test - public void textNodeTransformsNullToEmptyAndDoesNotThrowException() { - Element e = Element.createText(null); - Assert.assertEquals("", e.getText()); - } - - @Test - public void textNodeOuterHtml() { - Element e = Element.createText("foobar"); - Assert.assertEquals("foobar", e.getOuterHTML()); - } - - @Test - public void singleElementOuterHtml() { - Element e = ElementFactory.createAnchor(); - Assert.assertEquals("", e.getOuterHTML()); - } - - @Test - public void elementTreeOuterHtml() { - Element div = ElementFactory.createDiv(); - Element span = ElementFactory.createSpan(); - Element button = ElementFactory.createButton("hello"); - - div.appendChild(span); - span.appendChild(button); - - Assert.assertEquals( - "
\n" + " \n" + "
", - div.getOuterHTML()); - } - - @Test - public void elementAttributesOuterHtml() { - Element div = ElementFactory.createDiv(); - div.setAttribute("foo", "bar"); - div.getStyle().set("width", "20px"); - div.getClassList().add("cls"); - div.setAttribute("pin", ""); - - Assert.assertEquals( - "
", - div.getOuterHTML()); - } - - @Test - public void elementAttributeSpecialCharactersOuterHtml() { - Element div = ElementFactory.createDiv(); - div.setAttribute("foo", "bar\"'""); - - Assert.assertEquals("
", - div.getOuterHTML()); - } - - @Test - public void htmlComponentOuterHtml() { - Html html = new Html( - "
"); - Assert.assertEquals( - "
\n" - + " \n" + "
", - html.getElement().getOuterHTML()); - } - - @Test - public void callFunctionBeforeAttach() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - element.callJsFunction("noArgsMethod"); - ui.getElement().appendChild(element); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - assertPendingJs(ui, "return $0.noArgsMethod()", element); - } - - @Test - public void callFunctionAfterAttach() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - ui.getElement().appendChild(element); - element.callJsFunction("noArgsMethod"); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - assertPendingJs(ui, "return $0.noArgsMethod()", element); - } - - @Test - public void callFunctionBeforeDetach() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - ui.getElement().appendChild(element); - element.callJsFunction("noArgsMethod"); - ui.getElement().removeAllChildren(); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - List invocations = ui.getInternals() - .dumpPendingJavaScriptInvocations(); - Assert.assertTrue(invocations.isEmpty()); - } - - @Test - public void callFunctionBeforeReAttach() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - ui.getElement().appendChild(element); - element.callJsFunction("noArgsMethod"); - - Element div = ElementFactory.createDiv(); - ui.getElement().appendChild(div); - div.appendChild(element); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - assertPendingJs(ui, "return $0.noArgsMethod()", element); - } - - @Test - public void callFunctionOneParam() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - element.callJsFunction("method", "foo"); - ui.getElement().appendChild(element); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - assertPendingJs(ui, "return $0.method($1)", element, "foo"); - - } - - @Test - public void callFunctionTwoParams() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - element.callJsFunction("method", "foo", 123); - ui.getElement().appendChild(element); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - assertPendingJs(ui, "return $0.method($1,$2)", element, "foo", 123); - } - - @Test - public void callFunctionOnProperty() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - element.callJsFunction("property.method"); - ui.getElement().appendChild(element); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - assertPendingJs(ui, "return $0.property.method()", element); - } - - @Test - public void callFunctionOnSubProperty() { - UI ui = new MockUI(); - Element element = ElementFactory.createDiv(); - element.callJsFunction("property.other.method"); - ui.getElement().appendChild(element); - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - - assertPendingJs(ui, "return $0.property.other.method()", element); - } - - @Test - public void attachShadowRoot_shadowRootCreatedAndChildrenArePreserved() { - Element element = ElementFactory.createDiv(); - Element button = ElementFactory.createButton(); - Element emphasis = ElementFactory.createEmphasis(); - element.appendChild(button, emphasis); - - ShadowRoot shadow = element.attachShadow(); - Assert.assertNotNull(shadow); - Assert.assertEquals(element, shadow.getHost()); - Assert.assertEquals(shadow, element.getShadowRoot().get()); - Assert.assertEquals(2, element.getChildCount()); - Assert.assertEquals(2, element.getChildren().count()); - Assert.assertEquals(button, element.getChild(0)); - Assert.assertEquals(emphasis, element.getChild(1)); - } - - @Test - public void getShadowRoot_shadowRootIsEmpty() { - Element element = ElementFactory.createDiv(); - Assert.assertFalse(element.getShadowRoot().isPresent()); - } - - @Test - public void getParentNode_parentNodeIsTheSameAsParent() { - Element element = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - - element.appendChild(child); - - Assert.assertEquals(child.getParent(), child.getParentNode()); - } - - @Test - public void getParentNode_elementInShadowRoot_parentIsNull() { - ShadowRoot element = ElementFactory.createDiv().attachShadow(); - Element child = ElementFactory.createDiv(); - - element.appendChild(child); - - Assert.assertNull(child.getParent()); - Assert.assertEquals(element, child.getParentNode()); - } - - @Test - public void parentIsDisabled_childIsDisabled() { - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - - parent.appendChild(child); - - Assert.assertTrue("Parent should be enabled", parent.isEnabled()); - Assert.assertTrue("Child should be enabled", child.isEnabled()); - - parent.setEnabled(false); - - Assert.assertFalse("Parent should be disabled", parent.isEnabled()); - Assert.assertFalse("Child should be disabled", child.isEnabled()); - - child.removeFromParent(); - - Assert.assertTrue("Child should be enabled", child.isEnabled()); - } - - @Test - public void emptyElement_setDisabled_noChildFeatures() { - Element element = ElementFactory.createDiv(); - - element.setEnabled(false); - - BasicElementStateProviderTest.assertNoChildFeatures(element); - } - - @Test - public void emptyElement_isVirtualChild_noChildFeatures() { - Element element = ElementFactory.createDiv(); - - element.isVirtualChild(); - - BasicElementStateProviderTest.assertNoChildFeatures(element); - } - - @Test - public void elementWithoutComponent_getComponentFeature() { - Element element = ElementFactory.createDiv(); - element.appendChild(ElementFactory.createDiv()); - - element.getComponent(); - - Assert.assertFalse( - "getComponent() shouldn't initialize a component mapping feature", - element.getNode() - .getFeatureIfInitialized(ComponentMapping.class) - .isPresent()); - } - - @Test - public void readMissingProperty_noFeatureInitialized() { - Element element = ElementFactory.createDiv(); - - element.getProperty("foo"); - element.hasProperty("foo"); - element.removeProperty("foo"); - element.getPropertyNames().collect(Collectors.toList()); - - Assert.assertFalse( - "reading a property value shouldn't initialize a property map feature", - element.getNode() - .getFeatureIfInitialized(ElementPropertyMap.class) - .isPresent()); - } - - @Test - public void readMissingAttribute_noFeatureInitialized() { - Element element = ElementFactory.createDiv(); - - element.getAttribute("foo"); - element.hasAttribute("foo"); - element.removeAttribute("foo"); - element.getAttributeNames().collect(Collectors.toList()); - - Assert.assertFalse( - "reading an attribute value shouldn't initialize an attribute map feature", - element.getNode() - .getFeatureIfInitialized(ElementAttributeMap.class) - .isPresent()); - } - - @Test - public void virtualChildren_areIdentifiedAsSuch() { - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - Element virtualChild = ElementFactory.createDiv(); - Element grandVirtualChild = ElementFactory.createDiv(); - - parent.appendChild(child); - parent.appendVirtualChild(virtualChild); - virtualChild.appendChild(grandVirtualChild); - - Assert.assertFalse(parent.isVirtualChild()); - Assert.assertFalse(child.isVirtualChild()); - Assert.assertTrue(virtualChild.isVirtualChild()); - Assert.assertFalse(grandVirtualChild.isVirtualChild()); - } - - @Test - public void domPropertyListener_registersListenerAndDomTrigger() { - Element element = ElementFactory.createDiv(); - - AtomicReference listenerValue = new AtomicReference<>(); - - element.addPropertyChangeListener("property", "event", event -> { - if (listenerValue.getAndSet(event.getValue()) != null) { - Assert.fail("Unexpected event"); - } - }); - - Assert.assertEquals("The property should be synchronized", - DisabledUpdateMode.ONLY_WHEN_ENABLED, - element.getNode().getFeature(ElementListenerMap.class) - .getPropertySynchronizationMode("property")); - - ElementListenerMap listenerMap = element.getNode() - .getFeature(ElementListenerMap.class); - - Assert.assertEquals("A DOM event synchronization should be defined", - Collections.singleton( - JsonConstants.SYNCHRONIZE_PROPERTY_TOKEN + "property"), - ElementListenersTest.getExpressions(listenerMap, "event")); - - element.setProperty("property", "value"); - Assert.assertEquals("Listener shold be registered", listenerValue.get(), - "value"); - } - - @Test - public void domPropertyListener_unregisterCleansEverything() { - Element element = ElementFactory.createDiv(); - - DomListenerRegistration registration = element - .addPropertyChangeListener("property", "event", event -> { - Assert.fail("Unexpected event"); - }); - registration.remove(); - - Assert.assertNull("The property should not be synchronized", - element.getNode().getFeature(ElementListenerMap.class) - .getPropertySynchronizationMode("property")); - - ElementListenerMap listenerMap = element.getNode() - .getFeature(ElementListenerMap.class); - - Assert.assertEquals("There should be no DOM listener", - Collections.emptySet(), - ElementListenersTest.getExpressions(listenerMap, "event")); - - // Should not trigger assert in the listener - element.setProperty("property", "value"); - } - - @Test - public void removingVirtualChildrenIsPossible() { - Element parent = new Element("root"); - Element child1 = new Element("main"); - Element child2 = new Element("menu"); - - parent.appendVirtualChild(child1, child2); - - parent.removeVirtualChild(child2, child1); - - Assert.assertNull(child1.getParent()); - Assert.assertFalse(child1.isVirtualChild()); - - Assert.assertNull(child2.getParent()); - Assert.assertFalse(child2.isVirtualChild()); - } - - @Test(expected = IllegalArgumentException.class) - public void removeVirtualChildren_notVirtualChild_fails() { - Element parent = new Element("root"); - Element child1 = new Element("main"); - - parent.appendChild(child1); - - parent.removeVirtualChild(child1); - } - - @Test(expected = IllegalArgumentException.class) - public void removeFromParent_virtualChild_fails() { - Element parent = new Element("root"); - Element child1 = new Element("main"); - - parent.appendVirtualChild(child1); - - child1.removeFromParent(); - } - - @Test - public void executeJavaScript_delegatesToExecJs() { - AtomicReference invokedExpression = new AtomicReference<>(); - AtomicReference invokedParams = new AtomicReference<>(); - - Element element = new Element("div") { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... parameters) { - String oldExpression = invokedExpression.getAndSet(expression); - Assert.assertNull("There should be no old expression", - oldExpression); - - Serializable[] oldParams = invokedParams.getAndSet(parameters); - Assert.assertNull("There should be no old params", oldParams); - - return null; - } - }; - - element.executeJavaScript("foo", 1, true); - - Assert.assertEquals("foo", invokedExpression.get()); - Assert.assertEquals(Integer.valueOf(1), invokedParams.get()[0]); - Assert.assertEquals(Boolean.TRUE, invokedParams.get()[1]); - } - - @Test - public void callFunction_delegatesToCallJsFunction() { - AtomicReference invokedFuction = new AtomicReference<>(); - AtomicReference invokedParams = new AtomicReference<>(); - - Element element = new Element("div") { - @Override - public PendingJavaScriptResult callJsFunction(String functionName, - Serializable... arguments) { - String oldExpression = invokedFuction.getAndSet(functionName); - Assert.assertNull("There should be no old function name", - oldExpression); - - Serializable[] oldParams = invokedParams.getAndSet(arguments); - Assert.assertNull("There should be no old params", oldParams); - - return null; - } - }; - - element.callFunction("foo", 1, true); - - Assert.assertEquals("foo", invokedFuction.get()); - Assert.assertEquals(Integer.valueOf(1), invokedParams.get()[0]); - Assert.assertEquals(Boolean.TRUE, invokedParams.get()[1]); - } - - @Override - protected Element createParentNode() { - return ElementFactory.createDiv(); - } - - @Override - protected void assertChild(Node parent, int index, Element child) { - Assert.assertEquals(parent, child.getParent()); - Assert.assertEquals(child, parent.getChild(index)); - } - - private void assertPendingJs(UI ui, String js, Serializable... arguments) { - List pendingJs = ui.getInternals() - .dumpPendingJavaScriptInvocations(); - JavaScriptInvocation expected = new JavaScriptInvocation(js, arguments); - Assert.assertEquals(1, pendingJs.size()); - assertEquals(expected, pendingJs.get(0).getInvocation()); - - } - - private void assertEquals(JavaScriptInvocation expected, - JavaScriptInvocation actual) { - Assert.assertEquals(expected.getExpression(), actual.getExpression()); - Assert.assertArrayEquals(expected.getParameters().toArray(), - actual.getParameters().toArray()); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/ElementUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/ElementUtilTest.java deleted file mode 100644 index 9d70a3011e2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/ElementUtilTest.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import java.util.Optional; - -import org.mockito.Mockito; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Node; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; -import com.vaadin.flow.internal.nodefeature.InertData; - -import com.vaadin.flow.component.Component; - -public class ElementUtilTest { - - private Element parent; - private Element child; - private Element grandchild; - private StateTree stateTree; - - @Test - public void isNullValidAttribute() { - Assert.assertFalse(ElementUtil.isValidAttributeName(null)); - } - - @Test - public void isEmptyValidAttribute() { - Assert.assertFalse(ElementUtil.isValidAttributeName("")); - } - - @Test(expected = AssertionError.class) - public void isUpperCaseValidAttribute() { - // isValidAttributeName is designed to only be called with lowercase - // attribute names - ElementUtil.isValidAttributeName("FOO"); - } - - @Test - public void componentNotInitiallyAttached() { - Element e = ElementFactory.createDiv(); - Assert.assertFalse(e.getComponent().isPresent()); - } - - @Test - public void attachToComponent() { - Element e = ElementFactory.createDiv(); - Component c = Mockito.mock(Component.class); - ElementUtil.setComponent(e, c); - Assert.assertEquals(c, e.getComponent().get()); - } - - @Test - public void attachComponentToTextElement() { - Element e = Element.createText("Text text"); - Component c = Mockito.mock(Component.class); - ElementUtil.setComponent(e, c); - Assert.assertEquals(c, e.getComponent().get()); - } - - @Test(expected = IllegalStateException.class) - public void attachTwiceToComponent() { - Element e = ElementFactory.createDiv(); - Component c = Mockito.mock(Component.class); - ElementUtil.setComponent(e, c); - ElementUtil.setComponent(e, c); - } - - @Test(expected = IllegalArgumentException.class) - public void attachToNull() { - Element e = ElementFactory.createDiv(); - ElementUtil.setComponent(e, null); - } - - @Test(expected = IllegalStateException.class) - public void attachTwoComponents() { - Element e = ElementFactory.createDiv(); - Component c = Mockito.mock(Component.class); - Component c2 = Mockito.mock(Component.class); - ElementUtil.setComponent(e, c); - ElementUtil.setComponent(e, c2); - } - - @Test - public void toAndFromJsoup() { - final String EXPECTED_TEXT_1 = "Some text"; - final String EXPECTED_TEXT_2 = "Other text"; - - Element originalElement = ElementFactory.createDiv(); - originalElement.appendChild( - ElementFactory.createParagraph(EXPECTED_TEXT_1).appendChild( - ElementFactory.createDiv(EXPECTED_TEXT_2))); - - Document jDocument = Document.createShell("http://example.com"); - - Node jNode = ElementUtil.toJsoup(jDocument, originalElement); - - Optional optionalElement = ElementUtil.fromJsoup(jNode); - - Assert.assertTrue("Element should have been created from jNode", - optionalElement.isPresent()); - - Element recreatedElement = optionalElement.get(); - - // root - Assert.assertEquals("Root element should be div", "div", - recreatedElement.getTag()); - // child - Assert.assertEquals("Child element should be a paragraph", "p", - recreatedElement.getChild(0).getTag()); - Assert.assertEquals("Child element should have text", EXPECTED_TEXT_1, - recreatedElement.getChild(0).getText()); - // grand-child (#1, since #0 is the text node) - Assert.assertEquals("Grand-child element should be a div", "div", - recreatedElement.getChild(0).getChild(1).getTag()); - Assert.assertEquals("Grand-child element should have text", - EXPECTED_TEXT_2, - recreatedElement.getChild(0).getChild(1).getText()); - } - - @Test - public void isValidTagName_validTagNames() { - Assert.assertTrue(ElementUtil.isValidTagName("foo")); - Assert.assertTrue(ElementUtil.isValidTagName("foo-bar")); - Assert.assertTrue(ElementUtil.isValidTagName("foo_bar")); - Assert.assertTrue(ElementUtil.isValidTagName("foo_bar-baz")); - Assert.assertTrue(ElementUtil.isValidTagName("foo12.bar3")); - Assert.assertTrue(ElementUtil.isValidTagName("foo-._")); - Assert.assertTrue(ElementUtil.isValidTagName("x")); - } - - @Test - public void isValidTagName_invalidTagNames() { - Assert.assertFalse(ElementUtil.isValidTagName("1foo")); - Assert.assertFalse(ElementUtil.isValidTagName("-foo")); - Assert.assertFalse(ElementUtil.isValidTagName("_foo")); - Assert.assertFalse(ElementUtil.isValidTagName(".foo")); - Assert.assertFalse(ElementUtil.isValidTagName("foo>")); - Assert.assertFalse(ElementUtil.isValidTagName("foo$bar")); - } - - @Test - public void parentIsInert_childIgnoresParentInert_allThePermutations() { - setupElementHierarchy(); - - Assert.assertFalse("by default parent inert state is not ignored", - isIgnoreParentInert(child)); - Assert.assertFalse("by default element should not be inert", - isInert(child)); - - ElementUtil.setIgnoreParentInert(child, true); - Assert.assertFalse(isInert(child)); - - ElementUtil.setInert(parent, true); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertFalse(isInert(child)); - Assert.assertFalse(isInert(grandchild)); - - ElementUtil.setIgnoreParentInert(child, false); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertTrue(isInert(grandchild)); - - ElementUtil.setIgnoreParentInert(child, true); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertFalse(isInert(child)); - Assert.assertFalse(isInert(grandchild)); - - ElementUtil.setInert(child, true); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertTrue(isInert(grandchild)); - - ElementUtil.setInert(parent, false); - simulateWritingChangesToClient(); - - Assert.assertFalse(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertTrue(isInert(grandchild)); - } - - @Test - public void parentInert_grandChildIgnoresInert_notInert() { - setupElementHierarchy(); - - ElementUtil.setInert(parent, true); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertTrue(isInert(grandchild)); - - ElementUtil.setIgnoreParentInert(grandchild, true); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertFalse(isInert(grandchild)); - - ElementUtil.setIgnoreParentInert(grandchild, false); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertTrue(isInert(grandchild)); - } - - @Test - public void parentInertGrandChildIgnores_statesChangedAtSameTime_changesApplied() { - setupElementHierarchy(); - - ElementUtil.setInert(parent, true); - ElementUtil.setIgnoreParentInert(grandchild, true); - simulateWritingChangesToClient(); - - Assert.assertTrue(isInert(parent)); - Assert.assertTrue(isInert(child)); - Assert.assertFalse(isInert(grandchild)); - } - - @Test - public void parentInert_siblingIgnoresInheritingInert_siblingInert() { - final Element sibling = ElementFactory.createDiv(); - } - - private void setupElementHierarchy() { - parent = ElementFactory.createDiv(); - child = ElementFactory.createDiv(); - grandchild = ElementFactory.createDiv(); - parent.appendChild(child.appendChild(grandchild)); - stateTree = new StateTree(new UI().getInternals(), - ElementChildrenList.class, InertData.class); - final StateNode rootNode = stateTree.getRootNode(); - rootNode.getFeature(ElementChildrenList.class).add(0, parent.getNode()); - } - - private boolean isIgnoreParentInert(Element element) { - return element.getNode().getFeatureIfInitialized(InertData.class) - .map(InertData::isIgnoreParentInert).orElse(false); - } - - private boolean isInert(Element element) { - return element.getNode().isInert(); - } - - private void simulateWritingChangesToClient() { - stateTree.collectChanges(nodeChanges -> { - }); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/ShadowRootStateProviderTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/ShadowRootStateProviderTest.java deleted file mode 100644 index 7296b5fa4ac..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/ShadowRootStateProviderTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.dom.impl.ShadowRootStateProvider; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.nodefeature.ShadowRootData; - -public class ShadowRootStateProviderTest { - - @Test - public void supportsSelfCreatedNode() { - ShadowRootStateProvider provider = ShadowRootStateProvider.get(); - StateNode node = new StateNode(ShadowRootData.class); - StateNode shadowRoot = provider.createShadowRootNode(node); - Assert.assertTrue(provider.supports(shadowRoot)); - } - - @Test - public void doesNotSupportEmptyNode() { - ShadowRootStateProvider provider = ShadowRootStateProvider.get(); - Assert.assertFalse(provider.supports(new StateNode())); - } - - @Test - public void createShadowRootNode_originalNodeIsInitialized() { - ShadowRootStateProvider provider = ShadowRootStateProvider.get(); - StateNode node = new StateNode(ShadowRootData.class); - StateNode shadowRoot = provider.createShadowRootNode(node); - Assert.assertEquals(shadowRoot, - node.getFeature(ShadowRootData.class).getShadowRoot()); - } - - @Test - public void getParent_parentIsHostElement() { - ShadowRootStateProvider provider = ShadowRootStateProvider.get(); - StateNode node = new StateNode(ShadowRootData.class); - StateNode shadowRoot = provider.createShadowRootNode(node); - Assert.assertEquals(node, shadowRoot.getParent()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/ShadowRootTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/ShadowRootTest.java deleted file mode 100644 index 8e8778d9a2b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/ShadowRootTest.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.NodeVisitor.ElementType; -import com.vaadin.flow.dom.impl.ShadowRootStateProvider; -import com.vaadin.flow.internal.NullOwner; -import com.vaadin.flow.internal.nodefeature.NodeProperties; -import com.vaadin.flow.shared.Registration; - -public class ShadowRootTest extends AbstractNodeTest { - - @Test - public void publicElementMethodsShouldReturnElement() { - Set ignore = new HashSet<>(); - ignore.add("toString"); - ignore.add("hashCode"); - ignore.add("equals"); - - // Returns index of child element - ignore.add("indexOfChild"); - - assertMethodsReturnType(ShadowRoot.class, ignore); - } - - @Test - public void insertAtCurrentPositionNoOp() { - // Must have an UI to get attach events - UI ui = new UI(); - ShadowRoot parent = ui.getElement().attachShadow(); - Element child = ElementFactory.createDiv(); - - parent.appendChild(child); - - child.addDetachListener( - e -> Assert.fail("Child should not be detached")); - parent.insertChild(0, child); - } - - @Test - public void equalsSelf() { - ShadowRoot root = createParentNode(); - Assert.assertTrue(root.equals(root)); - } - - @Test - public void notEqualsNull() { - ShadowRoot root = createParentNode(); - Assert.assertFalse(root.equals(null)); - } - - @Test - public void attachListener_parentAttach_childListenersTriggered() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - Element grandChild = ElementFactory.createDiv(); - - AtomicInteger childTriggered = new AtomicInteger(); - AtomicInteger grandChildTriggered = new AtomicInteger(); - - Registration registrationHandle = child.addAttachListener(event -> { - childTriggered.addAndGet(1); - }); - child.addAttachListener(event -> { - Assert.assertEquals(child, event.getSource()); - }); - grandChild.addAttachListener(event -> { - grandChildTriggered.addAndGet(1); - }); - grandChild.addAttachListener(event -> { - Assert.assertEquals(grandChild, event.getSource()); - }); - - parent.attachShadow().appendChild(child); - child.appendChild(grandChild); - - Assert.assertEquals(childTriggered.get(), 0); - Assert.assertEquals(grandChildTriggered.get(), 0); - - body.appendChild(parent); - - Assert.assertEquals(childTriggered.get(), 1); - Assert.assertEquals(grandChildTriggered.get(), 1); - - body.removeAllChildren(); - parent.getShadowRoot().get().removeAllChildren(); - - body.appendChild(parent); - parent.getShadowRoot().get().appendChild(child); - - Assert.assertEquals(childTriggered.get(), 2); - Assert.assertEquals(grandChildTriggered.get(), 2); - - registrationHandle.remove(); - - body.removeAllChildren(); - body.appendChild(child); - - Assert.assertEquals(childTriggered.get(), 2); - Assert.assertEquals(grandChildTriggered.get(), 3); - } - - @Test - public void detachListener_parentDetach_childListenersTriggered() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - Element grandChild = ElementFactory.createDiv(); - - AtomicInteger triggered = new AtomicInteger(); - - Registration registrationHandle = child.addDetachListener(event -> { - triggered.addAndGet(1); - Assert.assertEquals(child, event.getSource()); - }); - - grandChild.addDetachListener(event -> { - triggered.addAndGet(1); - Assert.assertEquals(grandChild, event.getSource()); - }); - - child.appendChild(grandChild); - parent.attachShadow().appendChild(child); - body.appendChild(parent); - - Assert.assertEquals(triggered.get(), 0); - - body.removeAllChildren(); - Assert.assertEquals(triggered.get(), 2); - - body.appendChild(parent); - body.removeAllChildren(); - - Assert.assertEquals(triggered.get(), 4); - - body.appendChild(parent); - registrationHandle.remove(); - - body.removeAllChildren(); - - Assert.assertEquals(triggered.get(), 5); - } - - @Test - public void attachListener_eventOrder_childFirst() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - parent.attachShadow().appendChild(child); - - AtomicBoolean parentAttached = new AtomicBoolean(); - AtomicBoolean childAttached = new AtomicBoolean(); - - child.addAttachListener(event -> { - childAttached.set(true); - Assert.assertFalse(parentAttached.get()); - }); - parent.addAttachListener(event -> { - parentAttached.set(true); - Assert.assertTrue(childAttached.get()); - }); - - body.appendChild(parent); - - Assert.assertTrue(parentAttached.get()); - Assert.assertTrue(childAttached.get()); - } - - @Test - public void detachListener_eventOrder_childFirst() { - Element body = new UI().getElement(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - parent.attachShadow().appendChild(child); - body.appendChild(parent); - - AtomicBoolean parentDetached = new AtomicBoolean(); - AtomicBoolean childDetached = new AtomicBoolean(); - - child.addDetachListener(event -> { - childDetached.set(true); - Assert.assertFalse(parentDetached.get()); - }); - parent.addDetachListener(event -> { - parentDetached.set(true); - Assert.assertTrue(childDetached.get()); - }); - - body.removeAllChildren(); - - Assert.assertTrue(parentDetached.get()); - Assert.assertTrue(childDetached.get()); - } - - @Test - public void attachDetach_elementMoved_bothEventsTriggered() { - ShadowRoot bodyShadow = new UI().getElement().attachShadow(); - Element parent = ElementFactory.createDiv(); - Element child = ElementFactory.createDiv(); - - parent.appendChild(child); - bodyShadow.appendChild(parent); - - AtomicBoolean attached = new AtomicBoolean(); - AtomicBoolean detached = new AtomicBoolean(); - - child.addAttachListener(event -> { - attached.set(true); - Assert.assertTrue(detached.get()); - }); - child.addDetachListener(event -> { - detached.set(true); - Assert.assertFalse(attached.get()); - }); - - bodyShadow.appendChild(child); - - Assert.assertTrue(attached.get()); - Assert.assertTrue(detached.get()); - } - - @Test - public void attachEvent_stateTreeCanFound() { - ShadowRoot bodyShadow = new UI().getElement().attachShadow(); - Element child = ElementFactory.createDiv(); - - AtomicInteger attached = new AtomicInteger(); - - child.addAttachListener(event -> { - Assert.assertNotNull(event.getSource().getNode().getOwner()); - Assert.assertNotEquals(NullOwner.get(), - event.getSource().getNode().getOwner()); - }); - child.addAttachListener(event -> attached.incrementAndGet()); - - bodyShadow.appendChild(child); - Assert.assertEquals(1, attached.get()); - } - - @Test - public void detachEvent_stateTreeCanFound() { - ShadowRoot bodyShadow = new UI().getElement().attachShadow(); - Element child = ElementFactory.createDiv(); - bodyShadow.appendChild(child); - - AtomicInteger detached = new AtomicInteger(); - - child.addDetachListener(event -> { - Assert.assertNotNull(event.getSource().getNode().getOwner()); - Assert.assertNotEquals(NullOwner.get(), - event.getSource().getNode().getOwner()); - }); - child.addDetachListener(event -> detached.incrementAndGet()); - - bodyShadow.removeAllChildren(); - - Assert.assertEquals(1, detached.get()); - } - - @Test - public void getParentNode_parentNodeIsNull() { - ShadowRoot root = createParentNode(); - Assert.assertNull(root.getParentNode()); - } - - @Test - public void visitOnlyNode_hasDescendants_nodeVisitedAndNoDescendantsVisited() { - TestNodeVisitor visitor = new TestNodeVisitor(false); - - Map, ElementType> map = new HashMap<>(); - - ShadowRoot subject = createHierarchy(map); - - ShadowRootStateProvider.get().visit(subject.getNode(), visitor); - - Assert.assertEquals(1, visitor.getVisited().size()); - Assert.assertEquals(subject, - visitor.getVisited().keySet().iterator().next()); - Assert.assertEquals(null, - visitor.getVisited().values().iterator().next()); - } - - @Test - public void visitOnlyNode_hasDescendants_nodeAndDescendatnsAreVisited() { - TestNodeVisitor visitor = new TestNodeVisitor(true); - - Map, ElementType> map = new HashMap<>(); - - ShadowRoot subject = createHierarchy(map); - - ShadowRootStateProvider.get().visit(subject.getNode(), visitor); - - Assert.assertTrue(map.size() > 1); - - Assert.assertEquals( - "The collected descendants doesn't match expected descendatns", - map, visitor.getVisited()); - } - - private ShadowRoot createHierarchy(Map, ElementType> map) { - Element root = ElementFactory.createDiv(); - - ShadowRoot shadowRoot = root.attachShadow(); - - map.put(shadowRoot, null); - - Element shadowChild = ElementFactory.createAnchor(); - Element shadowVirtualChild = ElementFactory.createBr(); - shadowRoot.appendChild(shadowChild); - shadowRoot.appendVirtualChild(shadowVirtualChild); - - map.put(shadowChild, ElementType.REGULAR); - map.put(shadowVirtualChild, ElementType.VIRTUAL); - - Element virtualGrandChild = ElementFactory.createDiv(); - - shadowChild.getStateProvider().appendVirtualChild(shadowChild.getNode(), - virtualGrandChild, NodeProperties.INJECT_BY_ID, "id"); - - map.put(virtualGrandChild, ElementType.VIRTUAL_ATTACHED); - - return shadowRoot; - } - - @Override - protected ShadowRoot createParentNode() { - return ElementFactory.createDiv().attachShadow(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/StyleUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/StyleUtilTest.java deleted file mode 100644 index 0182d0b14fa..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/StyleUtilTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -public class StyleUtilTest { - private static final Map stylepPropertyToAttribute = new java.util.HashMap<>(); - static { - stylepPropertyToAttribute.put("width", "width"); - stylepPropertyToAttribute.put("borderRadius", "border-radius"); - stylepPropertyToAttribute.put("webkitBorderRadius", - "-webkit-border-radius"); - stylepPropertyToAttribute.put("mozBorderRadius", "-moz-border-radius"); - stylepPropertyToAttribute.put("msUserSelect", "-ms-user-select"); - stylepPropertyToAttribute.put("oUserSelect", "-o-user-select"); - } - - @Test - public void attributeToProperty() { - stylepPropertyToAttribute.entrySet().forEach((entry) -> { - String property = entry.getKey(); - String attribute = entry.getValue(); - Assert.assertEquals(property, - StyleUtil.styleAttributeToProperty(attribute)); - - }); - } - - @Test - public void propertyToAttribute() { - stylepPropertyToAttribute.entrySet().forEach((entry) -> { - String property = entry.getKey(); - String attribute = entry.getValue(); - Assert.assertEquals(attribute, - StyleUtil.stylePropertyToAttribute(property)); - - }); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/TestNodeVisitor.java b/flow-server/src/test/java/com/vaadin/flow/dom/TestNodeVisitor.java deleted file mode 100644 index f7d01d90d5d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/TestNodeVisitor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom; - -import java.util.HashMap; -import java.util.Map; - -public class TestNodeVisitor implements NodeVisitor { - - private final Map, ElementType> visited = new HashMap<>(); - private final boolean visitDescendants; - - public TestNodeVisitor(boolean visitDescendants) { - this.visitDescendants = visitDescendants; - } - - public Map, ElementType> getVisited() { - return visited; - } - - @Override - public boolean visit(ElementType type, Element element) { - visited.put(element, type); - return visitDescendants; - } - - @Override - public boolean visit(ShadowRoot root) { - visited.put(root, null); - return visitDescendants; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/impl/ElementStateProviderDeserializationTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/impl/ElementStateProviderDeserializationTest.java deleted file mode 100644 index 547e71e5684..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/impl/ElementStateProviderDeserializationTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom.impl; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HasComponents; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.dom.Element; - -/** - * @author Muammer Yucel - * @since 2.2. - * @see https://github.com/vaadin/flow/issues/7190 - */ -public class ElementStateProviderDeserializationTest { - - @Test - public void shouldRemoveChildComponentFromDeserializedParent() - throws Exception { - - TestParentComponent parent = (TestParentComponent) deserialize( - serialize(new TestParentComponent(new TestChildComponent()))); - - Component child = parent.getChildren().findFirst() - .orElseThrow(IllegalStateException::new); - - parent.remove(child); - - Assert.assertEquals("Child component should have been removed.", 0, - parent.getChildren().count()); - } - - private byte[] serialize(Object object) throws IOException { - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos)) { - oos.writeObject(object); - oos.flush(); - return baos.toByteArray(); - } - } - - private Object deserialize(byte[] bytes) - throws IOException, ClassNotFoundException { - try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - ObjectInputStream ois = new ObjectInputStream(bais)) { - return ois.readObject(); - } - } - - private static class TestParentComponent extends Component - implements HasComponents { - - private static final long serialVersionUID = 1L; - - public TestParentComponent(Component... components) { - super(new Element(Tag.DIV)); - add(components); - } - } - - private static class TestChildComponent extends Component { - - private static final long serialVersionUID = 1L; - - public TestChildComponent() { - super(new Element(Tag.DIV)); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/dom/impl/ThemeListImplTest.java b/flow-server/src/test/java/com/vaadin/flow/dom/impl/ThemeListImplTest.java deleted file mode 100644 index 48a7890ef29..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/dom/impl/ThemeListImplTest.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.dom.impl; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Test; - -import com.vaadin.flow.dom.Element; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Vaadin Ltd - * @since 1.0. - */ -public class ThemeListImplTest { - - private static class MockElement extends Element { - private final Map attributesMap = new HashMap<>(); - - private MockElement(String... themeNames) { - super("mock-element"); - if (themeNames.length > 0) { - attributesMap.put(ThemeListImpl.THEME_ATTRIBUTE_NAME, - Stream.of(themeNames).collect(Collectors.joining(" "))); - } - } - - @Override - public Element setAttribute(String attribute, String value) { - attributesMap.put(attribute, value); - return this; - } - - @Override - public String getAttribute(String attribute) { - return attributesMap.get(attribute); - } - - @Override - public Element removeAttribute(String attribute) { - attributesMap.remove(attribute); - return this; - } - } - - @Test - public void themeListCreatedWithNoThemes() { - ThemeListImpl emptyList = new ThemeListImpl(new MockElement()); - - assertTrue( - "ThemeList created from the element without themes should be empty", - emptyList.isEmpty()); - assertEquals( - "ThemeList created from the element without themes should be empty", - emptyList.size(), 0); - } - - @Test - public void themeListCreatedWithOneThemes() { - String themeName = "theme1"; - - ThemeListImpl elementWithOneTheme = new ThemeListImpl( - new MockElement(themeName)); - - assertEquals( - "ThemeList created from the element with one theme should contain single element", - elementWithOneTheme.size(), 1); - assertTrue( - "ThemeList created from the element with one theme should contain this theme as its single element", - elementWithOneTheme.contains(themeName)); - } - - @Test - public void themeListCreatedWithMultipleThemes() { - String[] themeNames = { "theme1", "theme2" }; - ThemeListImpl elementWithMultipleThemes = new ThemeListImpl( - new MockElement(themeNames)); - - assertFalse( - "ThemeList created from the element with multiple distinct themes should not be empty", - elementWithMultipleThemes.isEmpty()); - assertEquals( - "ThemeList created from the element with multiple distinct themes should be of the same size as number of the themes", - elementWithMultipleThemes.size(), themeNames.length); - assertTrue( - "ThemeList created from the element with multiple distinct themes should contain them all and oly them", - elementWithMultipleThemes - .containsAll(Arrays.asList(themeNames))); - } - - @Test - public void themeListCreatedWithDuplicateThemes() { - String[] themeNames = { "theme1", "theme1", "theme1" }; - ThemeListImpl elementWithMultipleThemes = new ThemeListImpl( - new MockElement(themeNames)); - - assertEquals( - "ThemeList created from the element with multiple themes should be of the same size as number of unique themes", - elementWithMultipleThemes.size(), 1); - assertTrue( - "ThemeList created from the element with multiple themes should be contain all unique themes", - elementWithMultipleThemes.contains(themeNames[0])); - } - - @Test - public void clear() { - MockElement element = new MockElement("theme1", "theme2"); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.clear(); - - assertTrue("ThemeList should be empty after it's cleared", - themeList.isEmpty()); - assertNull( - "If corresponding ThemeList is cleared, no themes should be preset in the corresponding element", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME)); - } - - @Test - public void remove() { - String themeToRemove = "theme2"; - String themeToLeave = "theme1"; - MockElement element = new MockElement(themeToLeave, themeToRemove); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.remove(themeToRemove); - - assertEquals( - "Only one theme should be present in ThemeList after removal", - themeList.size(), 1); - assertTrue("ThemeList should contain theme that was not removed", - themeList.contains(themeToLeave)); - assertEquals( - "Corresponding element should contain only the theme that was not removed", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME), - themeToLeave); - } - - @Test - public void removeAll() { - String themeToRemove1 = "theme3"; - String themeToRemove2 = "theme2"; - String themeToLeave = "theme1"; - MockElement element = new MockElement(themeToLeave, themeToRemove1, - themeToRemove2); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.removeAll(Arrays.asList(themeToRemove1, themeToRemove2)); - - assertEquals( - "Only one theme should be present in ThemeList after removal", - themeList.size(), 1); - assertTrue("ThemeList should contain theme that was not removed", - themeList.contains(themeToLeave)); - assertEquals( - "Corresponding element should contain only the theme that was not removed", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME), - themeToLeave); - } - - @Test - public void removeAllThemes() { - String[] themeNames = { "theme1", "theme2" }; - MockElement element = new MockElement(themeNames); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.removeAll(Arrays.asList(themeNames)); - - assertTrue( - "ThemeList should be empty after all it's themes are removed", - themeList.isEmpty()); - assertNull( - "If corresponding ThemeList is cleared, no themes should be preset in the corresponding element", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME)); - } - - @Test - public void retainAll() { - List elementsToRetain = Arrays.asList("retained", - "notRetained"); - String[] themeNames = { elementsToRetain.get(0), "theme2", "theme3" }; - MockElement element = new MockElement(themeNames); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.retainAll(elementsToRetain); - - assertEquals("ThemeList should contain one retained theme", - themeList.size(), 1); - assertEquals( - "Corresponding element should contain the only element present in ThemeList", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME), - themeList.iterator().next()); - } - - @Test - public void add() { - String themeToAdd = "theme"; - MockElement element = new MockElement(); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.add(themeToAdd); - - assertEquals("ThemeList should not be empty after adding a theme", - themeList.size(), 1); - assertTrue("ThemeList should contain theme added", - themeList.contains(themeToAdd)); - assertEquals("Corresponding element should contain the theme added", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME), - themeToAdd); - } - - @Test - public void addAll() { - List themesToAdd = Arrays.asList("theme1", "theme2", "theme3"); - MockElement element = new MockElement(); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.addAll(themesToAdd); - - assertFalse("ThemeList should not be empty after adding themes", - themeList.isEmpty()); - assertEquals( - "ThemeList size should be equal to number of distinct themes added if it was empty before", - themeList.size(), themesToAdd.size()); - assertTrue("ThemeList should contain all distinct themes added", - themeList.containsAll(themesToAdd)); - themesToAdd.forEach(themeName -> assertTrue( - "Each distinct theme added to ThemeList should be present in correspondent element's 'theme' attribute", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME) - .contains(themeName))); - } - - @Test - public void addDuplicates() { - List themesToAdd = Arrays.asList("theme1", "theme1", "theme1"); - MockElement element = new MockElement(); - ThemeListImpl themeList = new ThemeListImpl(element); - - themeList.addAll(themesToAdd); - - assertEquals( - "ThemeList should not be empty after themes have been added", - themeList.size(), 1); - assertTrue("ThemeList should contain all distinct themes added", - themeList.contains(themesToAdd.get(0))); - assertEquals( - "Corresponding element should have all distinct themes added", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME), - themesToAdd.get(0)); - } - - @Test - public void iteratorRemoval() { - String[] themeNames = { "theme1", "theme2", "theme3" }; - List originalThemes = Arrays.asList(themeNames); - MockElement element = new MockElement(themeNames); - ThemeListImpl themeList = new ThemeListImpl(element); - - Set removedElements = new HashSet<>(); - Iterator iterator = themeList.iterator(); - removedElements.add(iterator.next()); - iterator.remove(); - removedElements.add(iterator.next()); - iterator.remove(); - - assertEquals("ThemeList should have one element left after removal", - themeList.size(), 1); - String notRemovedTheme = themeList.iterator().next(); - assertTrue( - "Themes returned by ThemeList's iterator.next() should be present in the original list of themes", - originalThemes.containsAll(removedElements)); - assertTrue( - "Theme left in ThemeList after removal should be present in the original list of themes", - originalThemes.contains(notRemovedTheme)); - assertFalse( - "Removed themes should not contain theme left in the ThemeList", - removedElements.contains(notRemovedTheme)); - assertEquals( - "Theme left in ThemeList after removal should be the only theme preset in the corresponding element", - element.getAttribute(ThemeListImpl.THEME_ATTRIBUTE_NAME), - notRemovedTheme); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/CaseUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/CaseUtilTest.java deleted file mode 100644 index 5ecf65e2bda..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/CaseUtilTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -/** - * Tests for the {@link CaseUtil}. - */ -public class CaseUtilTest { - - @Test - public void upperCaseUnderscoreToHumanFriendly() { - assertNull(CaseUtil.upperCaseUnderscoreToHumanFriendly(null)); - assertEquals("", CaseUtil.upperCaseUnderscoreToHumanFriendly("")); - assertEquals("My Bean Container", CaseUtil - .upperCaseUnderscoreToHumanFriendly("MY_BEAN_CONTAINER")); - assertEquals("Awesome Url Factory", CaseUtil - .upperCaseUnderscoreToHumanFriendly("AWESOME_URL_FACTORY")); - assertEquals("Something", - CaseUtil.upperCaseUnderscoreToHumanFriendly("SOMETHING")); - } - - @Test - public void capitalize() { - assertNull(CaseUtil.capitalize(null)); - assertEquals("", CaseUtil.capitalize("")); - assertEquals("Great", CaseUtil.capitalize("great")); - assertEquals("WONDERFUL", CaseUtil.capitalize("WONDERFUL")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/ConstantPoolTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/ConstantPoolTest.java deleted file mode 100644 index 11df6629472..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/ConstantPoolTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import org.junit.Assert; -import org.junit.Test; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class ConstantPoolTest { - private ConstantPool constantPool = new ConstantPool(); - - @Test - public void newConstantPool_noNewItems() { - Assert.assertFalse(constantPool.hasNewConstants()); - Assert.assertEquals(0, constantPool.dumpConstants().keys().length); - } - - @Test - public void valueIsRegistered() { - ConstantPoolKey reference = new ConstantPoolKey(Json.createObject()); - - String constantId = constantPool.getConstantId(reference); - - Assert.assertTrue(constantPool.hasNewConstants()); - - JsonObject dump = constantPool.dumpConstants(); - - Assert.assertEquals(1, dump.keys().length); - Assert.assertEquals("{}", dump.get(constantId).toJson()); - } - - @Test - public void sameValue_sameId() { - ConstantPoolKey reference = new ConstantPoolKey(Json.createObject()); - - String constantId = constantPool.getConstantId(reference); - constantPool.dumpConstants(); - - String otherId = constantPool - .getConstantId(new ConstantPoolKey(Json.createObject())); - - Assert.assertEquals(constantId, otherId); - Assert.assertFalse(constantPool.hasNewConstants()); - } - - @Test - public void differentValue_differentId() { - ConstantPoolKey reference = new ConstantPoolKey(Json.createObject()); - - String constantId = constantPool.getConstantId(reference); - constantPool.dumpConstants(); - - String otherId = constantPool - .getConstantId(new ConstantPoolKey(Json.createArray())); - - Assert.assertNotEquals(constantId, otherId); - Assert.assertTrue(constantPool.hasNewConstants()); - } - - @Test - public void constantPoolKey_exportedDirectly_idCreated() { - final ConstantPoolKey constantPoolKey = new ConstantPoolKey( - Json.createObject()); - final JsonObject message = Json.createObject(); - constantPoolKey.export(message); - Assert.assertTrue(message.hasKey(constantPoolKey.getId())); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/CurrentInstanceTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/CurrentInstanceTest.java deleted file mode 100644 index e211d5facca..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/CurrentInstanceTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import static org.junit.Assert.assertNull; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.tests.util.TestUtil; - -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe -public class CurrentInstanceTest { - - @Before - public void clearExistingThreadLocals() { - // Ensure no previous test left some thread locals hanging - CurrentInstance.clearAll(); - } - - @Test - public void testInitiallyCleared() throws Exception { - assertCleared(); - } - - @Test - public void testClearedAfterRemove() throws Exception { - CurrentInstance.set(CurrentInstanceTest.class, this); - Assert.assertEquals(this, - CurrentInstance.get(CurrentInstanceTest.class)); - CurrentInstance.set(CurrentInstanceTest.class, null); - - assertCleared(); - } - - @Test - public void testClearedWithClearAll() throws Exception { - CurrentInstance.set(CurrentInstanceTest.class, this); - Assert.assertEquals(this, - CurrentInstance.get(CurrentInstanceTest.class)); - CurrentInstance.clearAll(); - - assertCleared(); - } - - private void assertCleared() throws SecurityException, NoSuchFieldException, - IllegalAccessException { - Assert.assertNull(getInternalCurrentInstanceVariable().get()); - } - - @SuppressWarnings("unchecked") - private ThreadLocal, CurrentInstance>> getInternalCurrentInstanceVariable() - throws SecurityException, NoSuchFieldException, - IllegalAccessException { - Field f = CurrentInstance.class.getDeclaredField("instances"); - f.setAccessible(true); - return (ThreadLocal, CurrentInstance>>) f.get(null); - } - - public void testInheritedClearedAfterRemove() { - - } - - private static class UIStoredInCurrentInstance extends UI { - @Override - protected void init(VaadinRequest request) { - } - } - - private static class SessionStoredInCurrentInstance extends VaadinSession { - public SessionStoredInCurrentInstance(VaadinService service) { - super(service); - } - } - - @Test - public void testRestoringNullUIWorks() throws Exception { - // First make sure current instance is empty - CurrentInstance.clearAll(); - - // Then store a new UI in there - Map, CurrentInstance> old = CurrentInstance - .setCurrent(new UIStoredInCurrentInstance()); - - // Restore the old values and assert that the UI is null again - CurrentInstance.restoreInstances(old); - assertNull(CurrentInstance.get(UI.class)); - } - - @Test - public void testRestoringNullSessionWorks() throws Exception { - // First make sure current instance is empty - CurrentInstance.clearAll(); - - // Then store a new session in there - Map, CurrentInstance> old = CurrentInstance - .setCurrent(new SessionStoredInCurrentInstance( - new MockVaadinServletService())); - - // Restore the old values and assert that the session is null again - CurrentInstance.restoreInstances(old); - assertNull(CurrentInstance.get(VaadinSession.class)); - assertNull(CurrentInstance.get(VaadinService.class)); - } - - @Test - public void testRestoreWithGarbageCollectedValue() - throws InterruptedException { - VaadinSession session1 = new VaadinSession( - new MockVaadinServletService()) { - @Override - public String toString() { - return "First session"; - } - }; - VaadinSession session2 = new VaadinSession( - new MockVaadinServletService()) { - @Override - public String toString() { - return "Second session"; - } - }; - - VaadinSession.setCurrent(session1); - Map, CurrentInstance> previous = CurrentInstance - .setCurrent(session2); - - // Use weak ref to verify object is collected - WeakReference ref = new WeakReference<>(session1); - - session1 = null; - Assert.assertTrue(TestUtil.isGarbageCollected(ref)); - - CurrentInstance.restoreInstances(previous); - - Assert.assertNull(VaadinSession.getCurrent()); - } - - @Test - public void nonInheritableThreadLocals() - throws InterruptedException, ExecutionException { - CurrentInstance.clearAll(); - CurrentInstance.set(CurrentInstanceTest.class, this); - - Assert.assertNotNull(CurrentInstance.get(CurrentInstanceTest.class)); - - Callable runnable = () -> { - Assert.assertNull(CurrentInstance.get(CurrentInstanceTest.class)); - return null; - }; - ExecutorService service = Executors.newSingleThreadExecutor(); - Future future = service.submit(runnable); - future.get(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/CustomElementNameValidatorTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/CustomElementNameValidatorTest.java deleted file mode 100644 index 1449ded2704..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/CustomElementNameValidatorTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -/** - * Test CustomElementNameValidator that it validates correctly. - */ -public class CustomElementNameValidatorTest { - - @Test - public void testInvalidElementNames() { - Stream.of("", "foo", "annotation-xml", "0-foo", "-foo", "foo-$", - "foo-/", "FOO-BAR", "foo/", "øl-unicorn", "foo-💩", - "5th-element") - .forEach(name -> Assert.assertFalse(String.format( - "Name %s is valid even though it should not be", name), - CustomElementNameValidator.isCustomElementName(name))); - } - - @Test - public void testValidNamesWithoutErrorOrWarning() { - Stream.of("foo-bar", "custom-element", "date-field", "dos-box", - "home-4-good") - .forEach(name -> Assert.assertTrue(String.format( - "Name %s is not valid even though it should be", name), - CustomElementNameValidator.isCustomElementName(name))); - } - - @Test - public void testValidButWithWarning() { - Stream.of("polymer-", "x-", "ng-", "unicorn-", "unicorn-ø", "uni--corn", - "uni-----corn", "uni-co___rn", "uni-co.rn", "uni-corné", - "xml-unicorn", "não-tém", "foo-bår") - .forEach(name -> Assert.assertTrue(String.format( - "Name %s is not valid even though it should be", name), - CustomElementNameValidator.isCustomElementName(name))); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/HasCurrentService.java b/flow-server/src/test/java/com/vaadin/flow/internal/HasCurrentService.java deleted file mode 100644 index 4b2b68f79df..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/HasCurrentService.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import org.junit.After; -import org.junit.Before; - -import com.vaadin.flow.server.VaadinService; - -import static org.junit.Assert.assertNull; - -/** - * Helper for test classes that need to have {@code VaadinService.getCurrent()} - * populated. - * - * @author Vaadin Ltd - * @since 1.0 - */ -public abstract class HasCurrentService { - // Store the service to prevent it from being garbage collected while the - // test is running - private VaadinService service; - - @Before - public void setUpCurrentService() { - clearCurrentService(); - assertNull(VaadinService.getCurrent()); - - service = createService(); - VaadinService.setCurrent(service); - } - - protected abstract VaadinService createService(); - - @After - public void clearCurrentService() { - VaadinService.setCurrent(null); - service = null; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/JsonCodecTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/JsonCodecTest.java deleted file mode 100644 index d20e4f8466d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/JsonCodecTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; - -import elemental.json.Json; -import elemental.json.JsonBoolean; -import elemental.json.JsonNull; -import elemental.json.JsonNumber; -import elemental.json.JsonObject; -import elemental.json.JsonString; -import elemental.json.JsonValue; - -public class JsonCodecTest { - private static List withTypeInfoUnsupportedValues = Arrays.asList( - new Object(), new StateNode(), new Date(), new String[0], - new ArrayList<>(), new HashSet<>(), new HashMap<>()); - - @Test - public void encodeWithoutTypeInfo_supportedTypes() { - assertJsonEquals(Json.create(true), - JsonCodec.encodeWithoutTypeInfo(Boolean.TRUE)); - assertJsonEquals(Json.create("string"), - JsonCodec.encodeWithoutTypeInfo("string")); - assertJsonEquals(Json.create(3.14), - JsonCodec.encodeWithoutTypeInfo(Double.valueOf(3.14))); - assertJsonEquals(Json.create(42), - JsonCodec.encodeWithoutTypeInfo(Integer.valueOf(42))); - assertJsonEquals(Json.createNull(), - JsonCodec.encodeWithoutTypeInfo(null)); - JsonObject json = Json.createObject(); - json.put("foo", "bar"); - assertJsonEquals(json, JsonCodec.encodeWithoutTypeInfo(json)); - - assertJsonEquals(Json.createNull(), Json.createNull()); - assertJsonEquals(Json.create(false), Json.create(false)); - assertJsonEquals(Json.create(234), Json.create(234)); - assertJsonEquals(Json.create("string"), Json.create("string")); - assertJsonEquals(json, json); - assertJsonEquals(Json.createArray(), Json.createArray()); - } - - @Test - public void encodeWithoutTypeInfo_unsupportedTypes() { - List unsupported = new ArrayList<>( - withTypeInfoUnsupportedValues); - unsupported.add(ElementFactory.createDiv()); - - for (Object value : unsupported) { - try { - JsonCodec.encodeWithoutTypeInfo(value); - - Assert.fail("Should throw for " + value.getClass()); - } catch (AssertionError expected) { - } - } - } - - @Test - public void encodeWithTypeInfo_basicTypes() { - assertJsonEquals(Json.create(true), - JsonCodec.encodeWithTypeInfo(Boolean.TRUE)); - assertJsonEquals(Json.createNull(), JsonCodec.encodeWithTypeInfo(null)); - - assertJsonEquals(Json.create(234), - JsonCodec.encodeWithTypeInfo(Json.create(234))); - assertJsonEquals(Json.create("string"), - JsonCodec.encodeWithTypeInfo(Json.create("string"))); - assertJsonEquals(Json.createObject(), - JsonCodec.encodeWithTypeInfo(Json.createObject())); - - // Array is escaped - assertJsonEquals( - JsonUtils.createArray(Json.create(JsonCodec.ARRAY_TYPE), - Json.createArray()), - JsonCodec.encodeWithTypeInfo(Json.createArray())); - } - - @Test - public void encodeWithTypeInfo_attachedElement() { - Element element = ElementFactory.createDiv(); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - tree.getRootNode().getFeature(ElementChildrenList.class).add(0, - element.getNode()); - - JsonValue json = JsonCodec.encodeWithTypeInfo(element); - - assertJsonEquals(JsonUtils.createArray(Json.create(JsonCodec.NODE_TYPE), - Json.create(element.getNode().getId())), json); - } - - @Test - public void encodeWithTypeInfo_detachedElement() { - Element element = ElementFactory.createDiv(); - - JsonValue json = JsonCodec.encodeWithTypeInfo(element); - - assertJsonEquals(Json.createNull(), json); - } - - @Test - public void encodeWithTypeInfo_unsupportedTypes() { - for (Object value : withTypeInfoUnsupportedValues) { - try { - JsonCodec.encodeWithTypeInfo(value); - - Assert.fail("Should throw for " + value.getClass()); - } catch (AssertionError expected) { - } - } - } - - private static void assertJsonEquals(JsonValue expected, JsonValue actual) { - Assert.assertTrue( - actual.toJson() + " does not equal " + expected.toJson(), - JsonUtils.jsonEquals(expected, actual)); - } - - @Test - public void decodeAs_booleanJson() { - JsonBoolean json = Json.create(true); - Assert.assertTrue(JsonCodec.decodeAs(json, Boolean.class)); - Assert.assertEquals("true", JsonCodec.decodeAs(json, String.class)); - Assert.assertEquals(Integer.valueOf(1), - JsonCodec.decodeAs(json, Integer.class)); - Assert.assertEquals(Double.valueOf(1.0), - JsonCodec.decodeAs(json, Double.class)); - Assert.assertEquals(json, JsonCodec.decodeAs(json, JsonValue.class)); - } - - @Test - public void decodeAs_stringJson() { - JsonString json = Json.create("Test123 String\n !%"); - Assert.assertTrue(JsonCodec.decodeAs(json, Boolean.class)); - Assert.assertEquals("Test123 String\n !%", - JsonCodec.decodeAs(json, String.class)); - Assert.assertEquals(Integer.valueOf(0), - JsonCodec.decodeAs(json, Integer.class)); - Assert.assertTrue(JsonCodec.decodeAs(json, Double.class).isNaN()); - Assert.assertEquals(json, JsonCodec.decodeAs(json, JsonValue.class)); - } - - @Test - public void decodeAs_numberJson() { - JsonNumber json = Json.create(15.7); - Assert.assertTrue(JsonCodec.decodeAs(json, Boolean.class)); - Assert.assertEquals("15.7", JsonCodec.decodeAs(json, String.class)); - Assert.assertEquals(Integer.valueOf(15), - JsonCodec.decodeAs(json, Integer.class)); - Assert.assertEquals(Double.valueOf(15.7), - JsonCodec.decodeAs(json, Double.class)); - Assert.assertEquals(json, JsonCodec.decodeAs(json, JsonValue.class)); - } - - @Test - public void decodeAs_nullJson() { - JsonNull json = Json.createNull(); - Assert.assertNull(JsonCodec.decodeAs(json, Boolean.class)); - Assert.assertNull(JsonCodec.decodeAs(json, String.class)); - Assert.assertNull(JsonCodec.decodeAs(json, Integer.class)); - Assert.assertNull(JsonCodec.decodeAs(json, Double.class)); - Assert.assertNull(JsonCodec.decodeAs(json, JsonValue.class)); - } - - @Test - public void decodeAs_jsonValue() { - JsonObject json = Json.createObject(); - json.put("foo", "bar"); - Assert.assertEquals("[object Object]", - JsonCodec.decodeAs(json, String.class)); - Assert.assertEquals(json, JsonCodec.decodeAs(json, JsonValue.class)); - // boolean - Assert.assertTrue(JsonCodec.decodeAs(json, Boolean.class)); - Assert.assertNull(JsonCodec.decodeAs(Json.createNull(), Boolean.class)); - Assert.assertTrue(JsonCodec.decodeAs(json, boolean.class)); - Assert.assertFalse( - JsonCodec.decodeAs(Json.createNull(), boolean.class)); - // integer - Assert.assertEquals(Integer.valueOf(0), - JsonCodec.decodeAs(json, Integer.class)); - Assert.assertNull(JsonCodec.decodeAs(Json.createNull(), Integer.class)); - Assert.assertEquals(Integer.valueOf(0), - JsonCodec.decodeAs(json, int.class)); - Assert.assertEquals(Integer.valueOf(0), - JsonCodec.decodeAs(Json.createNull(), int.class)); - // double - Assert.assertNull(JsonCodec.decodeAs(Json.createNull(), Double.class)); - Assert.assertTrue(JsonCodec.decodeAs(json, Double.class).isNaN()); - Assert.assertTrue(JsonCodec.decodeAs(json, double.class).isNaN()); - Assert.assertEquals(0.0d, - JsonCodec.decodeAs(Json.createNull(), double.class), 0.0001d); - } - - @Test(expected = ClassCastException.class) - public void decodeAs_jsonValueWrongType_classCastException() { - JsonObject json = Json.createObject(); - json.put("foo", "bar"); - JsonCodec.decodeAs(json, JsonNumber.class); - } - - @Test(expected = IllegalArgumentException.class) - public void decodeAs_unsupportedType() { - Assert.assertNull(JsonCodec.decodeAs(Json.create("foo"), float.class)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/JsonSerializerTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/JsonSerializerTest.java deleted file mode 100644 index 902b132f05c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/JsonSerializerTest.java +++ /dev/null @@ -1,749 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; - -import elemental.json.JsonArray; -import elemental.json.JsonBoolean; -import elemental.json.JsonNull; -import elemental.json.JsonNumber; -import elemental.json.JsonObject; -import elemental.json.JsonString; -import elemental.json.JsonValue; - -/** - * Tests for the {@link JsonSerializer}. - */ -public class JsonSerializerTest { - - private static final double PRECISION = 0.000001; - - public static enum SomeEnum { - SOME_VALUE_1, SOME_VALUE_2; - } - - public static class ObjectWithSimpleTypes { - - private String stringProperty; - private int intProperty; - private Integer integerProperty; - private long longProperty; - private Long longObjectProperty; - private short shortProperty; - private Short shortObjectProperty; - private double doubleProperty; - private Double doubleObjectProperty; - private byte byteProperty; - private Byte byteObjectProperty; - private boolean booleanProperty; - private Boolean booleanObjectProperty; - private char charProperty; - private Character characterProperty; - private SomeEnum enumProperty; - - public String getStringProperty() { - return stringProperty; - } - - public void setStringProperty(String stringProperty) { - this.stringProperty = stringProperty; - } - - public int getIntProperty() { - return intProperty; - } - - public void setIntProperty(int intProperty) { - this.intProperty = intProperty; - } - - public Integer getIntegerProperty() { - return integerProperty; - } - - public void setIntegerProperty(Integer integerProperty) { - this.integerProperty = integerProperty; - } - - public long getLongProperty() { - return longProperty; - } - - public void setLongProperty(long longProperty) { - this.longProperty = longProperty; - } - - public Long getLongObjectProperty() { - return longObjectProperty; - } - - public void setLongObjectProperty(Long longObjectProperty) { - this.longObjectProperty = longObjectProperty; - } - - public short getShortProperty() { - return shortProperty; - } - - public void setShortProperty(short shortProperty) { - this.shortProperty = shortProperty; - } - - public Short getShortObjectProperty() { - return shortObjectProperty; - } - - public void setShortObjectProperty(Short shortObjectProperty) { - this.shortObjectProperty = shortObjectProperty; - } - - public Double getDoubleObjectProperty() { - return doubleObjectProperty; - } - - public void setDoubleObjectProperty(Double doubleObjectProperty) { - this.doubleObjectProperty = doubleObjectProperty; - } - - public double getDoubleProperty() { - return doubleProperty; - } - - public void setDoubleProperty(double doubleProperty) { - this.doubleProperty = doubleProperty; - } - - public byte getByteProperty() { - return byteProperty; - } - - public void setByteProperty(byte byteProperty) { - this.byteProperty = byteProperty; - } - - public Byte getByteObjectProperty() { - return byteObjectProperty; - } - - public void setByteObjectProperty(Byte byteObjectProperty) { - this.byteObjectProperty = byteObjectProperty; - } - - public boolean isBooleanProperty() { - return booleanProperty; - } - - public void setBooleanProperty(boolean booleanProperty) { - this.booleanProperty = booleanProperty; - } - - public Boolean getBooleanObjectProperty() { - return booleanObjectProperty; - } - - public void setBooleanObjectProperty(Boolean booleanObjectProperty) { - this.booleanObjectProperty = booleanObjectProperty; - } - - public char getCharProperty() { - return charProperty; - } - - public void setCharProperty(char charProperty) { - this.charProperty = charProperty; - } - - public Character getCharacterProperty() { - return characterProperty; - } - - public void setCharacterProperty(Character characterProperty) { - this.characterProperty = characterProperty; - } - - public SomeEnum getEnumProperty() { - return enumProperty; - } - - public void setEnumProperty(SomeEnum enumProperty) { - this.enumProperty = enumProperty; - } - } - - public static class ObjectWithOtherObjects { - - private ObjectWithSimpleTypes object1; - private ObjectWithSimpleTypes object2; - - public ObjectWithSimpleTypes getObject1() { - return object1; - } - - public void setObject1(ObjectWithSimpleTypes object1) { - this.object1 = object1; - } - - public ObjectWithSimpleTypes getObject2() { - return object2; - } - - public void setObject2(ObjectWithSimpleTypes object2) { - this.object2 = object2; - } - } - - public static class RecursiveObject { - - private RecursiveObject recursive; - private int index; - - public RecursiveObject getRecursive() { - return recursive; - } - - public void setRecursive(RecursiveObject recursive) { - this.recursive = recursive; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - } - - public static class ObjectWithBasicCollections { - private List listOfStrings; - private Set setOfIntegers; - private LinkedList linkedListOfBooleans; - private List arrayListOfDoubles; - - public List getListOfStrings() { - return listOfStrings; - } - - public void setListOfStrings(List listOfStrings) { - this.listOfStrings = listOfStrings; - } - - public Set getSetOfIntegers() { - return setOfIntegers; - } - - public void setSetOfIntegers(Set setOfIntegers) { - this.setOfIntegers = setOfIntegers; - } - - public LinkedList getLinkedListOfBooleans() { - return linkedListOfBooleans; - } - - public void setLinkedListOfBooleans( - LinkedList linkedListOfBooleans) { - this.linkedListOfBooleans = linkedListOfBooleans; - } - - public List getArrayListOfDoubles() { - return arrayListOfDoubles; - } - - public void setArrayListOfDoubles(List arrayListOfDoubles) { - this.arrayListOfDoubles = arrayListOfDoubles; - } - } - - @Test - public void serializeBasicTypes_returnJsonBasicTypes() { - JsonValue json = JsonSerializer.toJson("someString"); - Assert.assertTrue("The JsonValue should be instanceof JsonString", - json instanceof JsonString); - Assert.assertEquals("someString", json.asString()); - - json = JsonSerializer.toJson(0); - Assert.assertTrue("The JsonValue should be instanceof JsonNumber", - json instanceof JsonNumber); - Assert.assertEquals(0.0, json.asNumber(), PRECISION); - - json = JsonSerializer.toJson(0.0); - Assert.assertTrue("The JsonValue should be instanceof JsonNumber", - json instanceof JsonNumber); - Assert.assertEquals(0.0, json.asNumber(), PRECISION); - - json = JsonSerializer.toJson(0l); - Assert.assertTrue("The JsonValue should be instanceof JsonNumber", - json instanceof JsonNumber); - Assert.assertEquals(0.0, json.asNumber(), PRECISION); - - json = JsonSerializer.toJson((byte) 0); - Assert.assertTrue("The JsonValue should be instanceof JsonNumber", - json instanceof JsonNumber); - Assert.assertEquals(0.0, json.asNumber(), PRECISION); - - json = JsonSerializer.toJson((short) 0); - Assert.assertTrue("The JsonValue should be instanceof JsonNumber", - json instanceof JsonNumber); - Assert.assertEquals(0.0, json.asNumber(), PRECISION); - - json = JsonSerializer.toJson(true); - Assert.assertTrue("The JsonValue should be instanceof JsonBoolean", - json instanceof JsonBoolean); - Assert.assertTrue(json.asBoolean()); - - json = JsonSerializer.toJson(false); - Assert.assertTrue("The JsonValue should be instanceof JsonBoolean", - json instanceof JsonBoolean); - Assert.assertFalse(json.asBoolean()); - - json = JsonSerializer.toJson(SomeEnum.SOME_VALUE_1); - Assert.assertTrue("The JsonValue should be instanceof JsonString", - json instanceof JsonString); - Assert.assertEquals(SomeEnum.SOME_VALUE_1.name(), json.asString()); - } - - @Test - public void serializeNull_returnNull() { - JsonValue json = JsonSerializer.toJson((Object) null); - Assert.assertTrue("The JsonValue should be instanceof JsonNull", - json instanceof JsonNull); - } - - @Test - public void serializeEmptyObjectWithBasicTypes_returnJsonObjectWithEmptyProperties() { - ObjectWithSimpleTypes bean = new ObjectWithSimpleTypes(); - JsonValue json = JsonSerializer.toJson(bean); - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject object = (JsonObject) json; - assertObjectHasNullValueForKey(object, "stringProperty"); - assertObjectHas0ValueForKey(object, "intProperty"); - assertObjectHasNullValueForKey(object, "integerProperty"); - assertObjectHas0ValueForKey(object, "longProperty"); - assertObjectHasNullValueForKey(object, "longObjectProperty"); - assertObjectHas0ValueForKey(object, "shortProperty"); - assertObjectHasNullValueForKey(object, "shortObjectProperty"); - assertObjectHas0ValueForKey(object, "doubleProperty"); - assertObjectHasNullValueForKey(object, "doubleObjectProperty"); - assertObjectHas0ValueForKey(object, "byteProperty"); - assertObjectHasNullValueForKey(object, "byteObjectProperty"); - assertObjectHasFalseValueForKey(object, "booleanProperty"); - assertObjectHasNullValueForKey(object, "booleanObjectProperty"); - assertObjectHasNullValueForKey(object, "characterProperty"); - assertObjectHasNullValueForKey(object, "enumProperty"); - - // char is a different case, it is a string at the json - Assert.assertTrue(object.hasKey("charProperty")); - Assert.assertEquals((char) 0, - object.getString("charProperty").charAt(0)); - - bean = JsonSerializer.toObject(ObjectWithSimpleTypes.class, json); - Assert.assertNotNull(bean); - Assert.assertNull(bean.getStringProperty()); - Assert.assertEquals(0, bean.getIntProperty()); - Assert.assertNull(bean.getIntegerProperty()); - Assert.assertEquals(0, bean.getLongProperty()); - Assert.assertNull(bean.getLongObjectProperty()); - Assert.assertEquals(0, bean.getShortProperty()); - Assert.assertNull(bean.getShortObjectProperty()); - Assert.assertEquals(0, bean.getDoubleProperty(), 0.00001); - Assert.assertNull(bean.getDoubleObjectProperty()); - Assert.assertEquals(0, bean.getByteProperty()); - Assert.assertNull(bean.getByteObjectProperty()); - Assert.assertEquals(false, bean.isBooleanProperty()); - Assert.assertNull(bean.getBooleanObjectProperty()); - Assert.assertEquals(0, bean.getCharProperty()); - Assert.assertNull(bean.getCharacterProperty()); - Assert.assertNull(bean.getEnumProperty()); - } - - @Test - public void serializePopulatedObjectWithBasicTypes_returnJsonObjectWithDefinedProperties() { - ObjectWithSimpleTypes bean = new ObjectWithSimpleTypes(); - bean.setStringProperty("someProperty"); - bean.setIntProperty(1); - bean.setIntegerProperty(2); - bean.setLongProperty(3); - bean.setLongObjectProperty(4l); - bean.setShortProperty((short) 5); - bean.setShortObjectProperty((short) 6); - bean.setDoubleProperty(7); - bean.setDoubleObjectProperty(8.0); - bean.setByteProperty((byte) 9); - bean.setByteObjectProperty((byte) 10); - bean.setBooleanProperty(true); - bean.setBooleanObjectProperty(false); - bean.setCharProperty('c'); - bean.setCharacterProperty('C'); - bean.setEnumProperty(SomeEnum.SOME_VALUE_2); - - JsonValue json = JsonSerializer.toJson(bean); - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject object = (JsonObject) json; - Assert.assertEquals("someProperty", object.getString("stringProperty")); - Assert.assertEquals(1, object.getNumber("intProperty"), PRECISION); - Assert.assertEquals(2, object.getNumber("integerProperty"), PRECISION); - Assert.assertEquals(3, object.getNumber("longProperty"), PRECISION); - Assert.assertEquals(4, object.getNumber("longObjectProperty"), - PRECISION); - Assert.assertEquals(5, object.getNumber("shortProperty"), PRECISION); - Assert.assertEquals(6, object.getNumber("shortObjectProperty"), - PRECISION); - Assert.assertEquals(7, object.getNumber("doubleProperty"), PRECISION); - Assert.assertEquals(8, object.getNumber("doubleObjectProperty"), - PRECISION); - Assert.assertEquals(9, object.getNumber("byteProperty"), PRECISION); - Assert.assertEquals(10, object.getNumber("byteObjectProperty"), - PRECISION); - Assert.assertEquals(true, object.getBoolean("booleanProperty")); - Assert.assertEquals(false, object.getBoolean("booleanObjectProperty")); - Assert.assertEquals('c', object.getString("charProperty").charAt(0)); - Assert.assertEquals('C', - object.getString("characterProperty").charAt(0)); - Assert.assertEquals(SomeEnum.SOME_VALUE_2.name(), - object.getString("enumProperty")); - - bean = JsonSerializer.toObject(ObjectWithSimpleTypes.class, json); - Assert.assertNotNull(bean); - Assert.assertEquals("someProperty", bean.getStringProperty()); - Assert.assertEquals(1, bean.getIntProperty()); - Assert.assertEquals(Integer.valueOf(2), bean.getIntegerProperty()); - Assert.assertEquals(3, bean.getLongProperty()); - Assert.assertEquals(Long.valueOf(4), bean.getLongObjectProperty()); - Assert.assertEquals(5, bean.getShortProperty()); - Assert.assertEquals(Short.valueOf((short) 6), - bean.getShortObjectProperty()); - Assert.assertEquals(7, bean.getDoubleProperty(), 0.00001); - Assert.assertEquals(Double.valueOf(8), bean.getDoubleObjectProperty()); - Assert.assertEquals(9, bean.getByteProperty()); - Assert.assertEquals(Byte.valueOf((byte) 10), - bean.getByteObjectProperty()); - Assert.assertEquals(true, bean.isBooleanProperty()); - Assert.assertEquals(Boolean.FALSE, bean.getBooleanObjectProperty()); - Assert.assertEquals('c', bean.getCharProperty()); - Assert.assertEquals((Character) 'C', bean.getCharacterProperty()); - Assert.assertEquals(SomeEnum.SOME_VALUE_2, bean.getEnumProperty()); - } - - @Test - public void serializeEmptyObjectWithObjects_returnJsonObjectWithNullProperties() { - ObjectWithOtherObjects bean = new ObjectWithOtherObjects(); - - JsonValue json = JsonSerializer.toJson(bean); - - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject jsonObject = (JsonObject) json; - Assert.assertTrue(jsonObject.hasKey("object1")); - Assert.assertTrue(jsonObject.get("object1") instanceof JsonNull); - Assert.assertTrue(jsonObject.hasKey("object2")); - Assert.assertTrue(jsonObject.get("object2") instanceof JsonNull); - - bean = JsonSerializer.toObject(ObjectWithOtherObjects.class, json); - - Assert.assertNotNull("The deserialized object should not be null", - bean); - Assert.assertNull(bean.getObject1()); - Assert.assertNull(bean.getObject2()); - } - - @Test - public void serializeObjectWithObjects_returnJsonObjectWithPopulatedProperties() { - ObjectWithOtherObjects bean = new ObjectWithOtherObjects(); - ObjectWithSimpleTypes innerBean = new ObjectWithSimpleTypes(); - innerBean.setStringProperty("someProperty"); - innerBean.setIntProperty(1); - innerBean.setIntegerProperty(2); - innerBean.setLongProperty(3); - innerBean.setLongObjectProperty(4l); - innerBean.setShortProperty((short) 5); - innerBean.setShortObjectProperty((short) 6); - innerBean.setDoubleProperty(7); - innerBean.setDoubleObjectProperty(8.0); - innerBean.setByteProperty((byte) 9); - innerBean.setByteObjectProperty((byte) 10); - innerBean.setBooleanProperty(true); - innerBean.setBooleanObjectProperty(false); - innerBean.setCharProperty('c'); - innerBean.setCharacterProperty('C'); - innerBean.setEnumProperty(SomeEnum.SOME_VALUE_2); - bean.setObject1(innerBean); - - innerBean = new ObjectWithSimpleTypes(); - innerBean.setStringProperty("someOtherProperty"); - innerBean.setIntProperty(10); - innerBean.setIntegerProperty(20); - innerBean.setLongProperty(30); - innerBean.setLongObjectProperty(40l); - innerBean.setShortProperty((short) 50); - innerBean.setShortObjectProperty((short) 60); - innerBean.setDoubleProperty(70); - innerBean.setDoubleObjectProperty(80.0); - innerBean.setByteProperty((byte) 90); - innerBean.setByteObjectProperty((byte) 100); - innerBean.setBooleanProperty(true); - innerBean.setBooleanObjectProperty(false); - innerBean.setCharProperty('d'); - innerBean.setCharacterProperty('D'); - innerBean.setEnumProperty(SomeEnum.SOME_VALUE_1); - bean.setObject2(innerBean); - - JsonValue json = JsonSerializer.toJson(bean); - - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject object = ((JsonObject) json).getObject("object1"); - Assert.assertNotNull("The object1 should be not be null", object); - - Assert.assertEquals("someProperty", object.getString("stringProperty")); - Assert.assertEquals(1, object.getNumber("intProperty"), PRECISION); - Assert.assertEquals(2, object.getNumber("integerProperty"), PRECISION); - Assert.assertEquals(3, object.getNumber("longProperty"), PRECISION); - Assert.assertEquals(4, object.getNumber("longObjectProperty"), - PRECISION); - Assert.assertEquals(5, object.getNumber("shortProperty"), PRECISION); - Assert.assertEquals(6, object.getNumber("shortObjectProperty"), - PRECISION); - Assert.assertEquals(7, object.getNumber("doubleProperty"), PRECISION); - Assert.assertEquals(8, object.getNumber("doubleObjectProperty"), - PRECISION); - Assert.assertEquals(9, object.getNumber("byteProperty"), PRECISION); - Assert.assertEquals(10, object.getNumber("byteObjectProperty"), - PRECISION); - Assert.assertEquals(true, object.getBoolean("booleanProperty")); - Assert.assertEquals(false, object.getBoolean("booleanObjectProperty")); - Assert.assertEquals('c', object.getString("charProperty").charAt(0)); - Assert.assertEquals('C', - object.getString("characterProperty").charAt(0)); - Assert.assertEquals(SomeEnum.SOME_VALUE_2.name(), - object.getString("enumProperty")); - - object = ((JsonObject) json).getObject("object2"); - Assert.assertNotNull("The object2 should be not be null", object); - - Assert.assertEquals("someOtherProperty", - object.getString("stringProperty")); - Assert.assertEquals(10, object.getNumber("intProperty"), PRECISION); - Assert.assertEquals(20, object.getNumber("integerProperty"), PRECISION); - Assert.assertEquals(30, object.getNumber("longProperty"), PRECISION); - Assert.assertEquals(40, object.getNumber("longObjectProperty"), - PRECISION); - Assert.assertEquals(50, object.getNumber("shortProperty"), PRECISION); - Assert.assertEquals(60, object.getNumber("shortObjectProperty"), - PRECISION); - Assert.assertEquals(70, object.getNumber("doubleProperty"), PRECISION); - Assert.assertEquals(80, object.getNumber("doubleObjectProperty"), - PRECISION); - Assert.assertEquals(90, object.getNumber("byteProperty"), PRECISION); - Assert.assertEquals(100, object.getNumber("byteObjectProperty"), - PRECISION); - Assert.assertEquals(true, object.getBoolean("booleanProperty")); - Assert.assertEquals(false, object.getBoolean("booleanObjectProperty")); - Assert.assertEquals('d', object.getString("charProperty").charAt(0)); - Assert.assertEquals('D', - object.getString("characterProperty").charAt(0)); - Assert.assertEquals(SomeEnum.SOME_VALUE_1.name(), - object.getString("enumProperty")); - } - - @Test - public void serializeEmptyRecursiveObject_returnJsonObjectWithNullProperties() { - RecursiveObject bean = new RecursiveObject(); - - JsonValue json = JsonSerializer.toJson(bean); - - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject jsonObject = (JsonObject) json; - Assert.assertTrue(jsonObject.hasKey("recursive")); - Assert.assertTrue(jsonObject.get("recursive") instanceof JsonNull); - Assert.assertEquals(0, jsonObject.getNumber("index"), PRECISION); - - bean = JsonSerializer.toObject(RecursiveObject.class, json); - - Assert.assertNotNull("The deserialized object should not be null", - bean); - Assert.assertNull(bean.getRecursive()); - Assert.assertEquals(0, bean.getIndex()); - } - - @Test - public void serializePopulatedRecursiveObject_returnJsonObjectWithPopulatedProperties() { - final int recursions = 10; - RecursiveObject bean = createRecusiveObject(recursions, 0); - - JsonValue json = JsonSerializer.toJson(bean); - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject object = ((JsonObject) json); - for (int i = 0; i < recursions; i++) { - Assert.assertEquals(i, object.getNumber("index"), PRECISION); - if (i < recursions - 1) { - object = object.getObject("recursive"); - } else { - Assert.assertTrue(object.get("recursive") instanceof JsonNull); - } - } - - bean = JsonSerializer.toObject(RecursiveObject.class, json); - - for (int i = 0; i < recursions; i++) { - Assert.assertEquals(i, bean.getIndex()); - bean = bean.getRecursive(); - } - } - - @Test - public void serializeEmptyObjectWithBasicCollections_returnJsonObjectWithNullProperties() { - ObjectWithBasicCollections bean = new ObjectWithBasicCollections(); - - /* - * private List listOfStrings; private Set - * setOfIntegers; private LinkedList linkedListOfBooleans; - * private ArrayList arrayListOfDoubles; - * - */ - - JsonValue json = JsonSerializer.toJson(bean); - - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject jsonObject = (JsonObject) json; - Assert.assertTrue(jsonObject.hasKey("listOfStrings")); - Assert.assertTrue(jsonObject.get("listOfStrings") instanceof JsonNull); - Assert.assertTrue(jsonObject.hasKey("setOfIntegers")); - Assert.assertTrue(jsonObject.get("setOfIntegers") instanceof JsonNull); - Assert.assertTrue(jsonObject.hasKey("linkedListOfBooleans")); - Assert.assertTrue( - jsonObject.get("linkedListOfBooleans") instanceof JsonNull); - Assert.assertTrue(jsonObject.hasKey("arrayListOfDoubles")); - Assert.assertTrue( - jsonObject.get("arrayListOfDoubles") instanceof JsonNull); - - bean = JsonSerializer.toObject(ObjectWithBasicCollections.class, json); - - Assert.assertNotNull("The deserialized object should not be null", - bean); - Assert.assertNull(bean.getListOfStrings()); - Assert.assertNull(bean.getSetOfIntegers()); - Assert.assertNull(bean.getLinkedListOfBooleans()); - Assert.assertNull(bean.getArrayListOfDoubles()); - } - - @Test - public void serializeObjectWithCollections_returnJsonObjectWithPopulatedProperties() { - ObjectWithBasicCollections bean = new ObjectWithBasicCollections(); - - bean.setListOfStrings(Arrays.asList("string1", "string2")); - bean.setSetOfIntegers(new LinkedHashSet<>(Arrays.asList(3, 4))); - bean.setLinkedListOfBooleans( - new LinkedList<>(Arrays.asList(true, false))); - bean.setArrayListOfDoubles(new ArrayList<>(Arrays.asList(5.0, 6.0))); - - JsonValue json = JsonSerializer.toJson(bean); - - Assert.assertTrue("The JsonValue should be instanceof JsonObject", - json instanceof JsonObject); - - JsonObject jsonObject = (JsonObject) json; - JsonArray array = (JsonArray) jsonObject.get("listOfStrings"); - Assert.assertEquals("string1", array.getString(0)); - Assert.assertEquals("string2", array.getString(1)); - - array = (JsonArray) jsonObject.get("setOfIntegers"); - Assert.assertEquals(3, array.getNumber(0), PRECISION); - Assert.assertEquals(4, array.getNumber(1), PRECISION); - - array = (JsonArray) jsonObject.get("linkedListOfBooleans"); - Assert.assertEquals(true, array.getBoolean(0)); - Assert.assertEquals(false, array.getBoolean(1)); - - array = (JsonArray) jsonObject.get("arrayListOfDoubles"); - Assert.assertEquals(5, array.getNumber(0), PRECISION); - Assert.assertEquals(6, array.getNumber(1), PRECISION); - - bean = JsonSerializer.toObject(ObjectWithBasicCollections.class, json); - - Assert.assertNotNull("The deserialized object should not be null", - bean); - assertCollectionItemsAreEqual(bean.getListOfStrings(), "string1", - "string2"); - assertCollectionItemsAreEqual(bean.getSetOfIntegers(), 3, 4); - assertCollectionItemsAreEqual(bean.getLinkedListOfBooleans(), true, - false); - assertCollectionItemsAreEqual(bean.getArrayListOfDoubles(), 5.0, 6.0); - } - - private void assertCollectionItemsAreEqual(Collection collection, - T... values) { - int index = 0; - for (T collectionValue : collection) { - Assert.assertEquals(collectionValue, values[index]); - index++; - } - } - - private RecursiveObject createRecusiveObject(int recursions, int index) { - if (index < recursions) { - RecursiveObject bean = new RecursiveObject(); - bean.setIndex(index); - bean.setRecursive(createRecusiveObject(recursions, index + 1)); - return bean; - } - return null; - } - - private void assertObjectHasNullValueForKey(JsonObject object, String key) { - Assert.assertTrue(key + " should be present in the JsonObject", - object.hasKey(key)); - Assert.assertTrue(key + " property should be JsonNull", - object.get(key) instanceof JsonNull); - } - - private void assertObjectHas0ValueForKey(JsonObject object, String key) { - Assert.assertTrue(key + " should be present in the JsonObject", - object.hasKey(key)); - Assert.assertEquals(key + " should be 0.0 in the JsonObject", 0.0, - object.getNumber(key), PRECISION); - } - - private void assertObjectHasFalseValueForKey(JsonObject object, - String key) { - Assert.assertTrue(key + " should be present in the JsonObject", - object.hasKey(key)); - Assert.assertEquals(key + " should be false in the JsonObject", false, - object.getBoolean(key)); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java deleted file mode 100644 index c7ae123018c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/JsonUtilsTest.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.DoubleStream; -import java.util.stream.Stream; - -import com.vaadin.flow.internal.JsonUtilsTest.ChildBean; - -import org.junit.Assert; -import org.junit.Test; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; -import elemental.json.JsonValue; -import elemental.json.impl.JreJsonNull; - -public class JsonUtilsTest { - @Test - public void testEquals() { - // Equal - Assert.assertTrue( - JsonUtils.jsonEquals(Json.create(true), Json.create(true))); - Assert.assertTrue( - JsonUtils.jsonEquals(Json.create("foo"), Json.create("foo"))); - Assert.assertTrue( - JsonUtils.jsonEquals(Json.create(3.14), Json.create(3.14))); - Assert.assertTrue( - JsonUtils.jsonEquals(Json.createNull(), Json.createNull())); - Assert.assertTrue( - JsonUtils.jsonEquals(createTestObject1(), createTestObject1())); - Assert.assertTrue( - JsonUtils.jsonEquals(createTestArray1(), createTestArray1())); - - // Non-equal with matching types - Assert.assertFalse( - JsonUtils.jsonEquals(Json.create(true), Json.create(false))); - Assert.assertFalse( - JsonUtils.jsonEquals(Json.create("foo"), Json.create("oof"))); - Assert.assertFalse( - JsonUtils.jsonEquals(Json.create(3.14), Json.create(3.142))); - Assert.assertFalse( - JsonUtils.jsonEquals(createTestObject1(), createTestObject2())); - Assert.assertFalse( - JsonUtils.jsonEquals(createTestArray1(), createTestArray2())); - - // Non-equal with different types - Assert.assertFalse( - JsonUtils.jsonEquals(Json.create(true), Json.create("true"))); - Assert.assertFalse( - JsonUtils.jsonEquals(Json.create(3.14), Json.create("3.14"))); - Assert.assertFalse( - JsonUtils.jsonEquals(Json.createNull(), Json.create("null"))); - Assert.assertFalse( - JsonUtils.jsonEquals(Json.createObject(), Json.create("{}"))); - Assert.assertFalse( - JsonUtils.jsonEquals(Json.createArray(), Json.create(0))); - Assert.assertFalse( - JsonUtils.jsonEquals(createTestArray1(), createTestObject1())); - } - - @Test(expected = AssertionError.class) - public void testEquals_firstNull_throws() { - JsonUtils.jsonEquals(null, Json.createNull()); - } - - @Test(expected = AssertionError.class) - public void testEquals_secondNull_throws() { - JsonUtils.jsonEquals(Json.createNull(), null); - } - - private static JsonObject createTestObject1() { - JsonObject object = Json.createObject(); - - object.put("foo", "foo"); - object.put("bar", createTestArray1()); - object.put("baz", Json.createObject()); - - return object; - } - - private static JsonObject createTestObject2() { - JsonObject object = Json.createObject(); - - object.put("foo", "oof"); - object.put("bar", createTestArray2()); - object.put("baz", Json.createArray()); - - return object; - } - - private static JsonArray createTestArray1() { - return Stream.of(Json.create("foo"), Json.createObject()) - .collect(JsonUtils.asArray()); - } - - private static JsonArray createTestArray2() { - return Stream.of(Json.create("bar"), Json.createArray()) - .collect(JsonUtils.asArray()); - } - - @Test - public void collectEmptyStream() { - Stream jsonValueStream = Stream.empty(); - JsonArray a = jsonValueStream.collect(JsonUtils.asArray()); - Assert.assertEquals(0, a.length()); - } - - public void createObjectStreamForNull() { - Assert.assertEquals(Stream.empty(), JsonUtils.objectStream(null)); - } - - public void createNumberStreamForNull() { - Assert.assertEquals(Stream.empty(), JsonUtils.numberStream(null)); - } - - public void createStreamForNull() { - Assert.assertEquals(Stream.empty(), JsonUtils.stream(null)); - } - - @Test - public void testStream() { - JsonArray array = createTestArray1(); - List list = JsonUtils.stream(array) - .collect(Collectors.toList()); - - Assert.assertEquals(2, list.size()); - Assert.assertEquals("foo", list.get(0).asString()); - Assert.assertTrue( - JsonUtils.jsonEquals(list.get(1), Json.createObject())); - } - - @Test - public void testObjectStream() { - JsonArray array = Stream.of(Json.createObject(), createTestObject1(), - createTestObject2()).collect(JsonUtils.asArray()); - - List objects = JsonUtils.objectStream(array) - .collect(Collectors.toList()); - - Assert.assertEquals(3, objects.size()); - Assert.assertTrue( - JsonUtils.jsonEquals(Json.createObject(), objects.get(0))); - Assert.assertTrue( - JsonUtils.jsonEquals(createTestObject1(), objects.get(1))); - Assert.assertTrue( - JsonUtils.jsonEquals(createTestObject2(), objects.get(2))); - } - - @Test - public void testNumberStream() { - double[] values = new double[] { 3.14, 42, Double.MAX_VALUE }; - - JsonArray array = DoubleStream.of(values).mapToObj(Json::create) - .collect(JsonUtils.asArray()); - - DoubleStream numberStream = JsonUtils.numberStream(array); - - Assert.assertArrayEquals(values, numberStream.toArray(), 0); - } - - @Test - public void testAsArray() { - Stream stream = JsonUtils.stream(createTestArray1()); - - JsonArray array = stream.collect(JsonUtils.asArray()); - - Assert.assertTrue(JsonUtils.jsonEquals(createTestArray1(), array)); - } - - @Test - public void testCreateArray() { - JsonArray array = JsonUtils.createArray(Json.create("string"), - Json.createNull()); - - Assert.assertEquals(2, array.length()); - Assert.assertEquals("string", array.getString(0)); - Assert.assertSame(JreJsonNull.class, array.get(1).getClass()); - } - - @Test - public void testCreateEmptyArray() { - JsonArray array = JsonUtils.createArray(); - - Assert.assertEquals(0, array.length()); - } - - @Test - public void createObject() { - HashMap map = new HashMap<>(); - map.put("integer", Integer.valueOf(3)); - map.put("string", "foo"); - - JsonObject object = JsonUtils.createObject(map, item -> { - if (item instanceof Integer) { - return Json.create(((Integer) item).doubleValue()); - } else { - return Json.create(String.valueOf(item)); - } - }); - - Assert.assertEquals(2, object.keys().length); - Assert.assertEquals(3, object.getNumber("integer"), 0); - Assert.assertEquals("foo", object.getString("string")); - } - - @Test - public void testCreateEmptyObject() { - JsonObject object = JsonUtils.createObject(Collections.emptyMap(), - item -> { - throw new AssertionError("Callback should not be called"); - }); - - Assert.assertEquals(0, object.keys().length); - } - - public static class SimpleBean { - private String string = "value"; - private int number = 1; - private float flt = 2.3f; - private double dbl = 4.56; - - public String getString() { - return string; - } - - public int getNumber() { - return number; - } - - public float getFlt() { - return flt; - } - - public double getDbl() { - return dbl; - } - } - - public static class ParentBean { - private String parentValue = "parent"; - private ChildBean child = new ChildBean(); - - public String getParentValue() { - return parentValue; - } - - public ChildBean getChild() { - return child; - } - } - - public static class ChildBean { - private String childValue = "child"; - - public String getChildValue() { - return childValue; - } - } - - public static class ListAndMapBean { - private Map integerMap = new HashMap<>(); - private Map childBeanMap = new HashMap<>(); - - private List integerList = new ArrayList<>(); - private List childBeanList = new ArrayList<>(); - { - integerMap.put("one", 1); - integerMap.put("two", 2); - - integerList.add(3); - integerList.add(2); - integerList.add(1); - - ChildBean firstChild = new ChildBean(); - firstChild.childValue = "firstChildValue"; - childBeanMap.put("First", firstChild); - ChildBean secondChild = new ChildBean(); - secondChild.childValue = "secondChildValue"; - childBeanMap.put("Second", secondChild); - - childBeanList.add(firstChild); - childBeanList.add(secondChild); - } - - public Map getIntegerMap() { - return integerMap; - } - - public List getChildBeanList() { - return childBeanList; - } - - public List getIntegerList() { - return integerList; - } - - public Map getChildBeanMap() { - return childBeanMap; - } - } - - @Test - public void simpleBeanToJson() { - JsonObject json = JsonUtils.beanToJson(new SimpleBean()); - Assert.assertEquals("value", json.getString("string")); - Assert.assertEquals(1.0, json.getNumber("number"), 0.0); - Assert.assertEquals(2.3, json.getNumber("flt"), 0.0); - Assert.assertEquals(4.56, json.getNumber("dbl"), 0.0); - } - - @Test - public void nestedBeanToJson() { - JsonObject json = JsonUtils.beanToJson(new ParentBean()); - Assert.assertEquals("parent", json.getString("parentValue")); - JsonObject child = json.getObject("child"); - Assert.assertEquals("child", child.getString("childValue")); - } - - @Test - public void nullChildBean() { - ParentBean bean = new ParentBean(); - bean.child = null; - - JsonObject json = JsonUtils.beanToJson(bean); - Assert.assertEquals(Json.createNull(), json.get("child")); - } - - @Test - public void beanWithListAndMap() { - ListAndMapBean bean = new ListAndMapBean(); - - JsonObject json = JsonUtils.beanToJson(bean); - - JsonObject integerMap = json.getObject("integerMap"); - Assert.assertEquals(1, integerMap.getNumber("one"), 0); - Assert.assertEquals(2, integerMap.getNumber("two"), 0); - - JsonObject childBeanMap = json.getObject("childBeanMap"); - JsonObject firstChild = childBeanMap.getObject("First"); - Assert.assertEquals("firstChildValue", - firstChild.getString("childValue")); - JsonObject secondChild = childBeanMap.getObject("Second"); - Assert.assertEquals("secondChildValue", - secondChild.getString("childValue")); - - JsonArray integerList = json.getArray("integerList"); - Assert.assertEquals(3, integerList.get(0).asNumber(), 0); - Assert.assertEquals(2, integerList.get(1).asNumber(), 0); - Assert.assertEquals(1, integerList.get(2).asNumber(), 0); - - JsonArray childBeanList = json.getArray("childBeanList"); - Assert.assertEquals("firstChildValue", - ((JsonObject) childBeanList.get(0)).getString("childValue")); - Assert.assertEquals("secondChildValue", - ((JsonObject) childBeanList.get(1)).getString("childValue")); - } - - @Test - public void simpleBeanListToJson() { - ArrayList list = new ArrayList<>(); - SimpleBean bean1 = new SimpleBean(); - bean1.string = "bean1"; - SimpleBean bean2 = new SimpleBean(); - bean2.string = "bean2"; - list.add(bean1); - list.add(bean2); - JsonArray json = JsonUtils.listToJson(list); - - Assert.assertEquals("bean1", json.getObject(0).getString("string")); - Assert.assertEquals("bean2", json.getObject(1).getString("string")); - } - - @Test - public void simpleMapToJson() { - Map map = new HashMap<>(); - SimpleBean bean1 = new SimpleBean(); - bean1.string = "bean1"; - SimpleBean bean2 = new SimpleBean(); - bean2.string = "bean2"; - - map.put("one", bean1); - map.put("two", bean2); - JsonObject json = JsonUtils.mapToJson(map); - - Assert.assertEquals("bean1", json.getObject("one").getString("string")); - Assert.assertEquals("bean2", json.getObject("two").getString("string")); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/LocaleUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/LocaleUtilTest.java deleted file mode 100644 index 88e923d05da..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/LocaleUtilTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.util.Arrays; -import java.util.Locale; -import java.util.Optional; -import java.util.Vector; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import com.vaadin.flow.server.VaadinRequest; - -/** - * Test class for the locale util methods. - */ -public class LocaleUtilTest { - - public static final Locale LOCALE_FI = new Locale("fi", "FI"); - public static final Locale LOCALE_EN = new Locale("en", "GB"); - - @Mock - VaadinRequest request; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - - // request locales are returned as Enumeration - Mockito.when(request.getLocales()).thenReturn( - new Vector<>(Arrays.asList(new Locale("fi"), LOCALE_EN)) - .elements()); - } - - @Test - public void exact_match_provided_matches() { - Optional exactLocaleMatch = LocaleUtil.getExactLocaleMatch( - request, Arrays.asList(Locale.ENGLISH, LOCALE_EN)); - - Assert.assertEquals( - "Found wrong locale event though an exact match should have been available.", - LOCALE_EN, exactLocaleMatch.get()); - } - - @Test - public void no_exact_match_returns_null() { - Optional exactLocaleMatch = LocaleUtil - .getExactLocaleMatch(request, Arrays.asList(Locale.ENGLISH)); - - Assert.assertFalse( - "Found locale event though none should have been available.", - exactLocaleMatch.isPresent()); - } - - @Test - public void language_match_gets_correct_target_by_request_priority() { - Optional exactLocaleMatch = LocaleUtil.getLocaleMatchByLanguage( - request, Arrays.asList(Locale.US, LOCALE_FI)); - - Assert.assertEquals( - "Found wrong locale event though an language match should have been available.", - LOCALE_FI, exactLocaleMatch.get()); - } - - @Test - public void language_match_returns_null_when_no_match() { - Optional exactLocaleMatch = LocaleUtil.getLocaleMatchByLanguage( - request, Arrays.asList(Locale.FRENCH, Locale.KOREA)); - - Assert.assertFalse( - "Found locale event though none should have been available.", - exactLocaleMatch.isPresent()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/RangeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/RangeTest.java deleted file mode 100644 index 04b591f9992..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/RangeTest.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -@SuppressWarnings("static-method") -public class RangeTest { - - @Test(expected = IllegalArgumentException.class) - public void startAfterEndTest() { - Range.between(10, 9); - } - - @Test(expected = IllegalArgumentException.class) - public void negativeLengthTest() { - Range.withLength(10, -1); - } - - @Test - public void constructorEquivalenceTest() { - assertEquals("10 == [10,11[", Range.withOnly(10), - Range.between(10, 11)); - assertEquals("[10,20[ == 10, length 10", Range.between(10, 20), - Range.withLength(10, 10)); - assertEquals("10 == 10, length 1", Range.withOnly(10), - Range.withLength(10, 1)); - } - - @Test - public void boundsTest() { - { - final Range range = Range.between(0, 10); - assertEquals("between(0, 10) start", 0, range.getStart()); - assertEquals("between(0, 10) end", 10, range.getEnd()); - } - - { - final Range single = Range.withOnly(10); - assertEquals("withOnly(10) start", 10, single.getStart()); - assertEquals("withOnly(10) end", 11, single.getEnd()); - } - - { - final Range length = Range.withLength(10, 5); - assertEquals("withLength(10, 5) start", 10, length.getStart()); - assertEquals("withLength(10, 5) end", 15, length.getEnd()); - } - } - - @Test - @SuppressWarnings("boxing") - public void equalsTest() { - final Range range1 = Range.between(0, 10); - final Range range2 = Range.withLength(0, 11); - - assertTrue("null", !range1.equals(null)); - assertTrue("reflexive", range1.equals(range1)); - assertEquals("symmetric", range1.equals(range2), range2.equals(range1)); - } - - @Test - public void containsTest() { - final int start = 0; - final int end = 10; - final Range range = Range.between(start, end); - - assertTrue("start should be contained", range.contains(start)); - assertTrue("start-1 should not be contained", - !range.contains(start - 1)); - assertTrue("end should not be contained", !range.contains(end)); - assertTrue("end-1 should be contained", range.contains(end - 1)); - - assertTrue("[0..10[ contains 5", Range.between(0, 10).contains(5)); - assertTrue("empty range does not contain 5", - !Range.between(5, 5).contains(5)); - } - - @Test - public void emptyTest() { - assertTrue("[0..0[ should be empty", Range.between(0, 0).isEmpty()); - assertTrue("Range of length 0 should be empty", - Range.withLength(0, 0).isEmpty()); - - assertTrue("[0..1[ should not be empty", - !Range.between(0, 1).isEmpty()); - assertTrue("Range of length 1 should not be empty", - !Range.withLength(0, 1).isEmpty()); - } - - @Test - public void splitTest() { - final Range startRange = Range.between(0, 10); - final Range[] splitRanges = startRange.splitAt(5); - assertEquals("[0..10[ split at 5, lower", Range.between(0, 5), - splitRanges[0]); - assertEquals("[0..10[ split at 5, upper", Range.between(5, 10), - splitRanges[1]); - } - - @Test - public void split_valueBefore() { - Range range = Range.between(10, 20); - Range[] splitRanges = range.splitAt(5); - - assertEquals(Range.between(10, 10), splitRanges[0]); - assertEquals(range, splitRanges[1]); - } - - @Test - public void split_valueAfter() { - Range range = Range.between(10, 20); - Range[] splitRanges = range.splitAt(25); - - assertEquals(range, splitRanges[0]); - assertEquals(Range.between(20, 20), splitRanges[1]); - } - - @Test - public void emptySplitTest() { - final Range range = Range.between(5, 10); - final Range[] split1 = range.splitAt(0); - assertTrue("split1, [0]", split1[0].isEmpty()); - assertEquals("split1, [1]", range, split1[1]); - - final Range[] split2 = range.splitAt(15); - assertEquals("split2, [0]", range, split2[0]); - assertTrue("split2, [1]", split2[1].isEmpty()); - } - - @Test - public void lengthTest() { - assertEquals("withLength length", 5, Range.withLength(10, 5).length()); - assertEquals("between length", 5, Range.between(10, 15).length()); - assertEquals("withOnly 10 length", 1, Range.withOnly(10).length()); - } - - @Test - public void intersectsTest() { - assertTrue("[0..10[ intersects [5..15[", - Range.between(0, 10).intersects(Range.between(5, 15))); - assertTrue("[0..10[ does not intersect [10..20[", - !Range.between(0, 10).intersects(Range.between(10, 20))); - } - - @Test - public void intersects_emptyInside() { - assertTrue("[5..5[ does intersect with [0..10[", - Range.between(5, 5).intersects(Range.between(0, 10))); - assertTrue("[0..10[ does intersect with [5..5[", - Range.between(0, 10).intersects(Range.between(5, 5))); - } - - @Test - public void intersects_emptyOutside() { - assertTrue("[15..15[ does not intersect with [0..10[", - !Range.between(15, 15).intersects(Range.between(0, 10))); - assertTrue("[0..10[ does not intersect with [15..15[", - !Range.between(0, 10).intersects(Range.between(15, 15))); - } - - @Test - public void subsetTest() { - assertTrue("[5..10[ is subset of [0..20[", - Range.between(5, 10).isSubsetOf(Range.between(0, 20))); - - final Range range = Range.between(0, 10); - assertTrue("range is subset of self", range.isSubsetOf(range)); - - assertTrue("[0..10[ is not subset of [5..15[", - !Range.between(0, 10).isSubsetOf(Range.between(5, 15))); - } - - @Test - public void offsetTest() { - assertEquals(Range.between(5, 15), Range.between(0, 10).offsetBy(5)); - } - - @Test - public void rangeStartsBeforeTest() { - final Range former = Range.between(0, 5); - final Range latter = Range.between(1, 5); - assertTrue("former should starts before latter", - former.startsBefore(latter)); - assertTrue("latter shouldn't start before latter", - !latter.startsBefore(former)); - - assertTrue("no overlap allowed", - !Range.between(0, 5).startsBefore(Range.between(0, 10))); - } - - @Test - public void rangeStartsAfterTest() { - final Range former = Range.between(0, 5); - final Range latter = Range.between(5, 10); - assertTrue("latter should start after former", - latter.startsAfter(former)); - assertTrue("former shouldn't start after latter", - !former.startsAfter(latter)); - - assertTrue("no overlap allowed", - !Range.between(5, 10).startsAfter(Range.between(0, 6))); - } - - @Test - public void rangeEndsBeforeTest() { - final Range former = Range.between(0, 5); - final Range latter = Range.between(5, 10); - assertTrue("latter should end before former", - former.endsBefore(latter)); - assertTrue("former shouldn't end before latter", - !latter.endsBefore(former)); - - assertTrue("no overlap allowed", - !Range.between(5, 10).endsBefore(Range.between(9, 15))); - } - - @Test - public void rangeEndsAfterTest() { - final Range former = Range.between(1, 5); - final Range latter = Range.between(1, 6); - assertTrue("latter should end after former", latter.endsAfter(former)); - assertTrue("former shouldn't end after latter", - !former.endsAfter(latter)); - - assertTrue("no overlap allowed", - !Range.between(0, 10).endsAfter(Range.between(5, 10))); - } - - @Test(expected = IllegalArgumentException.class) - public void combine_notOverlappingFirstSmaller() { - Range.between(0, 10).combineWith(Range.between(11, 20)); - } - - @Test(expected = IllegalArgumentException.class) - public void combine_notOverlappingSecondLarger() { - Range.between(11, 20).combineWith(Range.between(0, 10)); - } - - @Test(expected = IllegalArgumentException.class) - public void combine_firstEmptyNotOverlapping() { - Range.between(15, 15).combineWith(Range.between(0, 10)); - } - - @Test(expected = IllegalArgumentException.class) - public void combine_secondEmptyNotOverlapping() { - Range.between(0, 10).combineWith(Range.between(15, 15)); - } - - @Test - public void combine_barelyOverlapping() { - Range r1 = Range.between(0, 10); - Range r2 = Range.between(10, 20); - - // Test both ways, should give the same result - Range combined1 = r1.combineWith(r2); - Range combined2 = r2.combineWith(r1); - assertEquals(combined1, combined2); - - assertEquals(0, combined1.getStart()); - assertEquals(20, combined1.getEnd()); - } - - @Test - public void combine_subRange() { - Range r1 = Range.between(0, 10); - Range r2 = Range.between(2, 8); - - // Test both ways, should give the same result - Range combined1 = r1.combineWith(r2); - Range combined2 = r2.combineWith(r1); - assertEquals(combined1, combined2); - - assertEquals(r1, combined1); - } - - @Test - public void combine_intersecting() { - Range r1 = Range.between(0, 10); - Range r2 = Range.between(5, 15); - - // Test both ways, should give the same result - Range combined1 = r1.combineWith(r2); - Range combined2 = r2.combineWith(r1); - assertEquals(combined1, combined2); - - assertEquals(0, combined1.getStart()); - assertEquals(15, combined1.getEnd()); - - } - - @Test - public void combine_emptyInside() { - Range r1 = Range.between(0, 10); - Range r2 = Range.between(5, 5); - - // Test both ways, should give the same result - Range combined1 = r1.combineWith(r2); - Range combined2 = r2.combineWith(r1); - assertEquals(combined1, combined2); - - assertEquals(r1, combined1); - } - - @Test - public void expand_basic() { - Range r1 = Range.between(5, 10); - Range r2 = r1.expand(2, 3); - - assertEquals(Range.between(3, 13), r2); - } - - @Test - public void expand_negativeLegal() { - Range r1 = Range.between(5, 10); - - Range r2 = r1.expand(-2, -2); - assertEquals(Range.between(7, 8), r2); - - Range r3 = r1.expand(-3, -2); - assertEquals(Range.between(8, 8), r3); - - Range r4 = r1.expand(3, -8); - assertEquals(Range.between(2, 2), r4); - } - - @Test(expected = IllegalArgumentException.class) - public void expand_negativeIllegal1() { - Range r1 = Range.between(5, 10); - - // Should throw because the start would contract beyond the end - r1.expand(-3, -3); - - } - - @Test(expected = IllegalArgumentException.class) - public void expand_negativeIllegal2() { - Range r1 = Range.between(5, 10); - - // Should throw because the end would contract beyond the start - r1.expand(3, -9); - } - - @Test - public void restrictTo_fullyInside() { - Range r1 = Range.between(5, 10); - Range r2 = Range.between(4, 11); - - Range r3 = r1.restrictTo(r2); - assertTrue(r1 == r3); - } - - @Test - public void restrictTo_fullyOutside() { - Range r1 = Range.between(4, 11); - Range r2 = Range.between(5, 10); - - Range r3 = r1.restrictTo(r2); - assertTrue(r2 == r3); - } - - @Test - public void restrictTo_notInterstecting() { - Range r1 = Range.between(5, 10); - Range r2 = Range.between(15, 20); - - Range r3 = r1.restrictTo(r2); - assertTrue("Non-intersecting ranges should produce an empty result", - r3.isEmpty()); - - Range r4 = r2.restrictTo(r1); - assertTrue("Non-intersecting ranges should produce an empty result", - r4.isEmpty()); - } - - @Test - public void restrictTo_startOutside() { - Range r1 = Range.between(5, 10); - Range r2 = Range.between(7, 15); - - Range r3 = r1.restrictTo(r2); - - assertEquals(Range.between(7, 10), r3); - - assertEquals(r2.restrictTo(r1), r3); - } - - @Test - public void restrictTo_endOutside() { - Range r1 = Range.between(5, 10); - Range r2 = Range.between(4, 7); - - Range r3 = r1.restrictTo(r2); - - assertEquals(Range.between(5, 7), r3); - - assertEquals(r2.restrictTo(r1), r3); - } - - @Test - public void restrictTo_empty() { - Range r1 = Range.between(5, 10); - Range r2 = Range.between(0, 0); - - Range r3 = r1.restrictTo(r2); - assertTrue(r3.isEmpty()); - - Range r4 = r2.restrictTo(r1); - assertTrue(r4.isEmpty()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsGetFieldValueByTypeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsGetFieldValueByTypeTest.java deleted file mode 100644 index 732d52a4fef..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsGetFieldValueByTypeTest.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.vaadin.flow.internal; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -public class ReflectToolsGetFieldValueByTypeTest { - @Test - public void getFieldValue() { - class MyClass { - @SuppressWarnings("unused") - public Integer getField() { - return 1; - } - - @SuppressWarnings("unused") - public void setField(Integer i) { - } - - } - class MySubClass extends MyClass { - @SuppressWarnings("unused") - public String field = "Hello"; - } - - MySubClass myInstance = new MySubClass(); - - java.lang.reflect.Field memberField; - Object fieldValue = Boolean.FALSE; - try { - memberField = myInstance.getClass().getField("field"); - // Should get a String value. Without the third parameter (calling - // ReflectTools.getJavaFieldValue(Object object, Field field)) would - // get an Integer value - fieldValue = ReflectTools.getJavaFieldValue(myInstance, memberField, - String.class); - } catch (Exception e) { - } - assertTrue(fieldValue instanceof String); - - } - - @Test - public void getFieldValueViaGetter() { - class MyClass { - @SuppressWarnings("unused") - public Integer field = 1; - } - class MySubClass extends MyClass { - @SuppressWarnings("unused") - public String field = "Hello"; - } - - MySubClass myInstance = new MySubClass(); - - java.lang.reflect.Field memberField; - try { - memberField = myInstance.getClass().getField("field"); - // Should throw an IllegalArgument exception as the mySubClass class - // doesn't have an Integer field. - ReflectTools.getJavaFieldValue(myInstance, memberField, - Integer.class); - fail("Previous method call should have thrown an exception"); - } catch (Exception e) { - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsGetPrimitiveFieldValueTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsGetPrimitiveFieldValueTest.java deleted file mode 100644 index 096951967a0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsGetPrimitiveFieldValueTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.vaadin.flow.internal; - -import static org.junit.Assert.assertFalse; - -import org.junit.Test; - -public class ReflectToolsGetPrimitiveFieldValueTest { - @Test - public void getFieldValueViaGetter() { - class MyClass { - @SuppressWarnings("unused") - public int field = 1; - } - - MyClass myInstance = new MyClass(); - - java.lang.reflect.Field memberField; - Object fieldValue = Boolean.FALSE; - try { - memberField = myInstance.getClass().getField("field"); - fieldValue = ReflectTools.getJavaFieldValue(myInstance, - memberField); - } catch (Exception e) { - } - assertFalse(fieldValue instanceof Boolean); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsTest.java deleted file mode 100644 index 792bcea549e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectToolsTest.java +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -public class ReflectToolsTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - public class NonStaticInnerClass { - public NonStaticInnerClass() { - - } - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - public @interface TestAnnotation { - String value(); - } - - @TestAnnotation("foo") - public static class ClassWithAnnotation { - - } - - public static class ClassWithoutAnnotation { - - } - - private class PrivateInnerClass { - } - - private static class PrivateStaticInnerClassPublicConstructor { - @SuppressWarnings("unused") - public PrivateStaticInnerClassPublicConstructor() { - - } - } - - public static class StaticInnerPrivateConstructorClass { - private StaticInnerPrivateConstructorClass() { - } - } - - public static class StaticInnerConstructorNeedsParamsClass { - public StaticInnerConstructorNeedsParamsClass(String foo) { - - } - } - - public static class ConstructorThrowsExceptionClass { - public ConstructorThrowsExceptionClass() { - throw new NullPointerException(); - } - } - - public static class OkToCreate { - - } - - public static class VarArgsCtor { - - public VarArgsCtor(String... args) { - - } - } - - public interface Entity { - ID getId(); - - void setId(ID id); - } - - public static class CustomClassLoader extends ClassLoader { - protected CustomClassLoader(ClassLoader parent) { - super(parent); - } - - protected CustomClassLoader() { - super(); - } - } - - public class Category implements Serializable, Entity { - - @Override - public Long getId() { - return null; - } - - @Override - public void setId(Long id) { - } - } - - @Test - public void testCreateInstance() { - OkToCreate instance = ReflectTools.createInstance(OkToCreate.class); - - Assert.assertNotNull(instance); - Assert.assertSame("Created instance should be of the requested type", - OkToCreate.class, instance.getClass()); - } - - @Test - public void testCreateInstance_varArgsCtor() { - VarArgsCtor instance = ReflectTools.createInstance(VarArgsCtor.class); - - Assert.assertNotNull(instance); - Assert.assertSame("Created instance should be of the requested type", - VarArgsCtor.class, instance.getClass()); - } - - @Test - public void createNonStaticInnerClass() { - assertError( - ReflectTools.CREATE_INSTANCE_FAILED_FOR_NON_STATIC_MEMBER_CLASS, - NonStaticInnerClass.class); - } - - @Test - public void createPrivateInnerClass() { - assertError( - ReflectTools.CREATE_INSTANCE_FAILED_FOR_NON_STATIC_MEMBER_CLASS, - PrivateInnerClass.class); - } - - @Test - public void createStaticInnerPrivateConstructorClass() { - assertError( - ReflectTools.CREATE_INSTANCE_FAILED_NO_PUBLIC_NOARG_CONSTRUCTOR, - StaticInnerPrivateConstructorClass.class); - } - - @Test - public void createStaticInnerConstructorNeedsParamsClass() { - assertError( - ReflectTools.CREATE_INSTANCE_FAILED_NO_PUBLIC_NOARG_CONSTRUCTOR, - StaticInnerConstructorNeedsParamsClass.class); - } - - @Test - public void createConstructorThrowsExceptionClass() { - assertError( - ReflectTools.CREATE_INSTANCE_FAILED_CONSTRUCTOR_THREW_EXCEPTION, - ConstructorThrowsExceptionClass.class); - } - - @Test - public void localClass() { - class LocalClass { - } - assertError(ReflectTools.CREATE_INSTANCE_FAILED_LOCAL_CLASS, - LocalClass.class); - } - - @Test - public void createProxyForNonStaticInnerClass() { - Class originalClass = NonStaticInnerClass.class; - Class proxyClass = createProxyClass(originalClass); - - // Even though proxyClass was created on top of NonStaticInnerClass, the - // exception message does not show it. - // It's sort of a feature, because proxy class is created as a top-level - // class. - assertError( - ReflectTools.CREATE_INSTANCE_FAILED_NO_PUBLIC_NOARG_CONSTRUCTOR, - proxyClass); - - // This is how you get correct exception message. - try { - ReflectTools.createProxyInstance(proxyClass, originalClass); - Assert.fail("Creation should cause an exception"); - } catch (IllegalArgumentException re) { - Assert.assertEquals(String.format( - ReflectTools.CREATE_INSTANCE_FAILED_FOR_NON_STATIC_MEMBER_CLASS, - originalClass.getName()), re.getMessage()); - } - } - - public interface TestInterface { - - } - - public static class HasInterface implements TestInterface { - } - - public static class ParentInterface implements TestInterface { - } - - public static class ChildInterface extends ParentInterface { - } - - public interface TestInterfaceMulti { - - } - - public static class HasInterfaceMulti - implements TestInterfaceMulti { - } - - public static class ParentInterfacePartial - implements TestInterfaceMulti { - } - - public static class ParentInterfaceMulti - implements TestInterfaceMulti { - - } - - public static class ChildInterfaceMulti extends ParentInterfaceMulti { - } - - public static class ChildInterfacePartial - extends ParentInterfacePartial { - } - - public static abstract class TestAbstractClass { - - } - - protected static class TestProtectedClass { - - } - - protected static class TestPackageProtectedClass { - - } - - private static class TestPrivateClass { - - } - - public static class NormalService { - - } - - public static class TestNoNonArgConstructorClass { - public TestNoNonArgConstructorClass(String foo) { - - } - } - - @Test - public void getGenericInterfaceClass() { - Class genericInterfaceType = ReflectTools.getGenericInterfaceType( - HasInterface.class, TestInterface.class); - - Assert.assertEquals(String.class, genericInterfaceType); - - genericInterfaceType = ReflectTools.getGenericInterfaceType( - ChildInterface.class, TestInterface.class); - - Assert.assertEquals(Boolean.class, genericInterfaceType); - } - - @Test - public void getGenericInterfaceClasses() { - - List> genericInterfaceTypes = ReflectTools - .getGenericInterfaceTypes(HasInterface.class, - TestInterface.class); - Assert.assertArrayEquals(new Class[] { String.class }, - genericInterfaceTypes.toArray()); - - genericInterfaceTypes = ReflectTools.getGenericInterfaceTypes( - ChildInterface.class, TestInterface.class); - Assert.assertArrayEquals(new Class[] { Boolean.class }, - genericInterfaceTypes.toArray()); - - genericInterfaceTypes = ReflectTools.getGenericInterfaceTypes( - HasInterfaceMulti.class, TestInterfaceMulti.class); - Assert.assertArrayEquals( - new Class[] { String.class, Integer.class, Double.class }, - genericInterfaceTypes.toArray()); - - genericInterfaceTypes = ReflectTools.getGenericInterfaceTypes( - ChildInterfaceMulti.class, TestInterfaceMulti.class); - Assert.assertArrayEquals( - new Class[] { Boolean.class, Float.class, Long.class }, - genericInterfaceTypes.toArray()); - - genericInterfaceTypes = ReflectTools.getGenericInterfaceTypes( - ChildInterfacePartial.class, TestInterfaceMulti.class); - Assert.assertArrayEquals( - new Class[] { Boolean.class, Short.class, Long.class }, - genericInterfaceTypes.toArray()); - } - - @Test - public void findCommonBaseType_sameType() { - assertSame(Number.class, - ReflectTools.findCommonBaseType(Number.class, Number.class)); - } - - @Test - public void findCommonBaseType_aExtendsB() { - assertSame(Number.class, - ReflectTools.findCommonBaseType(Integer.class, Number.class)); - } - - @Test - public void findCommonBaseType_bExtendsA() { - assertSame(Number.class, - ReflectTools.findCommonBaseType(Number.class, Integer.class)); - } - - @Test - public void findCommonBaseType_commonBase() { - assertSame(Number.class, - ReflectTools.findCommonBaseType(Double.class, Integer.class)); - } - - @Test - public void findCommonBaseType_noCommonBase() { - assertSame(Object.class, - ReflectTools.findCommonBaseType(String.class, Number.class)); - } - - @Test - public void findCommonBaseType_interfaceNotSupported() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("a cannot be an interface"); - ReflectTools.findCommonBaseType(Comparable.class, Object.class); - } - - @Test - public void findCommonBaseType_primitiveNotSupported() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("a cannot be a primitive type"); - ReflectTools.findCommonBaseType(int.class, Object.class); - } - - @Test - public void getSetters_classIsGeneric_syntheticMethodsAreFilteredOut() { - List setters = ReflectTools.getSetterMethods(Category.class) - .collect(Collectors.toList()); - Assert.assertEquals(1, setters.size()); - Method setter = setters.get(0); - Assert.assertEquals("setId", setter.getName()); - Assert.assertEquals(Long.class, setter.getParameterTypes()[0]); - } - - @Test - public void findClosestCommonClassLoaderAncestor_findAncestor_whenBothArgumentsAreTheSame() { - CustomClassLoader loader = new CustomClassLoader(); - ClassLoader ret = ReflectTools - .findClosestCommonClassLoaderAncestor(loader, loader).get(); - - Assert.assertEquals(loader, ret); - } - - public void findClosestCommonClassLoaderAncestor_null_whenNoSharedAncestor() { - CustomClassLoader loader1 = new CustomClassLoader(); - CustomClassLoader loader2 = new CustomClassLoader(); - - Optional ret = ReflectTools - .findClosestCommonClassLoaderAncestor(loader1, loader2); - - Assert.assertFalse(ret.isPresent()); - } - - @Test - public void findClosestCommonClassLoaderAncestor_findsAncestor_whenOneIsParentOfTheOther() { - CustomClassLoader parent = new CustomClassLoader(); - CustomClassLoader child = new CustomClassLoader(parent); - ClassLoader ret = ReflectTools - .findClosestCommonClassLoaderAncestor(parent, child).get(); - - Assert.assertEquals(parent, ret); - } - - @Test - public void findClosestCommonClassLoaderAncestor_findsAncestor_whenLoadersShareParent() { - CustomClassLoader parent = new CustomClassLoader(); - CustomClassLoader childA = new CustomClassLoader(parent); - CustomClassLoader childB = new CustomClassLoader(parent); - ClassLoader ret = ReflectTools - .findClosestCommonClassLoaderAncestor(childA, childB).get(); - - Assert.assertEquals(parent, ret); - } - - @Test - public void findClosestCommonClassLoaderAncestor_findsAncestor_whenAncestorsAreOnDifferentLevels() { - CustomClassLoader grandParent = new CustomClassLoader(); - CustomClassLoader parent = new CustomClassLoader(grandParent); - CustomClassLoader childA = new CustomClassLoader(parent); - CustomClassLoader childB = new CustomClassLoader(grandParent); - - ClassLoader ret = ReflectTools - .findClosestCommonClassLoaderAncestor(childA, childB).get(); - - Assert.assertEquals(grandParent, ret); - } - - @Test - public void findClosestCommonClassLoaderAncestor_empty_whenEitherOrBothNull() { - CustomClassLoader loader = new CustomClassLoader(); - - Optional ret; - - ret = ReflectTools.findClosestCommonClassLoaderAncestor(loader, null); - Assert.assertFalse(ret.isPresent()); - - ret = ReflectTools.findClosestCommonClassLoaderAncestor(null, loader); - Assert.assertFalse(ret.isPresent()); - - ret = ReflectTools.findClosestCommonClassLoaderAncestor(null, null); - Assert.assertFalse(ret.isPresent()); - } - - @Test - public void hasAnnotation_annotationPresents_returnsTrue() { - Assert.assertTrue(ReflectTools.hasAnnotation(ClassWithAnnotation.class, - TestAnnotation.class.getName())); - } - - @Test - public void hasAnnotation_annotationIsAbsent_returnsFalse() { - Assert.assertFalse(ReflectTools.hasAnnotation( - ClassWithoutAnnotation.class, TestAnnotation.class.getName())); - } - - @Test - public void hasAnnotationWithSimpleName_annotationPresents_returnsTrue() { - Assert.assertTrue(ReflectTools.hasAnnotationWithSimpleName( - ClassWithAnnotation.class, - TestAnnotation.class.getSimpleName())); - } - - @Test - public void hasAnnotationWithSimpleName_annotationIsAbsent_returnsFalse() { - Assert.assertFalse(ReflectTools.hasAnnotationWithSimpleName( - ClassWithoutAnnotation.class, - TestAnnotation.class.getSimpleName())); - } - - @Test - public void getAnnotationMethodValue_annotaitonHasMethod_theValueIsReturned() { - Assert.assertEquals("foo", ReflectTools.getAnnotationMethodValue( - ClassWithAnnotation.class.getAnnotation(TestAnnotation.class), - "value")); - } - - @Test(expected = IllegalArgumentException.class) - public void getAnnotationMethodValue_annotationHasNoMethod_throws() { - ReflectTools.getAnnotationMethodValue( - ClassWithAnnotation.class.getAnnotation(TestAnnotation.class), - "foo"); - } - - @Test - public void getAnnotation_annotationPresents_returnsAnnotation() { - Optional annotation = ReflectTools.getAnnotation( - ClassWithAnnotation.class, TestAnnotation.class.getName()); - Assert.assertTrue(annotation.isPresent()); - Assert.assertEquals( - ClassWithAnnotation.class.getAnnotation(TestAnnotation.class), - annotation.get()); - } - - @Test - public void getAnnotation_annotationIsAbsent_returnsEmpty() { - Optional annotation = ReflectTools.getAnnotation( - ClassWithoutAnnotation.class, TestAnnotation.class.getName()); - Assert.assertFalse(annotation.isPresent()); - } - - @Test - public void intefaceShouldNotBeInstantiableService() { - assertFalse(ReflectTools.isInstantiableService(TestInterface.class)); - } - - @Test - public void abstractClassShouldNotBeInstantiableService() { - assertFalse( - ReflectTools.isInstantiableService(TestAbstractClass.class)); - } - - @Test - public void nonPublicClassShouldNotBeInstantiableService() { - assertFalse( - ReflectTools.isInstantiableService(TestProtectedClass.class)); - assertFalse(ReflectTools - .isInstantiableService(TestPackageProtectedClass.class)); - assertFalse(ReflectTools.isInstantiableService(TestPrivateClass.class)); - } - - @Test - public void ClassWithoutNonArgConstructorShouldNotBeInstantiableService() { - assertFalse(ReflectTools - .isInstantiableService(TestNoNonArgConstructorClass.class)); - } - - @Test - public void nonStaticInnerClassShouldNotBeInstantiableService() { - assertFalse( - ReflectTools.isInstantiableService(NonStaticInnerClass.class)); - } - - @Test - public void privateInnerClassShouldNotBeInstantiableService() { - assertFalse( - ReflectTools.isInstantiableService(PrivateInnerClass.class)); - } - - @Test - public void normalSericieShouldBeInstantiableService() { - assertTrue(ReflectTools.isInstantiableService(NormalService.class)); - } - - private Class createProxyClass(Class originalClass) { - return new ByteBuddy().subclass(originalClass).make() - .load(originalClass.getClassLoader(), - ClassLoadingStrategy.Default.WRAPPER) - .getLoaded(); - } - - private void assertError(String expectedError, Class cls) { - try { - ReflectTools.createInstance(cls); - Assert.fail("Creation should cause an exception"); - } catch (IllegalArgumentException re) { - Assert.assertEquals(String.format(expectedError, cls.getName()), - re.getMessage()); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectionCacheTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/ReflectionCacheTest.java deleted file mode 100644 index 4eafebacc18..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/ReflectionCacheTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import java.lang.ref.WeakReference; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.tests.util.TestUtil; - -public class ReflectionCacheTest { - - @Test - public void generateCachedValues() { - AtomicInteger count = new AtomicInteger(); - - ReflectionCache cache = new ReflectionCache<>( - type -> count.incrementAndGet()); - - Assert.assertEquals(0, count.get()); - - Assert.assertEquals(1, cache.get(Object.class).intValue()); - Assert.assertEquals(2, cache.get(String.class).intValue()); - - Assert.assertEquals(1, cache.get(Object.class).intValue()); - - Assert.assertEquals(2, count.get()); - } - - @Test - public void cacheContains() { - ReflectionCache cache = new ReflectionCache<>( - type -> type); - - Assert.assertFalse(cache.contains(Object.class)); - - cache.get(Object.class); - Assert.assertTrue(cache.contains(Object.class)); - Assert.assertFalse(cache.contains(String.class)); - } - - @Test - public void cacheClear() { - ReflectionCache cache = new ReflectionCache<>( - type -> type); - - cache.get(Object.class); - Assert.assertTrue(cache.contains(Object.class)); - - cache.clear(); - Assert.assertFalse(cache.contains(Object.class)); - } - - @Test - public void clearAll() { - ReflectionCache cache1 = new ReflectionCache<>( - type -> type); - ReflectionCache cache2 = new ReflectionCache<>( - type -> type); - - cache1.get(Object.class); - cache2.get(Object.class); - - ReflectionCache.clearAll(); - - Assert.assertFalse(cache1.contains(Object.class)); - Assert.assertFalse(cache2.contains(Object.class)); - } - - @Test - public void cacheIsGarbageCollected() throws InterruptedException { - ReflectionCache cache1 = new ReflectionCache<>( - type -> type); - WeakReference> ref = new WeakReference<>( - cache1); - - cache1 = null; - Assert.assertTrue(TestUtil.isGarbageCollected(ref)); - } - - @Test - public void cacheIsClearedAfterGc() throws InterruptedException { - ReflectionCache cache = new ReflectionCache<>( - type -> type); - cache.get(Object.class); - - // Ensure garbage is collected before clearing - TestUtil.isGarbageCollected(new WeakReference<>(new Object())); - - ReflectionCache.clearAll(); - - Assert.assertFalse(cache.contains(Object.class)); - } - - @Test - public void currentInstancesNotAvailable() { - String currentString = "My string"; - CurrentInstance.set(String.class, currentString); - - ReflectionCache cache = new ReflectionCache<>( - type -> type.getSimpleName() + ": " - + CurrentInstance.get(String.class)); - - try { - String result = cache.get(Object.class); - - Assert.assertEquals("Current instance should not be in the result", - "Object: null", result); - Assert.assertEquals( - "Current instance should be preserved after running", - currentString, CurrentInstance.get(String.class)); - } finally { - CurrentInstance.set(String.class, null); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/ResponseWriterTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/ResponseWriterTest.java deleted file mode 100644 index 326f415fd2c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/ResponseWriterTest.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; -import java.util.zip.GZIPOutputStream; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import com.vaadin.external.apache.commons.fileupload2.MultipartStream; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletOutputStream; -import jakarta.servlet.WriteListener; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -/** - * @author Vaadin Ltd - * @since 1.0. - */ -public class ResponseWriterTest { - private static final String PATH_JS = "/static/file.js"; - private static final String PATH_GZ = "/static/file.js.gz"; - private static final String PATH_BR = "/static/file.js.br"; - private static final String CLASS_PATH_JS = "/VAADIN/build/file.js"; - private static final String CLASS_PATH_GZ = "/VAADIN/build/file.js.gz"; - private static final String FAULTY_CLASS_PATH_JS = "/VAADIN/config/file.js"; - private static final String FAULTY_CLASS_PATH_GZ = "/VAADIN/config/file.js.gz"; - - private static final byte[] fileJsContents = "File.js contents" - .getBytes(StandardCharsets.UTF_8); - private static final byte[] fileJsGzippedContents = gzip(fileJsContents); - // Dummy contents since we don't have a brotli encoder on the test - // classpath - private static final byte[] fileJsBrotliContents = "Fake brotli".getBytes(); - - private static final Map pathToUrl = new HashMap<>(); - static { - pathToUrl.put(PATH_JS, - createFileURLWithDataAndLength(PATH_JS, fileJsContents)); - pathToUrl.put(PATH_GZ, - createFileURLWithDataAndLength(PATH_GZ, fileJsGzippedContents)); - pathToUrl.put(PATH_BR, - createFileURLWithDataAndLength(PATH_BR, fileJsBrotliContents)); - pathToUrl.put(CLASS_PATH_JS, - createFileURLWithDataAndLength(CLASS_PATH_JS, fileJsContents)); - pathToUrl.put(CLASS_PATH_GZ, createFileURLWithDataAndLength( - CLASS_PATH_GZ, fileJsGzippedContents)); - pathToUrl.put(FAULTY_CLASS_PATH_JS, createFileURLWithDataAndLength( - FAULTY_CLASS_PATH_JS, fileJsContents)); - pathToUrl.put(FAULTY_CLASS_PATH_GZ, createFileURLWithDataAndLength( - FAULTY_CLASS_PATH_GZ, fileJsGzippedContents)); - } - - private ServletContext servletContext; - private HttpServletRequest request; - private HttpServletResponse response; - private AtomicLong responseContentLength; - private OverrideableResponseWriter responseWriter; - - private static class OverrideableResponseWriter extends ResponseWriter { - private Boolean overrideAcceptsGzippedResource; - private Boolean overrideAcceptsBrotliResource; - - public OverrideableResponseWriter( - DeploymentConfiguration deploymentConfiguration) { - super(deploymentConfiguration); - } - - @Override - protected boolean acceptsGzippedResource(HttpServletRequest request) { - if (overrideAcceptsGzippedResource != null) { - return overrideAcceptsGzippedResource; - } - return super.acceptsGzippedResource(request); - } - - @Override - protected boolean acceptsBrotliResource(HttpServletRequest request) { - if (overrideAcceptsBrotliResource != null) { - return overrideAcceptsBrotliResource.booleanValue(); - } - return super.acceptsBrotliResource(request); - } - } - - public static class CapturingServletOutputStream - extends ServletOutputStream { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - @Override - public void write(int b) throws IOException { - baos.write(b); - } - - @Override - public void setWriteListener(WriteListener writeListener) { - } - - @Override - public boolean isReady() { - return true; - } - - public byte[] getOutput() { - return baos.toByteArray(); - } - }; - - @Before - public void setUp() { - MockDeploymentConfiguration deploymentConfiguration = new MockDeploymentConfiguration(); - deploymentConfiguration.setBrotli(true); - - responseWriter = new OverrideableResponseWriter( - deploymentConfiguration); - servletContext = Mockito.mock(ServletContext.class); - request = Mockito.mock(HttpServletRequest.class); - Mockito.when(request.getServletContext()).thenReturn(servletContext); - // No header == getDateHeader returns -1 (Mockito default is 0) - Mockito.when(request.getDateHeader(ArgumentMatchers.anyString())) - .thenReturn(-1L); - - response = Mockito.mock(HttpServletResponse.class); - responseContentLength = new AtomicLong(-1L); - Mockito.doAnswer(invocation -> { - responseContentLength.set((long) invocation.getArguments()[0]); - return null; - }).when(response).setContentLengthLong(ArgumentMatchers.anyLong()); - } - - @Test - public void contentType() { - AtomicReference contentType = new AtomicReference<>(null); - Mockito.doAnswer(invocation -> { - contentType.set((String) invocation.getArguments()[0]); - return null; - }).when(response).setContentType(ArgumentMatchers.anyString()); - - Mockito.when(servletContext.getMimeType("/file.png")) - .thenReturn("image/png"); - - responseWriter.writeContentType("/file.png", request, response); - - Assert.assertEquals("image/png", contentType.get()); - } - - @Test - public void noContentType() { - AtomicReference contentType = new AtomicReference<>(null); - Mockito.doAnswer(invocation -> { - contentType.set((String) invocation.getArguments()[0]); - return null; - }).when(response).setContentType(ArgumentMatchers.anyString()); - - Mockito.when(servletContext.getMimeType("/file")).thenReturn(null); - - responseWriter.writeContentType("/file", request, response); - - Assert.assertNull(contentType.get()); - } - - @Test - public void acceptsGzippedResource() { - Assert.assertTrue(acceptsGzippedResource("compress, gzip")); - Assert.assertTrue(acceptsGzippedResource("brotli, gzip")); - Assert.assertTrue(acceptsGzippedResource("gzip")); - Assert.assertTrue(acceptsGzippedResource("gzip;")); - Assert.assertTrue(acceptsGzippedResource("gzip;q")); - Assert.assertFalse(acceptsGzippedResource("compress; q=1 , gzip;q=0")); - Assert.assertFalse(acceptsGzippedResource("")); - Assert.assertFalse(acceptsGzippedResource("compress")); - - Assert.assertTrue( - acceptsGzippedResource("compress;q = 0.5, gzip;q=0.6")); - Assert.assertTrue( - acceptsGzippedResource("gzip;q=1.0, identity;q=0.5, *;q=0")); - Assert.assertTrue(acceptsGzippedResource("*")); - Assert.assertTrue(acceptsGzippedResource("*;q=0;gzip")); - Assert.assertFalse(acceptsGzippedResource("*;q=0")); - Assert.assertFalse(acceptsGzippedResource("*;q=0.0")); - Assert.assertFalse(acceptsGzippedResource("*;q=0.00")); - Assert.assertFalse(acceptsGzippedResource("*;q=0.000")); - } - - private boolean acceptsGzippedResource(String acceptEncodingHeader) { - Mockito.when(request.getHeader("Accept-Encoding")) - .thenReturn(acceptEncodingHeader); - return responseWriter.acceptsGzippedResource(request); - } - - @Test - public void acceptsBrotliResource() { - // Not testing all the same cases as for gzip since most of those - // variants are effectively testing the same parser functionality - Assert.assertTrue(acceptsBrotliResource("compress, brotli")); - Assert.assertFalse(acceptsBrotliResource("gzip")); - - Assert.assertTrue( - acceptsBrotliResource("compress;q = 0.5, brotli;q=0.6")); - Assert.assertTrue(acceptsBrotliResource("*")); - Assert.assertFalse(acceptsBrotliResource("*;q=0")); - } - - private boolean acceptsBrotliResource(String acceptEncodingHeader) { - Mockito.when(request.getHeader("Accept-Encoding")) - .thenReturn(acceptEncodingHeader); - return responseWriter.acceptsBrotliResource(request); - } - - @Test - public void writeDataGzipped() throws IOException { - responseWriter.overrideAcceptsGzippedResource = true; - - makePathsAvailable(PATH_JS, PATH_GZ); - - assertResponse(fileJsGzippedContents); - } - - @Test - public void writeDataGzippedClassPathResource() throws IOException { - responseWriter.overrideAcceptsGzippedResource = true; - - makePathsAvailable(CLASS_PATH_JS); - makeClassPathAvailable(CLASS_PATH_GZ); - - assertResponse(CLASS_PATH_JS, fileJsGzippedContents); - } - - @Test - public void writeDataNotGzippedClassPathNotAcceptedPath() - throws IOException { - responseWriter.overrideAcceptsGzippedResource = true; - - makePathsAvailable(FAULTY_CLASS_PATH_JS); - makeClassPathAvailable(FAULTY_CLASS_PATH_GZ); - - assertResponse(FAULTY_CLASS_PATH_JS, fileJsContents); - } - - @Test - public void writeDataNoGzippedVersion() throws IOException { - responseWriter.overrideAcceptsGzippedResource = true; - - makePathsAvailable(PATH_JS); - - assertResponse(fileJsContents); - } - - @Test - public void writeDataBrowserDoesNotAcceptGzippedVersion() - throws IOException { - responseWriter.overrideAcceptsGzippedResource = false; - - makePathsAvailable(PATH_JS, PATH_GZ); - - assertResponse(fileJsContents); - } - - @Test - public void writeDataBrotli() throws IOException { - responseWriter.overrideAcceptsBrotliResource = Boolean.TRUE; - - // Enable gzip as well to see that Brotli takes priority over gzip in - // case both are accepted and available - responseWriter.overrideAcceptsGzippedResource = Boolean.TRUE; - - makePathsAvailable(PATH_JS, PATH_GZ, PATH_BR); - - assertResponse(fileJsBrotliContents); - } - - @Test - public void writeDataNoBrotliVersion() throws IOException { - responseWriter.overrideAcceptsBrotliResource = Boolean.TRUE; - - makePathsAvailable(PATH_JS); - - assertResponse(fileJsContents); - } - - @Test - public void writeDataBrowserDoesNotAcceptBrotli() throws IOException { - responseWriter.overrideAcceptsBrotliResource = Boolean.FALSE; - - makePathsAvailable(PATH_JS, PATH_BR); - - assertResponse(fileJsContents); - } - - @Test - public void writeDataBrotliDisabled() throws IOException { - MockDeploymentConfiguration configuration = new MockDeploymentConfiguration(); - configuration.setBrotli(false); - - responseWriter = new OverrideableResponseWriter(configuration); - - responseWriter.overrideAcceptsBrotliResource = Boolean.TRUE; - - makePathsAvailable(PATH_JS, PATH_BR); - - assertResponse(fileJsContents); - } - - @Test - public void writeByteRangeFromStart() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=0-1")); - - assertResponse(Arrays.copyOfRange(fileJsContents, 0, 2)); - assertResponseHeaders(new Pair<>("Accept-Ranges", "bytes"), new Pair<>( - "Content-Range", "bytes 0-1/" + fileJsContents.length)); - Assert.assertEquals(2L, responseContentLength.get()); - assertStatus(206); - } - - @Test - public void writeByteRangeSubset() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=10-11")); - assertResponse(Arrays.copyOfRange(fileJsContents, 10, 12)); - assertResponseHeaders(new Pair<>("Accept-Ranges", "bytes"), new Pair<>( - "Content-Range", "bytes 10-11/" + fileJsContents.length)); - Assert.assertEquals(2L, responseContentLength.get()); - assertStatus(206); - } - - @Test - public void writeByteRangeStartOmitted() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=-10")); - assertResponse(Arrays.copyOfRange(fileJsContents, 0, 11)); - assertResponseHeaders(new Pair<>("Accept-Ranges", "bytes"), new Pair<>( - "Content-Range", "bytes 0-10/" + fileJsContents.length)); - Assert.assertEquals(11L, responseContentLength.get()); - assertStatus(206); - } - - @Test - public void writeByteRangeEndOmitted() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=10-")); - assertResponse( - Arrays.copyOfRange(fileJsContents, 10, fileJsContents.length)); - assertResponseHeaders(new Pair<>("Accept-Ranges", "bytes"), new Pair<>( - "Content-Range", "bytes 10-15/" + fileJsContents.length)); - Assert.assertEquals(6L, responseContentLength.get()); - assertStatus(206); - } - - @Test - public void writeByteRangePastFileSize() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=10-100000")); - assertResponse( - Arrays.copyOfRange(fileJsContents, 10, fileJsContents.length)); - assertResponseHeaders(new Pair<>("Accept-Ranges", "bytes"), new Pair<>( - "Content-Range", "bytes 10-15/" + fileJsContents.length)); - Assert.assertEquals(6L, responseContentLength.get()); - assertStatus(206); - } - - @Test - public void writeByteRangeEmpty() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=10-9")); - assertResponse(new byte[] {}); - assertStatus(416); - } - - @Test - public void writeByteRangeMalformed() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "f-d-d___")); - assertResponse(new byte[] {}); - assertStatus(416); - } - - @Test - public void writeByteRangeBothEndsOpen() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "-")); - assertResponse(new byte[] {}); - assertStatus(416); - } - - @Test - public void writeByteRangeMultiPartSequential() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=1-4, 5-6, 10-12")); - // "File.js contents" - // ^0123456789ABCDEF^ - assertMultipartResponse(PATH_JS, Arrays.asList( - new Pair<>(new String[] { "Content-Range: bytes 1-4/16" }, - "ile.".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 5-6/16" }, - "js".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 10-12/16" }, - "nte".getBytes()))); - assertStatus(206); - } - - @Test - public void writeByteRangeMultiPartNonSequential() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=10-12, 1-4, 5-6")); - // "File.js contents" - // ^0123456789ABCDEF^ - assertMultipartResponse(PATH_JS, - Arrays.asList( - new Pair<>( - new String[] { - "Content-Range: bytes 10-12/16" }, - "nte".getBytes()), - new Pair<>( - new String[] { "Content-Range: bytes 1-4/16" }, - "ile.".getBytes()), - new Pair<>( - new String[] { "Content-Range: bytes 5-6/16" }, - "js".getBytes()))); - assertStatus(206); - } - - @Test - public void writeByteRangeMultiPartOverlapping() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=0-15, 1-4")); - // "File.js contents" - // ^0123456789ABCDEF^ - assertMultipartResponse(PATH_JS, Arrays.asList( - new Pair<>(new String[] { "Content-Range: bytes 0-15/16" }, - "File.js contents".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 1-4/16" }, - "ile.".getBytes()))); - assertStatus(206); - } - - @Test - public void writeByteRangeMultiPartTooManyRequested() throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", - "bytes=0-0, 0-0, 1-1, 2-2, 3-3, 4-4, 5-5, 6-6, 7-7, 8-8, 9-9, 10-10, 11-11, 12-12, 13-13, 14-14, 15-15, 16-16")); - // "File.js contents" - // ^0123456789ABCDEF^ - assertMultipartResponse(PATH_JS, Arrays.asList( - new Pair<>(new String[] { "Content-Range: bytes 0-0/16" }, - "F".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 0-0/16" }, - "F".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 1-1/16" }, - "i".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 2-2/16" }, - "l".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 3-3/16" }, - "e".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 4-4/16" }, - ".".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 5-5/16" }, - "j".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 6-6/16" }, - "s".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 7-7/16" }, - " ".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 8-8/16" }, - "c".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 9-9/16" }, - "o".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 10-10/16" }, - "n".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 11-11/16" }, - "t".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 12-12/16" }, - "e".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 13-13/16" }, - "n".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 14-14/16" }, - "t".getBytes()))); - assertStatus(206); - } - - @Test - public void writeByteRangeMultiPartTooManyOverlappingRequested() - throws IOException { - makePathsAvailable(PATH_JS); - mockRequestHeaders(new Pair<>("Range", "bytes=2-4, 0-4, 3-14")); - // "File.js contents" - // ^0123456789ABCDEF^ - assertMultipartResponse(PATH_JS, Arrays.asList( - new Pair<>(new String[] { "Content-Range: bytes 2-4/16" }, - "le.".getBytes()), - new Pair<>(new String[] { "Content-Range: bytes 0-4/16" }, - "File.".getBytes()))); - assertStatus(206); - } - - private void assertResponse(byte[] expectedResponse) throws IOException { - assertResponse(PATH_JS, expectedResponse); - } - - private void assertResponse(String path, byte[] expectedResponse) - throws IOException { - CapturingServletOutputStream out = new CapturingServletOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(out); - responseWriter.writeResponseContents(path, pathToUrl.get(path), request, - response); - - Assert.assertArrayEquals(expectedResponse, out.getOutput()); - Assert.assertEquals(expectedResponse.length, - responseContentLength.get()); - } - - private void assertMultipartResponse(String path, - List> expectedHeadersAndBytes) - throws IOException { - CapturingServletOutputStream out = new CapturingServletOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(out); - - AtomicReference contentType = new AtomicReference<>(null); - Mockito.doAnswer(invocation -> { - contentType.set((String) invocation.getArguments()[0]); - return null; - }).when(response).setContentType(ArgumentMatchers.anyString()); - - responseWriter.writeResponseContents(path, pathToUrl.get(path), request, - response); - final byte[] output = out.getOutput(); - - Assert.assertNotNull(contentType.get()); - Assert.assertTrue(contentType.get() - .startsWith("multipart/byteranges; boundary=")); - - String boundary = contentType.get() - .substring(contentType.get().indexOf("=") + 1); - - @SuppressWarnings("deprecation") - MultipartStream mps = new MultipartStream( - new ByteArrayInputStream(output), boundary.getBytes()); - for (Pair expected : expectedHeadersAndBytes) { - String[] expectedHeaders = expected.getFirst(); - String actualHeaders = mps.readHeaders(); - for (String expectedHeader : expectedHeaders) { - Assert.assertTrue( - String.format("Headers:\n%s\ndid not contain:\n%s", - actualHeaders, expectedHeader), - actualHeaders.contains(expectedHeader)); - } - byte[] expectedBytes = expected.getSecond(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - mps.readBodyData(outputStream); - byte[] bytes = outputStream.toByteArray(); - Assert.assertArrayEquals(expectedBytes, bytes); - } - - // check that there are no excess parts - try { - mps.readHeaders(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - mps.readBodyData(outputStream); - Assert.assertTrue("excess bytes in multipart response", - outputStream.toByteArray().length == 0); - } catch (IOException ioe) { - // all is well, stream ended - } - } - - private void assertStatus(int status) { - Mockito.verify(response).setStatus(status); - } - - private void makePathsAvailable(String... paths) - throws MalformedURLException { - for (String path : paths) { - URL url = pathToUrl.get(path); - if (url == null) { - throw new IllegalArgumentException("Unsupported path: " + path); - } - Mockito.when(servletContext.getResource(path)).thenReturn(url); - } - } - - private void makeClassPathAvailable(String... paths) { - for (String path : paths) { - URL url = pathToUrl.get(path); - if (url == null) { - throw new IllegalArgumentException("Unsupported path: " + path); - } - ClassLoader classLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletContext.getClassLoader()) - .thenReturn(classLoader); - Mockito.when( - classLoader.getResource("META-INF/VAADIN/webapp" + path)) - .thenReturn(url); - } - } - - @SafeVarargs - private final void assertResponseHeaders(Pair... headers) { - for (Pair header : headers) { - Mockito.verify(response).setHeader(header.getFirst(), - header.getSecond()); - } - } - - @SafeVarargs - private final void mockRequestHeaders(Pair... headers) { - for (Pair header : headers) { - Mockito.when(request.getHeader(header.getFirst())) - .thenReturn(header.getSecond()); - Mockito.when(request.getHeaders(header.getFirst())) - .thenReturn(Collections.enumeration( - Collections.singleton(header.getSecond()))); - } - Mockito.when(request.getHeaderNames()) - .thenReturn(Collections.enumeration(Arrays.stream(headers) - .map(Pair::getFirst).collect(Collectors.toList()))); - } - - private static byte[] gzip(byte[] input) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (GZIPOutputStream stream = new GZIPOutputStream(baos)) { - stream.write(input); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - return baos.toByteArray(); - } - - private static URL createFileURLWithDataAndLength(String name, - byte[] data) { - return createFileURLWithDataAndLength(name, data, -1); - } - - private static URL createFileURLWithDataAndLength(String name, byte[] data, - long lastModificationTime) { - try { - return new URL("file", "", -1, name, new URLStreamHandler() { - @Override - protected URLConnection openConnection(URL u) - throws IOException { - URLConnection connection = Mockito - .mock(URLConnection.class); - Mockito.when(connection.getInputStream()) - .thenReturn(new ByteArrayInputStream(data)); - Mockito.when(connection.getContentLengthLong()) - .thenReturn((long) data.length); - Mockito.when(connection.getLastModified()) - .thenReturn(lastModificationTime); - return connection; - } - }); - } catch (MalformedURLException e) { - throw new UncheckedIOException(e); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/StateNodeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/StateNodeTest.java deleted file mode 100644 index c1aa29087f6..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/StateNodeTest.java +++ /dev/null @@ -1,1676 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.NodeAttachChange; -import com.vaadin.flow.internal.change.NodeChange; -import com.vaadin.flow.internal.change.NodeDetachChange; -import com.vaadin.flow.internal.nodefeature.ElementAttributeMap; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; -import com.vaadin.flow.internal.nodefeature.ElementClassList; -import com.vaadin.flow.internal.nodefeature.ElementData; -import com.vaadin.flow.internal.nodefeature.ElementPropertyMap; -import com.vaadin.flow.internal.nodefeature.InertData; -import com.vaadin.flow.internal.nodefeature.NodeFeature; -import com.vaadin.flow.shared.Registration; - -public class StateNodeTest { - - private static class TestStateNode extends StateNode { - private int i = -1; - - public TestStateNode() { - super(ElementChildrenList.class); - } - - public void setData(int data) { - i = data; - } - - public int getData() { - return i; - } - - @Override - public String toString() { - return Integer.toString(getData()); - } - } - - private static class TestStateTree extends StateTree { - - private Set dirtyNodes; - - public TestStateTree() { - super(new UI().getInternals(), ElementChildrenList.class); - } - - @Override - public void markAsDirty(StateNode node) { - super.markAsDirty(node); - if (dirtyNodes == null) { - dirtyNodes = new HashSet<>(); - } - dirtyNodes.add(node); - } - - } - - @Test - public void newNodeState() { - StateNode node = createEmptyNode(); - - NodeOwner owner = node.getOwner(); - - Assert.assertNotNull("New node should have an owner", owner); - - Assert.assertEquals("New node shold have unassigned id", -1, - node.getId()); - - Assert.assertFalse("Node should not be attached", node.isAttached()); - } - - @Test - public void nodeContainsDefinedFeatures() { - StateNode node = new StateNode(ElementData.class); - - Assert.assertTrue("Should have feature defined in constructor", - node.hasFeature(ElementData.class)); - - ElementData feature = node.getFeature(ElementData.class); - - Assert.assertNotNull("Existing feature should also be available", - feature); - - Assert.assertFalse( - "Should not have a feature that wasn't defined in constructor", - node.hasFeature(ElementPropertyMap.class)); - } - - @Test(expected = IllegalStateException.class) - public void getMissingFeatureThrows() { - StateNode node = new StateNode(ElementData.class); - node.getFeature(ElementPropertyMap.class); - } - - @Test - public void attachDetachChangeCollection() { - StateNode node = createEmptyNode(); - - List changes = new ArrayList<>(); - Consumer collector = changes::add; - - node.collectChanges(collector); - - Assert.assertTrue("Node should have no changes", changes.isEmpty()); - - // Attach node - setParent(node, createStateTree().getRootNode()); - - node.collectChanges(collector); - - Assert.assertEquals("Should have 1 change", 1, changes.size()); - Assert.assertTrue("Should have attach change", - changes.get(0) instanceof NodeAttachChange); - changes.clear(); - - node.collectChanges(collector); - Assert.assertTrue("Node should have no changes", changes.isEmpty()); - - // Detach node - setParent(node, null); - - node.collectChanges(collector); - Assert.assertEquals("Should have 1 change", 1, changes.size()); - Assert.assertTrue("Should have detach change", - changes.get(0) instanceof NodeDetachChange); - changes.clear(); - } - - @Test - public void appendChildBeforeParent() { - StateNode parent = createParentNode("parent"); - StateNode child = createParentNode("child"); - StateNode grandchild = createEmptyNode("grandchild"); - - StateNode root = createStateTree().getRootNode(); - - setParent(grandchild, child); - setParent(child, parent); - setParent(parent, root); - - Assert.assertNotEquals(-1, parent.getId()); - Assert.assertNotEquals(-1, child.getId()); - Assert.assertNotEquals(-1, grandchild.getId()); - } - - @Test - public void appendParentBeforeChild() { - StateNode parent = createParentNode("parent"); - StateNode child = createParentNode("child"); - StateNode grandchild = createEmptyNode("grandchild"); - - StateNode root = createStateTree().getRootNode(); - - setParent(parent, root); - setParent(child, parent); - setParent(grandchild, child); - - Assert.assertNotEquals(-1, parent.getId()); - Assert.assertNotEquals(-1, child.getId()); - Assert.assertNotEquals(-1, grandchild.getId()); - } - - @Test(expected = IllegalStateException.class) - public void setChildAsParent() { - StateNode parent = createParentNode("parent"); - StateNode child = createParentNode("child"); - - setParent(child, parent); - setParent(parent, child); - } - - @Test(expected = IllegalStateException.class) - public void setAsOwnParent() { - StateNode parent = createParentNode("parent"); - - setParent(parent, parent); - } - - /** - * Test for #252: stack overflow exception - * - * Firefox won't show elements nested more than 200 levels deep, thus makes - * no sense to test insane depth. - */ - @Test - public void recursiveTreeNavigation_resilienceInDepth() { - TestStateNode childOfRoot = new TestStateNode(); - TestStateNode node = createTree(childOfRoot, 3000); - StateTree tree = createStateTree(); - - setParent(childOfRoot, tree.getRootNode()); - - Set set = IntStream.range(-1, node.getData() + 1).boxed() - .collect(Collectors.toSet()); - childOfRoot.visitNodeTree(n -> visit((TestStateNode) n, tree, set)); - Assert.assertTrue(set.isEmpty()); - } - - /** - * Test for #252: stack overflow exception - * - * Firefox won't show elements nested more than 200 levels deep, thus makes - * no sense to test insane depth. - */ - @Test - public void recursiveTreeNavigation_resilienceInSize() { - TestStateNode childOfRoot = new TestStateNode(); - int count = 300; - StateNode node = createTree(childOfRoot, count); - while (node.getParent() != null) { - node = node.getParent(); - for (int i = 1; i < 50; i++) { - TestStateNode child = new TestStateNode(); - setParent(child, node); - child.setData(count); - count++; - } - } - StateTree tree = createStateTree(); - - setParent(childOfRoot, tree.getRootNode()); - - Set set = IntStream.range(-1, count).boxed() - .collect(Collectors.toSet()); - childOfRoot.visitNodeTree(n -> visit((TestStateNode) n, - (StateTree) childOfRoot.getOwner(), set)); - Assert.assertTrue(set.isEmpty()); - } - - @Test - public void nodeTreeOnAttach_bottomUpTraversing_correctOrder() { - TestStateNode root = new TestStateNode(); - LinkedList data = new LinkedList<>(); - data.add(0); - root.setData(0); - int count = 1; - - for (int i = 0; i < 5; i++) { - TestStateNode childOfRoot = new TestStateNode(); - childOfRoot.setData(count); - data.add(count); - if (i % 2 == 0) { - for (int j = 0; j < 5; j++) { - TestStateNode child = new TestStateNode(); - setParent(child, childOfRoot); - child.setData(count); - data.add(count); - count++; - } - } - setParent(childOfRoot, root); - } - - root.visitNodeTreeBottomUp(node -> Assert.assertEquals( - ((Integer) ((TestStateNode) node).getData()), - data.removeLast())); - } - - @Test - public void nodeTreeOnAttach_bottomUpTraversing_brokenParentInChildDoesNotEndInLoop() - throws NoSuchFieldException, IllegalAccessException { - // Set data is used to track the node during debug see - // TestStateNode.toString - TestStateNode root = new TestStateNode(); - root.setData(0); - List count = new ArrayList<>(); - - final Field parent = StateNode.class.getDeclaredField("parent"); - parent.setAccessible(true); - - TestStateNode childOfRoot = new TestStateNode(); - childOfRoot.setData(1); - - TestStateNode child = new TestStateNode(); - child.setData(2); - setParent(child, childOfRoot); - - parent.set(child, null); - - setParent(childOfRoot, root); - - root.visitNodeTreeBottomUp(node -> count.add(1)); - - Assert.assertEquals("Each node should be visited once", 3, - count.size()); - } - - @Test - public void attachListener_onSetParent_listenerTriggered() { - StateNode root = new TestStateTree().getRootNode(); - TestStateNode child = new TestStateNode(); - - Assert.assertFalse(child.isAttached()); - AtomicBoolean triggered = new AtomicBoolean(false); - - child.addAttachListener(() -> triggered.set(true)); - - setParent(child, root); - - Assert.assertTrue(triggered.get()); - } - - @Test - public void attachListener_listenerRemoved_listenerNotTriggered() { - StateNode root = new TestStateTree().getRootNode(); - TestStateNode child = new TestStateNode(); - - Assert.assertFalse(child.isAttached()); - AtomicBoolean triggered = new AtomicBoolean(false); - - Registration registrationHandle = child - .addAttachListener(() -> triggered.set(true)); - registrationHandle.remove(); - - setParent(child, root); - - Assert.assertFalse(triggered.get()); - } - - @Test - public void detachListener_onSetParent_listenerTriggered() { - StateNode root = new TestStateTree().getRootNode(); - TestStateNode child = new TestStateNode(); - - setParent(child, root); - Assert.assertTrue(child.isAttached()); - - AtomicBoolean triggered = new AtomicBoolean(false); - - child.addDetachListener(() -> triggered.set(true)); - - setParent(child, null); - - Assert.assertTrue("Detach listener was not triggered.", - triggered.get()); - } - - @Test - public void detachListener_listenerRemoved_listenerNotTriggered() { - StateNode root = new TestStateTree().getRootNode(); - TestStateNode child = new TestStateNode(); - - setParent(child, root); - Assert.assertTrue(child.isAttached()); - - AtomicBoolean triggered = new AtomicBoolean(false); - - Registration registrationHandle = child - .addDetachListener(() -> triggered.set(true)); - registrationHandle.remove(); - - setParent(child, null); - - Assert.assertFalse( - "Detach listener was triggered even though handler was removed.", - triggered.get()); - } - - @Test - public void detachListener_removesNode_notUnregisteredTwice() { - StateTree tree = createStateTree(); - StateNode root = createParentNode(""); - setParent(root, tree.getRootNode()); - - TestStateNode child = new TestStateNode(); - - setParent(child, root); - Assert.assertTrue(child.isAttached()); - - AtomicBoolean triggered = new AtomicBoolean(false); - - child.addDetachListener(() -> { - Assert.assertTrue( - "Child node should still have a parent and be been seen as attached", - child.isAttached()); - Assert.assertFalse("Child node should have been unregistered", - tree.hasNode(child)); - - child.setParent(null); - Assert.assertTrue("Child's parent should be null", - child.getParent() == null); - - triggered.set(true); - }); - - setParent(child, null); - - Assert.assertTrue("Detach listener was not triggered.", - triggered.get()); - } - - public static StateNode createEmptyNode() { - return createEmptyNode("Empty node"); - } - - public static StateNode createEmptyNode(String toString) { - return createTestNode(toString); - } - - public static StateNode createParentNode(String toString) { - return createTestNode(toString, ElementChildrenList.class); - } - - @SafeVarargs - public static StateNode createTestNode(String toString, - Class... features) { - return new StateNode(features) { - @Override - public String toString() { - if (toString != null) { - return toString; - } else { - return super.toString(); - } - } - - @Override - public boolean hasFeature( - Class featureType) { - // Inform that we don't have ElementData so that PropertyMap - // doesn't try to initialize an element for our test state node - if (featureType.isAssignableFrom(ElementData.class)) { - return false; - } - return super.hasFeature(featureType); - } - - }; - } - - public static void setParent(StateNode child, StateNode parent) { - if (parent == null) { - // Remove child - parent = child.getParent(); - - ElementChildrenList children = parent - .getFeature(ElementChildrenList.class); - children.remove(children.indexOf(child)); - } else { - // Add child - assert child.getParent() == null; - - ElementChildrenList children = parent - .getFeature(ElementChildrenList.class); - children.add(children.size(), child); - } - } - - /** - * Creates a tree with given {@code root} and {@code depth}. The resulting - * tree is just a chain. - *

- * Returns the leaf (last) node. - */ - private TestStateNode createTree(TestStateNode root, int depth) { - TestStateNode node = root; - for (int i = 0; i < depth; i++) { - TestStateNode child = new TestStateNode(); - child.setData(i); - node.getFeature(ElementChildrenList.class).add(0, child); - node = child; - } - return node; - } - - private void visit(TestStateNode node, StateTree tree, Set set) { - Assert.assertEquals(tree, node.getOwner()); - set.remove(node.getData()); - } - - private StateTree createStateTree() { - StateTree stateTree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - return stateTree; - } - - @Test - public void runWhenAttachedNodeNotAttached() { - StateTree tree = createStateTree(); - AtomicInteger commandRun = new AtomicInteger(0); - StateNode node = createEmptyNode(); - node.runWhenAttached(ui -> { - Assert.assertEquals(tree.getUI(), ui); - commandRun.incrementAndGet(); - }); - - Assert.assertEquals(0, commandRun.get()); - - setParent(node, tree.getRootNode()); - Assert.assertEquals(1, commandRun.get()); - setParent(node, null); - setParent(node, tree.getRootNode()); - Assert.assertEquals(1, commandRun.get()); - } - - @Test - public void runMultipleWhenAttachedNodeNotAttached() { - StateTree tree = createStateTree(); - AtomicInteger commandRun = new AtomicInteger(0); - StateNode node = createEmptyNode(); - node.runWhenAttached(ui -> { - Assert.assertEquals(tree.getUI(), ui); - commandRun.incrementAndGet(); - }); - node.runWhenAttached(ui -> { - Assert.assertEquals(tree.getUI(), ui); - commandRun.incrementAndGet(); - }); - - Assert.assertEquals(0, commandRun.get()); - - setParent(node, tree.getRootNode()); - Assert.assertEquals(2, commandRun.get()); - } - - @Test - public void runWhenAttachedNodeAttached() { - AtomicInteger commandRun = new AtomicInteger(0); - StateNode node = createEmptyNode(); - StateTree tree = createStateTree(); - setParent(node, tree.getRootNode()); - node.runWhenAttached(ui -> { - Assert.assertEquals(tree.getUI(), ui); - commandRun.incrementAndGet(); - }); - - Assert.assertEquals(1, commandRun.get()); - } - - @Test - public void requiredFeatures() { - StateNode stateNode = new StateNode( - Arrays.asList(ElementClassList.class, ElementPropertyMap.class), - ElementAttributeMap.class); - - Assert.assertTrue(stateNode.hasFeature(ElementClassList.class)); - Assert.assertTrue(stateNode.hasFeature(ElementPropertyMap.class)); - Assert.assertTrue(stateNode.hasFeature(ElementAttributeMap.class)); - - Assert.assertTrue(stateNode.isReportedFeature(ElementClassList.class)); - Assert.assertTrue( - stateNode.isReportedFeature(ElementPropertyMap.class)); - Assert.assertFalse( - stateNode.isReportedFeature(ElementAttributeMap.class)); - } - - @Test - public void collectChanges_initiallyActiveElement_sendOnlyDisalowFeatureChangesWhenInactive() { - StateNode stateNode = createTestNode("Active node", - ElementPropertyMap.class, ElementData.class); - - ElementData visibility = stateNode.getFeature(ElementData.class); - ElementPropertyMap properties = stateNode - .getFeature(ElementPropertyMap.class); - - TestStateTree tree = new TestStateTree(); - - // attach the node to be able to get changes - tree.getRootNode().getFeature(ElementChildrenList.class).add(0, - stateNode); - - assertCollectChanges_initiallyVisible(stateNode, properties, - isVisible -> { - visibility.setVisible(isVisible); - stateNode.updateActiveState(); - }); - } - - @Test - public void collectChanges_inertElement_inertChangesCollected() { - StateNode parent = createTestNode("Parent node", - ElementChildrenList.class, InertData.class); - StateNode child = createTestNode("Child node", - ElementChildrenList.class, InertData.class); - StateNode grandchild = createTestNode("Grandchild node", - InertData.class); - - new StateTree(new UI().getInternals(), ElementChildrenList.class, - InertData.class).getRootNode() - .getFeature(ElementChildrenList.class).add(0, parent); - parent.getFeature(ElementChildrenList.class).add(0, child); - child.getFeature(ElementChildrenList.class).add(0, grandchild); - - Assert.assertFalse(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - - parent.getFeature(InertData.class).setInertSelf(true); - - Assert.assertFalse(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - - parent.collectChanges(nodeChange -> { - }); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertTrue(grandchild.isInert()); - - child.getFeature(InertData.class).setIgnoreParentInert(true); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertTrue(grandchild.isInert()); - - // parent doesn't have any changes, nothing happens until child is - // collected - parent.collectChanges(nodeChange -> { - }); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertTrue(grandchild.isInert()); - - child.collectChanges(nodeChange -> { - }); - - Assert.assertTrue(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - - // change both but only collect parent -> changes cascaded - parent.getFeature(InertData.class).setInertSelf(false); - child.getFeature(InertData.class).setIgnoreParentInert(false); - - Assert.assertTrue(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - - parent.collectChanges(nodeChange -> { - }); - - Assert.assertFalse(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - } - - @Test - public void collectChanges_inertChildMoved_inertStateInherited() { - StateNode inertParent = createTestNode("Inert parent", - ElementChildrenList.class, InertData.class); - StateNode child = createTestNode("Child", InertData.class); - StateNode parent = createTestNode("Non-inert parent", - ElementChildrenList.class, InertData.class); - - final ElementChildrenList feature = new StateTree( - new UI().getInternals(), ElementChildrenList.class, - InertData.class).getRootNode() - .getFeature(ElementChildrenList.class); - feature.add(0, parent); - feature.add(1, inertParent); - inertParent.getFeature(ElementChildrenList.class).add(0, child); - - inertParent.getFeature(InertData.class).setInertSelf(true); - inertParent.collectChanges(node -> { - }); - - Assert.assertTrue(inertParent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertFalse(parent.isInert()); - - inertParent.getFeature(ElementChildrenList.class).remove(0); - parent.getFeature(ElementChildrenList.class).add(0, child); - - Assert.assertTrue(inertParent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(parent.isInert()); - - parent.getFeature(ElementChildrenList.class).remove(0); - inertParent.getFeature(ElementChildrenList.class).add(0, child); - - Assert.assertTrue(inertParent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertFalse(parent.isInert()); - } - - @Test - public void collectChanges_inactivateViaParent_initiallyActiveElement_sendOnlyDisalowFeatureChangesWhenInactive() { - StateNode stateNode = createTestNode("Active node", - ElementPropertyMap.class, ElementData.class); - - StateNode parent = createTestNode("Parent node", - ElementPropertyMap.class, ElementData.class, - ElementChildrenList.class); - - parent.getFeature(ElementChildrenList.class).add(0, stateNode); - - ElementData visibility = parent.getFeature(ElementData.class); - ElementPropertyMap properties = stateNode - .getFeature(ElementPropertyMap.class); - - TestStateTree tree = new TestStateTree(); - - // attach the node to be able to get changes - tree.getRootNode().getFeature(ElementChildrenList.class).add(0, parent); - - assertCollectChanges_initiallyVisible(stateNode, properties, - isVisible -> { - visibility.setVisible(isVisible); - parent.updateActiveState(); - }); - } - - @Test - public void collectChanges_initiallyInactiveElement_sendOnlyDisalowAndReportedFeatures_sendAllChangesWhenActive() { - Element element = ElementFactory.createAnchor(); - - StateNode stateNode = element.getNode(); - - ElementData visibility = stateNode.getFeature(ElementData.class); - ElementPropertyMap properties = stateNode - .getFeature(ElementPropertyMap.class); - - TestStateTree tree = new TestStateTree(); - - // attach the node to be able to get changes - tree.getRootNode().getFeature(ElementChildrenList.class).add(0, - stateNode); - - assertCollectChanges_initiallyInactive(stateNode, properties, - isVisible -> { - visibility.setVisible(isVisible); - stateNode.updateActiveState(); - }); - } - - @Test - public void collectChanges_initiallyInactiveViaParentElement_sendOnlyDisalowAndReportedFeatures_sendAllChangesWhenActive() { - Element element = ElementFactory.createAnchor(); - - StateNode stateNode = element.getNode(); - - StateNode parent = createTestNode("Parent node", - ElementPropertyMap.class, ElementData.class, - ElementChildrenList.class); - - parent.getFeature(ElementChildrenList.class).add(0, stateNode); - - ElementData visibility = parent.getFeature(ElementData.class); - - ElementPropertyMap properties = stateNode - .getFeature(ElementPropertyMap.class); - - TestStateTree tree = new TestStateTree(); - - // attach the node to be able to get changes - tree.getRootNode().getFeature(ElementChildrenList.class).add(0, parent); - - assertCollectChanges_initiallyInactive(stateNode, properties, - isVisible -> { - visibility.setVisible(isVisible); - parent.updateActiveState(); - }); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * ^ | - * |---------+ - * - * parent is attached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test c goes to a as a child when attach event is fired for b - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInAttachListener_firstAsParent_lastAsChild() { - assertAttachDetachEvents(createNodes(), "a", "c", false); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * | ^ - * +---------| - * - * parent is attached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test a goes to c as a child when attach event is fired for b - * Only one attach event is expected for a because it had not been yet attached when attach event for - * b is fired and it has been detached from parent and attached to c - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInAttachListener_lastAsParent_firstAsChild() { - assertAttachDetachEvents(createNodes(), "c", "a", true); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * | ^ - * +----| - * - * parent is attached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test a goes to b as a child when attach event is fired for c - * Only one attach event is expected for a because it had not been yet attached when attach event for - * c is fired and it has been detached from parent and attached to b - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInAttachListener_middleAsParent_firstAsChild() { - assertAttachDetachEvents(createNodes(), "b", "a", true); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * ^ | - * |----+ - * - * parent is attached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test b goes to a as a child when attach event is fired for c - * Only one attach event is expected for b because it had not been yet attached when attach event for - * c is fired and it has been detached from parent and attached to a/code> - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInAttachListener_firstAsParent_middleAsChild() { - assertAttachDetachEvents(createNodes(), "a", "b", true); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * ^ | - * |----+ - * - * parent is attached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test c goes to b as a child when attach event is fired for a - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInAttachListener_middleAsParent_lastAsChild() { - assertAttachDetachEvents(createNodes(), "b", "c", false); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * | ^ - * +----| - * - * parent is attached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test b goes to c as a child when attach event is fired for a - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInAttachListener_lastAsParent_middleAsChild() { - assertAttachDetachEvents(createNodes(), "c", "b", false); - } - - @Test - public void detachParent_detachFirstChildOnDetachLast_oneDetachEvent() { - TestStateTree tree = new TestStateTree(); - - StateNode childA = createEmptyNode("a"); - StateNode childB = createEmptyNode("b"); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - addChild(parent, childB); - - addChild(tree.getRootNode(), parent); - - AtomicInteger detachEvents = new AtomicInteger(); - childB.addDetachListener(() -> removeFromParent(childA)); - childA.addDetachListener(() -> detachEvents.incrementAndGet()); - - removeFromParent(parent); - - Assert.assertEquals(1, detachEvents.get()); - } - - @Test - public void detachParent_detachLastChildOnDetachFirst_oneDetachEvent() { - TestStateTree tree = new TestStateTree(); - - StateNode childA = createEmptyNode("a"); - StateNode childB = createEmptyNode("b"); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - addChild(parent, childB); - - addChild(tree.getRootNode(), parent); - - AtomicInteger detachEvents = new AtomicInteger(); - childA.addDetachListener(() -> removeFromParent(childA)); - childB.addDetachListener(() -> detachEvents.incrementAndGet()); - - removeFromParent(parent); - - Assert.assertEquals(1, detachEvents.get()); - } - - @Test - public void detachParent_appendChildOnDetach_noEvents() { - TestStateTree tree = new TestStateTree(); - - StateNode childA = createEmptyNode("a"); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - - addChild(tree.getRootNode(), parent); - - AtomicInteger events = new AtomicInteger(); - childA.addDetachListener(() -> { - StateNode b = createEmptyNode("b"); - b.addAttachListener(events::incrementAndGet); - b.addDetachListener(events::incrementAndGet); - addChild(parent, b); - }); - - removeFromParent(parent); - Assert.assertEquals(0, events.get()); - } - - @Test - public void detachParent_insertChildAsFirstOnDetach_noEvents() { - TestStateTree tree = new TestStateTree(); - - StateNode child = createEmptyNode("a"); - - StateNode parent = createParentNode("parent"); - - addChild(parent, child); - - addChild(tree.getRootNode(), parent); - - AtomicInteger events = new AtomicInteger(); - child.addDetachListener(() -> { - StateNode b = createEmptyNode("b"); - b.addAttachListener(events::incrementAndGet); - b.addDetachListener(events::incrementAndGet); - ElementChildrenList list = parent - .getFeature(ElementChildrenList.class); - list.add(0, b); - }); - - removeFromParent(parent); - Assert.assertEquals(0, events.get()); - } - - @Test - public void attachParent_detachFirstOnAttachLast_noEvents() { - TestStateTree tree = new TestStateTree(); - - StateNode childA = createEmptyNode("a"); - StateNode childB = createEmptyNode("b"); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - addChild(parent, childB); - - AtomicInteger events = new AtomicInteger(); - childB.addAttachListener(() -> { - removeFromParent(childA); - }); - - childA.addAttachListener(events::incrementAndGet); - childA.addDetachListener(events::incrementAndGet); - - addChild(tree.getRootNode(), parent); - - // events are fired from right to left, so b had been - // handled first and a had been detached before attach - // event has been fired for a. So no events for - // a - Assert.assertEquals(0, events.get()); - } - - @Test - public void attachParent_detachLastOnAttachFirst_attachDetachEvents() { - TestStateTree tree = new TestStateTree(); - - StateNode childA = createEmptyNode("a"); - StateNode childB = createEmptyNode("b"); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - addChild(parent, childB); - - childA.addAttachListener(() -> { - removeFromParent(childB); - }); - - List attachDetachEvents = new ArrayList<>(); - childB.addAttachListener(() -> attachDetachEvents.add(true)); - childB.addDetachListener(() -> attachDetachEvents.add(false)); - - addChild(tree.getRootNode(), parent); - - /* - * Here attach event for b had been fired first since it - * had been handled first. Then on attach event for a the - * b has been removed. So we should get also a detach - * event. - */ - Assert.assertEquals(2, attachDetachEvents.size()); - Assert.assertTrue(attachDetachEvents.get(0)); - Assert.assertFalse(attachDetachEvents.get(1)); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * ^ | - * |---------+ - * - * parent is detached, - * detach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test c goes to a as a child when detach event is fired for b - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInDetachListener_firstAsParent_lastAsChild() { - assertDetachAttachEvents(createNodes(), "a", "c"); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * | ^ - * +---------| - * - * parent is detached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test a goes to c as a child when detach event is fired for b - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInDetachListener_lastAsParent_firstAsChild() { - assertDetachAttachEvents(createNodes(), "c", "a"); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * | ^ - * +----| - * - * parent is detached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test a goes to b as a child when detach event is fired for c - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInDetachListener_middleAsParent_firstAsChild() { - assertDetachAttachEvents(createNodes(), "b", "a"); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * ^ | - * |----+ - * - * parent is detached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test b goes to a as a child when detach event is fired for c - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInDetachListener_firstAsParent_middleAsChild() { - assertDetachAttachEvents(createNodes(), "a", "b"); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * ^ | - * |----+ - * - * parent is detached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test c goes to b as a child when detach event is fired for a - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInDetachListener_middleAsParent_lastAsChild() { - assertDetachAttachEvents(createNodes(), "b", "c"); - } - - /** - * @formatter:off - * - * parent - * / | \ - * a b c - * | ^ - * +----| - * - * parent is detached, - * attach events are fired from bottom to up, from right, to left: - * the order of firing events is : c, b, a, parent - * - * In this test b goes to c as a child when detach event is fired for a - * - * @formatter:on - */ - @Test - public void modifyNodeTreeInDetachListener_lastAsParent_middleAsChild() { - assertDetachAttachEvents(createNodes(), "c", "b"); - } - - /** - * #5316: removeFromTree removes StateTree reference and resets descendant - * nodes. - */ - @Test - public void removeFromTree_nodeAttached_detachedAndDescendantsReset() { - // given grandParent -> parent -> child - StateNode grandParent = createParentNode("grandParent"); - StateNode parent = createParentNode("parent"); - addChild(grandParent, parent); - StateNode child = createEmptyNode("child"); - addChild(parent, child); - - TestStateTree tree = new TestStateTree(); - addChild(tree.getRootNode(), grandParent); - - // when parent is removed from the tree - parent.removeFromTree(); - - // then parent's parent is null - Assert.assertNull(parent.getParent()); - - // then parent and its descendants are reset - assertNodesReset(parent, child); - } - - /** - * #5316: removeFromTree when invoked from a DetachListener removes - * StateTree reference and resets descendant nodes. - */ - @Test - public void removeFromTree_nodeAttachedAndInDetachListener_detachedAndDescendantsReset() { - // given grandParent -> parent -> child - StateNode grandParent = createParentNode("grandParent"); - StateNode parent = createParentNode("parent"); - addChild(grandParent, parent); - StateNode child = createEmptyNode("child"); - addChild(parent, child); - - TestStateTree tree = new TestStateTree(); - addChild(tree.getRootNode(), grandParent); - - // given parent's detach listener removes the node from the tree - parent.addDetachListener(() -> parent.removeFromTree()); - - // when parent is removed from the tree - parent.setParent(null); - - // then parent and its descendants are reset - assertNodesReset(parent, child); - } - - @Test - public void removeFromTree_closeUI_allowsToSetANewTree() { - UI ui = new UI(); - - AtomicBoolean isRootAttached = new AtomicBoolean(); - isRootAttached.set(true); - - StateNode root = new StateNode(ElementChildrenList.class) { - @Override - public boolean isAttached() { - return isRootAttached.get(); - } - - }; - - StateTree stateTree = new StateTree(ui.getInternals(), - ElementChildrenList.class) { - - @Override - public StateNode getRootNode() { - return root; - } - - @Override - public boolean hasNode(StateNode node) { - if (getRootNode().equals(node)) { - return true; - } - return super.hasNode(node); - } - }; - - root.setTree(stateTree); - - StateNode child = createEmptyNode("child"); - StateNode anotherChild = createEmptyNode("anotherChild"); - - addChild(root, child); - addChild(root, anotherChild); - - // remove the second child from its parent (don't remove it from the - // tree!) - removeFromParent(anotherChild); - - // Once a child is added to a tree its id is not negative - Assert.assertNotEquals(-1, anotherChild.getId()); - - // Remove the first child from the tree (as it's done on preserve on - // refresh) - child.removeFromTree(); - // emulate closed UI - isRootAttached.set(false); - - // At this point the second child still refers to the stateTree and - // normally it's not allowed to move nodes from one tree to another but - // stateTree is "detached" and marked as replaced on - // preserve on refresh via removeFromTree called on another - // node - anotherChild.setTree(new TestStateTree()); - - // It's possible to set a new tree for the child whose owner is detached - // as marked replaced via preserved on refresh, its id is reset to -1 - Assert.assertEquals(-1, anotherChild.getId()); - } - - private void assertNodesReset(StateNode... nodes) { - for (StateNode node : nodes) { - Assert.assertEquals(-1, node.getId()); - Assert.assertFalse(node.isAttached()); - Assert.assertEquals(NullOwner.get(), node.getOwner()); - node.collectChanges(c -> Assert.fail("No changes expected")); - } - } - - private void assertAttachDetachEvents(Map nodes, - String newParent, String child, boolean expectSingleEvent) { - TestStateTree tree = new TestStateTree(); - - // use the order from the list - StateNode childA = nodes.get("a"); - StateNode childB = nodes.get("b"); - StateNode childC = nodes.get("c"); - - // those are the same nodes that above but it's easier to have a - // dedicate variables for them - StateNode newParentNode = nodes.remove(newParent); - StateNode childNode = nodes.remove(child); - - StateNode nodeWithListener = nodes.values().iterator().next(); - nodeWithListener.addAttachListener(() -> { - addChild(newParentNode, childNode); - }); - - List attachDetachEvents = new ArrayList<>(); - childNode.addAttachListener(() -> { - attachDetachEvents.add(childNode.getParent()); - }); - childNode.addDetachListener(() -> attachDetachEvents.add(false)); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - addChild(parent, childB); - addChild(parent, childC); - - addChild(tree.getRootNode(), parent); - - /* - * Depending on the order of children there should be either only one - * ATTACH event or 3 events: intermediate ATTACH and DETACH and final - * ATTACH. - */ - if (expectSingleEvent) { - Assert.assertEquals(1, attachDetachEvents.size()); - Assert.assertEquals(newParentNode, attachDetachEvents.get(0)); - } else { - Assert.assertEquals(3, attachDetachEvents.size()); - Assert.assertEquals(parent, attachDetachEvents.get(0)); - Assert.assertEquals(Boolean.FALSE, attachDetachEvents.get(1)); - Assert.assertEquals(newParentNode, attachDetachEvents.get(2)); - } - - Assert.assertEquals(newParentNode, childNode.getParent()); - } - - private void assertDetachAttachEvents(Map nodes, - String newParent, String child) { - TestStateTree tree = new TestStateTree(); - - // use the order from the list - StateNode childA = nodes.get("a"); - StateNode childB = nodes.get("b"); - StateNode childC = nodes.get("c"); - - // those are the same nodes that above but it's easier to have a - // dedicate variables for them - StateNode newParentNode = nodes.remove(newParent); - StateNode childNode = nodes.remove(child); - - StateNode nodeWithListener = nodes.values().iterator().next(); - nodeWithListener.addDetachListener(() -> { - addChild(newParentNode, childNode); - }); - - StateNode parent = createParentNode("parent"); - - addChild(parent, childA); - addChild(parent, childB); - addChild(parent, childC); - - addChild(tree.getRootNode(), parent); - - List attachDetachEvents = new ArrayList<>(); - childNode.addAttachListener(() -> { - attachDetachEvents.add(childNode.getParent()); - }); - childNode.addDetachListener(() -> attachDetachEvents.add(false)); - - removeFromParent(parent); - - // Only one DETACH event is expected - Assert.assertEquals(1, attachDetachEvents.size()); - Assert.assertFalse((Boolean) attachDetachEvents.get(0)); - } - - private Map createNodes() { - return Stream - .of(createParentNode("a"), createParentNode("b"), - createParentNode("c")) - .collect(Collectors.toMap(node -> node.toString(), - Function.identity())); - } - - private void addChild(StateNode parent, StateNode node) { - removeFromParent(node); - ElementChildrenList list = parent.getFeature(ElementChildrenList.class); - list.add(list.size(), node); - } - - private void removeFromParent(StateNode node) { - if (node.getParent() == null) { - return; - } - ElementChildrenList list = node.getParent() - .getFeature(ElementChildrenList.class); - for (int i = 0; i < list.size(); i++) { - StateNode child = list.get(i); - if (node.equals(child)) { - list.remove(i); - break; - } - } - } - - private void assertCollectChanges_initiallyInactive(StateNode stateNode, - ElementPropertyMap properties, Consumer activityUpdater) { - - TestStateTree tree = (TestStateTree) stateNode.getOwner(); - tree.dirtyNodes.clear(); - - ElementData visibility = stateNode.getFeature(ElementData.class); - activityUpdater.accept(false); - - properties.setProperty("foo", "bar"); - - // activity updater may modify visibility of the node itself or its - // ancestor. The number of changes will depend on whether the subject - // node is visible or not - boolean visibilityChanged = !visibility.isVisible(); - - List changes = new ArrayList<>(); - stateNode.collectChanges(changes::add); - - if (visibilityChanged) { - Assert.assertEquals(1, tree.dirtyNodes.size()); - MatcherAssert.assertThat(tree.dirtyNodes, - CoreMatchers.hasItem(stateNode)); - } else { - // the target node should be marked as dirty because it's visible - // but its parent is inactive - Assert.assertEquals(2, tree.dirtyNodes.size()); - stateNode.visitNodeTree(node -> MatcherAssert - .assertThat(tree.dirtyNodes, CoreMatchers.hasItem(node))); - } - - Assert.assertEquals(visibilityChanged ? 3 : 2, changes.size()); - // node is attached event - MatcherAssert.assertThat(changes.get(0), - CoreMatchers.instanceOf(NodeAttachChange.class)); - // tag update (ElementData is reported feature) and possible active - // state update - Optional tagFound = changes.stream() - .filter(MapPutChange.class::isInstance) - .map(MapPutChange.class::cast) - .filter(chang -> chang.getKey().equals("tag")).findFirst(); - Assert.assertTrue("No tag change found", tagFound.isPresent()); - MapPutChange tagChange = tagFound.get(); - - MapPutChange change = (MapPutChange) changes.get(1); - if (visibilityChanged) { - MatcherAssert.assertThat(changes.get(2), - CoreMatchers.instanceOf(MapPutChange.class)); - change = tagChange.equals(change) ? (MapPutChange) changes.get(2) - : change; - } - - Assert.assertEquals(Element.get(stateNode).getTag(), - tagChange.getValue()); - - if (visibilityChanged) { - Assert.assertEquals(Boolean.FALSE, change.getValue()); - } - - changes.clear(); - - // now the node becomes active and should send all values from all - // features (including values that has not been sent previously). - - activityUpdater.accept(true); - - properties.setProperty("baz", "foo"); - stateNode.collectChanges(changes::add); - - Assert.assertEquals(visibilityChanged ? 3 : 2, changes.size()); - // node is attached event - // property updates and possible visibility update - MatcherAssert.assertThat(changes.get(1), - CoreMatchers.instanceOf(MapPutChange.class)); - - Optional visibilityChange = changes.stream() - .filter(MapPutChange.class::isInstance) - .map(MapPutChange.class::cast) - .filter(chang -> chang.getFeature().equals(ElementData.class)) - .findFirst(); - - if (visibilityChanged) { - Assert.assertTrue(visibilityChange.isPresent()); - Assert.assertTrue((Boolean) visibilityChange.get().getValue()); - changes.remove(visibilityChange.get()); - } - - Optional fooUpdate = changes.stream() - .filter(MapPutChange.class::isInstance) - .map(MapPutChange.class::cast) - .filter(chang -> chang.getKey().equals("foo")).findFirst(); - - Assert.assertTrue(fooUpdate.isPresent()); - Assert.assertEquals("bar", fooUpdate.get().getValue()); - - changes.remove(fooUpdate.get()); - - change = (MapPutChange) changes.get(0); - Assert.assertEquals("foo", change.getValue()); - Assert.assertEquals("baz", change.getKey()); - - // Don't make any changes, check that there are no changes collected - changes.clear(); - stateNode.collectChanges(changes::add); - - Assert.assertEquals(0, changes.size()); - } - - private void assertCollectChanges_initiallyVisible(StateNode stateNode, - ElementPropertyMap properties, Consumer activityUpdater) { - ElementData visibility = stateNode.getFeature(ElementData.class); - - // check that normal flow works as it should (without any inactivity) - properties.setProperty("foo", "bar"); - - List changes = new ArrayList<>(); - stateNode.collectChanges(changes::add); - - Assert.assertEquals(2, changes.size()); - // node is attached event - MatcherAssert.assertThat(changes.get(0), - CoreMatchers.instanceOf(NodeAttachChange.class)); - // the property update event - MatcherAssert.assertThat(changes.get(1), - CoreMatchers.instanceOf(MapPutChange.class)); - - changes.clear(); - - TestStateTree tree = (TestStateTree) stateNode.getOwner(); - tree.dirtyNodes.clear(); - - // now make the node inactive via the VisibiltyData - - activityUpdater.accept(false); - - // now the node becomes inactive and should send only changes for - // VisibiltyData, but don't loose changes for other features - - properties.setProperty("foo", "baz"); - - stateNode.collectChanges(changes::add); - - // activity updater may modify visibility of the node itself or its - // ancestor. The number of changes will depend on whether the subject - // node is visible or not - boolean visibilityChanged = !visibility.isVisible(); - - // The only possible change is visibility value change - Assert.assertEquals(visibilityChanged ? 1 : 0, changes.size()); - - MapPutChange change; - if (visibilityChanged) { - Assert.assertEquals(1, tree.dirtyNodes.size()); - MatcherAssert.assertThat(tree.dirtyNodes, - CoreMatchers.hasItem(stateNode)); - MatcherAssert.assertThat(changes.get(0), - CoreMatchers.instanceOf(MapPutChange.class)); - change = (MapPutChange) changes.get(0); - Assert.assertEquals(ElementData.class, change.getFeature()); - } else { - // the target node should be marked as dirty because it's visible - // but its parent is inactive - Assert.assertEquals(2, tree.dirtyNodes.size()); - stateNode.visitNodeTree(node -> MatcherAssert - .assertThat(tree.dirtyNodes, CoreMatchers.hasItem(node))); - } - - changes.clear(); - - // make the node active again - activityUpdater.accept(true); - - stateNode.collectChanges(changes::add); - - // Two possible changes: probable visibility value change and property - // update change - Assert.assertEquals(visibilityChanged ? 2 : 1, changes.size()); - MatcherAssert.assertThat(changes.get(0), - CoreMatchers.instanceOf(MapPutChange.class)); - change = (MapPutChange) changes.get(0); - - MapPutChange propertyChange; - - if (visibilityChanged) { - MapPutChange visibilityChange = ElementData.class - .equals(change.getFeature()) ? change - : (MapPutChange) changes.get(1); - propertyChange = change.equals(visibilityChange) - ? (MapPutChange) changes.get(1) - : change; - } else { - propertyChange = change; - } - - Assert.assertEquals(ElementPropertyMap.class, - propertyChange.getFeature()); - Assert.assertEquals("baz", propertyChange.getValue()); - - // Don't make any changes, check that there are no changes collected - changes.clear(); - stateNode.collectChanges(changes::add); - - Assert.assertEquals(0, changes.size()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/StateTreeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/StateTreeTest.java deleted file mode 100644 index 548e85536a0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/StateTreeTest.java +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.function.SerializableConsumer; -import com.vaadin.flow.internal.change.ListAddChange; -import com.vaadin.flow.internal.change.ListRemoveChange; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.NodeAttachChange; -import com.vaadin.flow.internal.change.NodeChange; -import com.vaadin.flow.internal.change.NodeDetachChange; -import com.vaadin.flow.internal.change.NodeFeatureChange; -import com.vaadin.flow.internal.nodefeature.ElementAttributeMap; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; -import com.vaadin.flow.internal.nodefeature.ElementData; -import com.vaadin.flow.internal.nodefeature.ElementPropertyMap; -import com.vaadin.flow.internal.nodefeature.NodeFeature; -import com.vaadin.flow.internal.nodefeature.PushConfigurationMap.PushConfigurationParametersMap; -import com.vaadin.tests.util.TestUtil; - -import elemental.json.JsonObject; - -public class StateTreeTest { - - private StateTree tree = new UI().getInternals().getStateTree(); - - public static class AttachableNode extends StateNode { - - private boolean attached; - - public AttachableNode() { - } - - public AttachableNode(boolean attached) { - this.attached = attached; - } - - public void setAttached(boolean attached) { - this.attached = attached; - } - - @Override - public boolean isAttached() { - return attached; - } - } - - public static class CollectableNode extends StateNode { - - public CollectableNode() { - super(ElementData.class, ElementChildrenList.class); - } - - @Override - public void collectChanges(Consumer collector) { - collector.accept(new NodeChange(this) { - @Override - protected void populateJson(JsonObject json, - ConstantPool constantPool) { - } - }); - } - } - - @Test - public void rootNodeState() { - StateNode rootNode = tree.getRootNode(); - - Assert.assertNull("Root node should have no parent", - rootNode.getParent()); - - Assert.assertTrue("Root node should always be attached", - rootNode.isAttached()); - - Assert.assertEquals("Root node should always have the same id", 1, - rootNode.getId()); - - Assert.assertSame(tree, rootNode.getOwner()); - } - - @Test(expected = IllegalStateException.class) - public void rootNode_setStateNodeAsParent_throws() { - tree.getRootNode().setParent(new StateNode()); - } - - @Test - public void rootNode_setNullAsParent_nodeIsDetached() { - AtomicInteger detachCount = new AtomicInteger(); - Assert.assertTrue(tree.hasNode(tree.getRootNode())); - tree.getRootNode() - .addDetachListener(() -> detachCount.incrementAndGet()); - tree.getRootNode().setParent(null); - Assert.assertEquals(1, detachCount.get()); - Assert.assertFalse(tree.getRootNode().isAttached()); - - Assert.assertFalse(tree.hasNode(tree.getRootNode())); - } - - @Test - public void attachedNodeIsAttached() { - StateNode node = StateNodeTest.createEmptyNode(); - - Assert.assertFalse("New node should not be attached", - node.isAttached()); - - StateNodeTest.setParent(node, tree.getRootNode()); - - Assert.assertTrue("Node with parent set should be attached", - node.isAttached()); - - StateNodeTest.setParent(node, null); - - Assert.assertFalse("Node without parent should not be attached", - node.isAttached()); - } - - @Test(expected = IllegalStateException.class) - public void moveNodeToOtherRoot_throws() { - StateNode node = StateNodeTest.createEmptyNode(); - - StateNodeTest.setParent(node, tree.getRootNode()); - - StateNodeTest.setParent(node, null); - - StateTree anotherTree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - - StateNodeTest.setParent(node, anotherTree.getRootNode()); - } - - @Test - public void testNoRootAttachChange() { - List changes = collectChangesExceptChildrenAddRemove(); - - for (NodeChange change : changes) { - if (change instanceof NodeFeatureChange) { - Class feature = ((NodeFeatureChange) change) - .getFeature(); - Assert.assertNotEquals(ElementChildrenList.class, feature); - } else if (change instanceof NodeAttachChange) { - StateNode node = ((NodeAttachChange) change).getNode(); - Assert.assertNotEquals(tree.getRootNode(), node); - } - } - - } - - @Test - public void testTreeChangeCollection() { - StateNode node2 = StateNodeTest.createEmptyNode(); - StateNodeTest.setParent(node2, tree.getRootNode()); - - List changes = collectChangesExceptChildrenAddRemove(); - - List notChildrenChanges = new ArrayList<>(); - for (NodeChange change : changes) { - if (change instanceof NodeFeatureChange) { - Class feature = ((NodeFeatureChange) change) - .getFeature(); - Assert.assertNotEquals(ElementChildrenList.class, feature); - } else { - notChildrenChanges.add(change); - } - } - - Assert.assertEquals(2, notChildrenChanges.size()); - NodeAttachChange nodeChange = (NodeAttachChange) notChildrenChanges - .get(0); - // The first node is not in the "hierarchy" tree but is the Push - // config node - Assert.assertTrue(nodeChange.getNode() - .hasFeature(PushConfigurationParametersMap.class)); - - NodeAttachChange attachChange = (NodeAttachChange) notChildrenChanges - .get(1); - Assert.assertSame(node2, attachChange.getNode()); - } - - @Test - public void testDirtyNodeCollection() { - StateNode node1 = tree.getRootNode(); - StateNode node2 = StateNodeTest.createEmptyNode("node2"); - - StateNodeTest.setParent(node2, node1); - - NodeOwner owner = node1.getOwner(); - - Assert.assertSame("Both nodes should have the same owner", owner, - node2.getOwner()); - - Set initialDirty = tree.collectDirtyNodes(); - - HashSet dirty = initialDirty.stream().filter( - node -> !node.hasFeature(PushConfigurationParametersMap.class)) - .collect(Collectors.toCollection(HashSet::new)); - Assert.assertEquals("Both nodes should initially be empty", - new HashSet<>(Arrays.asList(node1, node2)), dirty); - - tree.collectChanges(change -> { - }); - - node2.markAsDirty(); - - Set collectAfterOneMarked = tree.collectDirtyNodes(); - Assert.assertTrue("Marked node should be in collect result", - collectAfterOneMarked.contains(node2)); - } - - @Test - public void testDirtyNodeCollectionOrder() { - StateNode rootNode = tree.getRootNode(); - List nodes = new ArrayList<>(); - for (int i = 0; i < 10; i++) { - StateNode node = StateNodeTest.createEmptyNode("node" + i); - nodes.add(node); - StateNodeTest.setParent(node, rootNode); - } - - nodes.forEach(StateNode::markAsDirty); - List expected = new ArrayList<>(); - expected.add(rootNode); - expected.addAll(nodes); - - Object[] dirty = tree.collectDirtyNodes().stream().filter( - node -> !node.hasFeature(PushConfigurationParametersMap.class)) - .toArray(); - Assert.assertArrayEquals(expected.toArray(), dirty); - - tree.collectChanges(change -> { - }); - - nodes.forEach(StateNode::markAsDirty); - expected = new ArrayList<>(nodes); - Assert.assertArrayEquals(expected.toArray(), - tree.collectDirtyNodes().toArray()); - } - - @Test - public void testDetachInChanges() { - StateNode node1 = tree.getRootNode(); - StateNode node2 = StateNodeTest.createEmptyNode(); - StateNodeTest.setParent(node2, node1); - - // Clear - collectChangesExceptChildrenAddRemove(); - - StateNodeTest.setParent(node2, null); - - List changes = collectChangesExceptChildrenAddRemove(); - - Assert.assertEquals("Should be one change.", 1, changes.size()); - Assert.assertTrue("Should have a detach change", - changes.get(0) instanceof NodeDetachChange); - } - - @Test - public void allValuesAfterReattach() { - StateNode node1 = tree.getRootNode(); - StateNode node2 = new StateNode(ElementData.class); - - StateNodeTest.setParent(node2, node1); - node2.getFeature(ElementData.class).setTag("foo"); - collectChangesExceptChildrenAddRemove(); - - StateNodeTest.setParent(node2, null); - collectChangesExceptChildrenAddRemove(); - - StateNodeTest.setParent(node2, node1); - List changes = collectChangesExceptChildrenAddRemove(); - - Assert.assertEquals("Should be three changes.", 2, changes.size()); - Assert.assertTrue("First change should re-attach the node.", - changes.get(0) instanceof NodeAttachChange); - Assert.assertTrue("Second change should put the tag or payload value.", - changes.get(1) instanceof MapPutChange); - - Optional tagFound = changes.stream() - .filter(MapPutChange.class::isInstance) - .map(MapPutChange.class::cast) - .filter(chang -> chang.getKey().equals("tag")).findFirst(); - Assert.assertTrue("No tag change found", tagFound.isPresent()); - MapPutChange nodeChange = tagFound.get(); - Assert.assertEquals(ElementData.class, nodeChange.getFeature()); - Assert.assertEquals("tag", nodeChange.getKey()); - Assert.assertEquals("foo", nodeChange.getValue()); - } - - private List collectChangesExceptChildrenAddRemove() { - List changes = new ArrayList<>(); - tree.collectChanges(change -> { - if ((change instanceof ListAddChange - || change instanceof ListRemoveChange) - && ((NodeFeatureChange) change) - .getFeature() == ElementChildrenList.class) { - return; - } else { - changes.add(change); - } - }); - return changes; - } - - @Test - public void testSerializable() { - @SuppressWarnings("unchecked") - Class[] features = new Class[] { - ElementChildrenList.class, ElementData.class, - ElementAttributeMap.class, ElementPropertyMap.class }; - StateTree tree = new StateTree(new UI().getInternals(), features); - - StateNode root = tree.getRootNode(); - root.getFeature(ElementData.class).setTag("body"); - StateNode child = new StateNode(features); - root.getFeature(ElementChildrenList.class).add(0, child); - child.getFeature(ElementData.class).setTag(Tag.DIV); - - byte[] serialized = SerializationUtils.serialize(tree); - StateTree d1 = (StateTree) SerializationUtils.deserialize(serialized); - - Assert.assertNotNull(d1); - } - - @Test - public void reattachedNodeRetainsId() throws InterruptedException { - StateNode child = new StateNode(ElementChildrenList.class); - StateNode grandChild = new StateNode(ElementChildrenList.class); - - child.getFeature(ElementChildrenList.class).add(0, grandChild); - - ElementChildrenList children = tree.getRootNode() - .getFeature(ElementChildrenList.class); - children.add(0, child); - - int childId = child.getId(); - int grandChildId = grandChild.getId(); - - Assert.assertTrue(child.isAttached()); - Assert.assertTrue(grandChild.isAttached()); - - Assert.assertSame(child, tree.getNodeById(childId)); - Assert.assertSame(grandChild, tree.getNodeById(grandChildId)); - - children.remove(0); - - Assert.assertFalse(child.isAttached()); - Assert.assertFalse(grandChild.isAttached()); - - Assert.assertNull(tree.getNodeById(childId)); - Assert.assertNull(tree.getNodeById(grandChildId)); - - children.add(0, child); - - Assert.assertTrue(child.isAttached()); - Assert.assertTrue(grandChild.isAttached()); - - Assert.assertEquals(childId, child.getId()); - Assert.assertEquals(grandChildId, grandChild.getId()); - - Assert.assertSame(child, tree.getNodeById(childId)); - Assert.assertSame(grandChild, tree.getNodeById(grandChildId)); - } - - @Test - public void detachedNodeGarbageCollected() throws InterruptedException { - StateNode child = new StateNode(ElementChildrenList.class); - StateNode grandChild = new StateNode(ElementChildrenList.class); - - child.getFeature(ElementChildrenList.class).add(0, grandChild); - - ElementChildrenList children = tree.getRootNode() - .getFeature(ElementChildrenList.class); - children.add(0, child); - - WeakReference childRef = new WeakReference<>(child); - child = null; - - WeakReference grandChildRef = new WeakReference<>( - grandChild); - grandChild = null; - - children.remove(0); - - tree.collectChanges(c -> { - // nop - }); - - Assert.assertTrue(TestUtil.isGarbageCollected(childRef)); - Assert.assertTrue(TestUtil.isGarbageCollected(grandChildRef)); - } - - @Test - public void beforeClientResponse_regularOrder() { - StateNode rootNode = new AttachableNode(true); - - List results = new ArrayList<>(); - - tree.beforeClientResponse(rootNode, context -> results.add(0)); - tree.beforeClientResponse(rootNode, context -> results.add(1)); - tree.beforeClientResponse(rootNode, context -> results.add(2)); - - tree.runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 3 results in the list", - results.size() == 3); - - for (int i = 0; i < results.size(); i++) { - Assert.assertEquals( - "The result at index '" + i + "' should be " + i, i, - results.get(i).intValue()); - } - } - - @Test - public void beforeClientResponse_initiallyAttachedToOneUI_executedWithAnother_executionDoesNotHappen() { - StateTree initialTree = new UI().getInternals().getStateTree(); - - StateNode child = new StateNode(ElementChildrenList.class); - StateNodeTest.setParent(child, initialTree.getRootNode()); - - AtomicBoolean isExecuted = new AtomicBoolean(); - initialTree.beforeClientResponse(child, - context -> isExecuted.set(true)); - - child.removeFromTree(); - - StateNodeTest.setParent(child, tree.getRootNode()); - tree.runExecutionsBeforeClientResponse(); - - Assert.assertFalse(isExecuted.get()); - } - - @Test - public void beforeClientResponse_initiallyNotAttached_executedWithUI_executionRun() { - StateTree someTree = new UI().getInternals().getStateTree(); - - StateNode child = new StateNode(ElementChildrenList.class); - - AtomicBoolean isExecuted = new AtomicBoolean(); - someTree.beforeClientResponse(child, context -> isExecuted.set(true)); - - StateNodeTest.setParent(child, tree.getRootNode()); - tree.runExecutionsBeforeClientResponse(); - - Assert.assertTrue(isExecuted.get()); - } - - @Test - public void beforeClientResponse_withInnerRunnables() { - StateNode rootNode = new AttachableNode(true); - - List results = new ArrayList<>(); - - tree.beforeClientResponse(rootNode, context -> results.add(0)); - tree.beforeClientResponse(rootNode, context -> { - results.add(1); - tree.beforeClientResponse(rootNode, context2 -> results.add(3)); - tree.beforeClientResponse(rootNode, context2 -> results.add(4)); - }); - tree.beforeClientResponse(rootNode, context -> results.add(2)); - - tree.runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 5 results in the list", - results.size() == 5); - - for (int i = 0; i < results.size(); i++) { - Assert.assertEquals( - "The result at index '" + i + "' should be " + i, i, - results.get(i).intValue()); - } - } - - @Test - public void beforeClientResponse_withUnattachedNodes() { - StateNode rootNode = new AttachableNode(true); - StateNode emptyNode = new AttachableNode(); - - List results = new ArrayList<>(); - - tree.beforeClientResponse(emptyNode, context -> results.add(0)); - tree.beforeClientResponse(rootNode, context -> results.add(1)); - tree.beforeClientResponse(emptyNode, context -> results.add(2)); - tree.beforeClientResponse(rootNode, context -> results.add(3)); - - tree.runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 2 results in the list", - results.size() == 2); - - Assert.assertEquals("The result at index '0' should be " + 1, 1, - results.get(0).intValue()); - Assert.assertEquals("The result at index '1' should be " + 3, 3, - results.get(1).intValue()); - } - - @Test - public void beforeClientResponse_withAttachedNodesDuringExecution() { - StateNode rootNode = tree.getRootNode(); - StateNode emptyNode1 = StateNodeTest.createEmptyNode("node1"); - StateNode emptyNode2 = StateNodeTest.createEmptyNode("node2"); - - List results = new ArrayList<>(); - - tree.beforeClientResponse(emptyNode1, context -> { - results.add(0); - StateNodeTest.setParent(emptyNode2, rootNode); - }); - tree.beforeClientResponse(rootNode, context -> { - results.add(1); - StateNodeTest.setParent(emptyNode1, rootNode); - }); - tree.beforeClientResponse(emptyNode2, context -> results.add(2)); - tree.beforeClientResponse(rootNode, context -> results.add(3)); - - tree.runExecutionsBeforeClientResponse(); - Assert.assertTrue("There should be 4 results in the list", - results.size() == 4); - - Assert.assertEquals("The result at index '0' should be 1", 1, - results.get(0).intValue()); - Assert.assertEquals("The result at index '1' should be 3", 3, - results.get(1).intValue()); - Assert.assertEquals("The result at index '2' should be 0", 0, - results.get(2).intValue()); - Assert.assertEquals("The result at index '3' should be 2", 2, - results.get(3).intValue()); - } - - @Test - public void beforeClientResponse_nodeGarbageCollectedDespiteClosure() - throws InterruptedException { - StateNode node1 = tree.getRootNode(); - StateNode node2 = StateNodeTest.createEmptyNode("node2"); - - StateNodeTest.setParent(node2, node1); - - class CapturingConsumer - implements SerializableConsumer { - private final Object captured; - - public CapturingConsumer(Object captured) { - this.captured = captured; - } - - @Override - public void accept(ExecutionContext t) { - // no-op - } - } - - tree.beforeClientResponse(node2, new CapturingConsumer(node2)); - - StateNodeTest.setParent(node2, null); - - WeakReference ref = new WeakReference<>(node2); - node2 = null; - - // Collect to release from list of detached nodes - tree.collectChanges(value -> { - // nop - }); - - Assert.assertTrue(TestUtil.isGarbageCollected(ref)); - } - - @Test - public void collectChanges_updateActiveState() { - StateNode node1 = Mockito.mock(StateNode.class); - StateNode node2 = Mockito.mock(StateNode.class); - - Mockito.when(node1.getOwner()).thenReturn(tree); - Mockito.when(node2.getOwner()).thenReturn(tree); - - tree.markAsDirty(node1); - tree.markAsDirty(node2); - - tree.collectChanges(node -> { - }); - - Mockito.verify(node1).updateActiveState(); - Mockito.verify(node2).updateActiveState(); - } - - @Test - public void collectChanges_parentIsInactive_childrenAreCollected() { - StateNode node1 = new CollectableNode(); - StateNode node2 = new CollectableNode(); - StateNode node3 = new CollectableNode(); - - node1.setTree(tree); - node2.setTree(tree); - node3.setTree(tree); - - node1.getFeature(ElementChildrenList.class).add(0, node2); - node2.getFeature(ElementChildrenList.class).add(0, node3); - - // cleanup the current dirty nodes - tree.collectChanges(node -> { - }); - - node1.getFeature(ElementData.class).setVisible(false); - - List collectedNodes = new ArrayList<>(3); - - tree.collectChanges(change -> collectedNodes.add(change.getNode())); - - Assert.assertEquals(3, collectedNodes.size()); - Assert.assertTrue(collectedNodes.contains(node1)); - Assert.assertTrue(collectedNodes.contains(node2)); - Assert.assertTrue(collectedNodes.contains(node3)); - } - - @Test - public void prepareForResync_nodeHasAttachAndDetachListeners_treeIsDirtyAndListenersAreCalled() { - StateNode node1 = tree.getRootNode(); - StateNode node2 = StateNodeTest.createEmptyNode("node2"); - StateNodeTest.setParent(node2, node1); - - AtomicInteger attachCount = new AtomicInteger(); - node2.addAttachListener(attachCount::incrementAndGet); - AtomicInteger detachCount = new AtomicInteger(); - node2.addDetachListener(detachCount::incrementAndGet); - - tree.collectChanges(c -> { - }); - Assert.assertEquals(0, tree.collectDirtyNodes().size()); - - tree.getRootNode().prepareForResync(); - - Assert.assertEquals(1, attachCount.get()); - Assert.assertEquals(1, detachCount.get()); - - Assert.assertEquals(3, tree.collectDirtyNodes().size()); - - Set dirtyNodes = new HashSet<>(tree.collectDirtyNodes()); - Assert.assertTrue(dirtyNodes.remove(node1)); - Assert.assertTrue(dirtyNodes.remove(node2)); - - StateNode remaining = dirtyNodes.iterator().next(); - // The remaining node is not in the "hierarchy" tree but is the Push - // config node - Assert.assertTrue( - remaining.hasFeature(PushConfigurationParametersMap.class)); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/StringUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/StringUtilTest.java deleted file mode 100644 index b7f5263d73c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/StringUtilTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import org.junit.Assert; -import org.junit.Test; - -public class StringUtilTest { - - @Test - public void commentRemoval_handlesCommentsCorrectly() { - String singleLineBlock = StringUtil - .removeComments("return html'/* single line block comment*/';"); - - Assert.assertEquals("return html'';", singleLineBlock); - - String blockComment = StringUtil - .removeComments("return html'/* block with new lines\n" - + "* still in my/their block */';"); - Assert.assertEquals("return html'';", blockComment); - - String newLineSingleBlock = StringUtil - .removeComments("return html'/* not here \n*/';"); - Assert.assertEquals("return html'';", newLineSingleBlock); - - String noComments = "`"; - Assert.assertEquals(noComments, StringUtil.removeComments(noComments)); - - String lineComment = StringUtil - .removeComments("return html'// this line comment\n';"); - Assert.assertEquals("return html'\n';", lineComment); - - String mixedComments = StringUtil.removeComments( - "return html'/* not here \n*/\nCode;// neither this\n" - + "/* this should // be fine\n* to remove / */';"); - Assert.assertEquals("return html'\nCode;\n';", mixedComments); - } - - @Test - public void commentRemoval_emojiInString_removalDoesnotThrowResultIsTheSame() { - String initialTemplate = "import { html } from '@polymer/polymer/lib/utils/html-tag.js';\n" - + "class EmployeeForm extends PolymerElement {\n" - + " static get template() {\n" + " return html`\n" - + "
\n" - + " \n" + " \n" - + "🚧 Training: Coming soon 🚧\n" + " \n" - + " \n" + "
\n" + "`;\n" + " }\n" - + "\n"; - String template = StringUtil.removeComments(initialTemplate); - Assert.assertEquals(initialTemplate, template); - } - - @Test - public void removeComments_commentsWithAsterisksInside_commentIsRemoved() { - String result = StringUtil.removeComments("/* comment **/ ;"); - Assert.assertEquals(" ;", result); - } - - @Test - public void removeJsComments_handlesApostropheAsInString() { - String httpImport = "import 'http://localhost:56445/files/transformed/@vaadin/vaadin-text-field/vaadin-text-field.js';"; - - Assert.assertEquals("Nothing shoiuld be removed for import", httpImport, - StringUtil.removeComments(httpImport, true)); - - String result = StringUtil.removeComments("/* comment **/ ;", true); - Assert.assertEquals(" ;", result); - - String singleLineBlock = StringUtil.removeComments( - "return html`/* single line block comment*/`;", true); - - Assert.assertEquals("return html``;", singleLineBlock); - - String blockComment = StringUtil - .removeComments("return html`/* block with new lines\n" - + "* still in my/their block */`;", true); - Assert.assertEquals("return html``;", blockComment); - - String newLineSingleBlock = StringUtil - .removeComments("return html`/* not here \n*/`;", true); - Assert.assertEquals("return html``;", newLineSingleBlock); - - String noComments = "`"; - Assert.assertEquals(noComments, - StringUtil.removeComments(noComments, true)); - - String lineComment = StringUtil - .removeComments("return html`// this line comment\n`;", true); - Assert.assertEquals("return html`\n`;", lineComment); - - String mixedComments = StringUtil.removeComments( - "return html`/* not here \n*/\nCode;// neither this\n" - + "/* this should // be fine\n* to remove / */`;", - true); - Assert.assertEquals("return html`\nCode;\n`;", mixedComments); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/UrlUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/UrlUtilTest.java deleted file mode 100644 index c193def53fc..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/UrlUtilTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal; - -import jakarta.servlet.http.HttpServletRequest; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinServletService; - -public class UrlUtilTest { - - private String encodeURIShouldNotBeEscaped = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;,/?:@&=+$-_.!~*'()#"; - private String encodeURIComponentShouldNotBeEscaped = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"; - - @Test - public void isExternal_URLStartsWithTwoSlashes_returnsTrue() { - Assert.assertTrue(UrlUtil.isExternal("//foo")); - } - - @Test - public void isExternal_URLContainsAnySchemaAsPrefix_returnsTrue() { - Assert.assertTrue(UrlUtil.isExternal("http://foo")); - Assert.assertTrue(UrlUtil.isExternal("https://foo")); - Assert.assertTrue(UrlUtil.isExternal("context://foo")); - Assert.assertTrue(UrlUtil.isExternal("base://foo")); - } - - @Test - public void isExternal_URLDoesnotContainSchema_returnsFalse() { - Assert.assertFalse(UrlUtil.isExternal("foo")); - } - - @Test - public void plusAndSpaceHandledCorrectly() { - Assert.assertEquals("Plus+Spa%20+%20ce", - UrlUtil.encodeURI("Plus+Spa + ce")); - Assert.assertEquals("Plus%2BSpa%20%2B%20ce", - UrlUtil.encodeURIComponent("Plus+Spa + ce")); - } - - @Test - public void encodeURI_shouldNotBeEscaped() { - Assert.assertEquals(encodeURIShouldNotBeEscaped, - UrlUtil.encodeURI(encodeURIShouldNotBeEscaped)); - } - - @Test - public void encodeURI_mustBeEscaped() { - for (char c = 0; c < 255; c++) { - String s = String.valueOf(c); - if (encodeURIShouldNotBeEscaped.contains(s)) { - continue; - } - Assert.assertNotEquals(UrlUtil.encodeURI(s), s); - } - } - - @Test - public void encodeURIComponent_shouldNotBeEscaped() { - Assert.assertEquals(encodeURIComponentShouldNotBeEscaped, UrlUtil - .encodeURIComponent(encodeURIComponentShouldNotBeEscaped)); - } - - @Test - public void encodeURIComponent_mustBeEscaped() { - for (char c = 0; c < 255; c++) { - String s = String.valueOf(c); - if (encodeURIComponentShouldNotBeEscaped.contains(s)) { - continue; - } - Assert.assertNotEquals(UrlUtil.encodeURIComponent(s), s); - } - } - - @Test - public void getServletPathRelative() { - Assert.assertEquals(".", UrlUtil.getServletPathRelative("/foo/bar/", - createRequest("/foo", "/bar"))); - Assert.assertEquals(".", UrlUtil.getServletPathRelative("/foo/bar", - createRequest("/foo", "/bar"))); - Assert.assertEquals("..", UrlUtil.getServletPathRelative("/foo/", - createRequest("/foo", "/bar"))); - Assert.assertEquals("../..", UrlUtil.getServletPathRelative("/", - createRequest("/foo", "/bar"))); - Assert.assertEquals("..", UrlUtil.getServletPathRelative("/foo", - createRequest("/foo", "/bar"))); - Assert.assertEquals("../../login", UrlUtil.getServletPathRelative( - "/login", createRequest("/foo", "/bar"))); - Assert.assertEquals("../login", UrlUtil.getServletPathRelative( - "/foo/login", createRequest("/foo", "/bar"))); - Assert.assertEquals("login", UrlUtil.getServletPathRelative( - "/foo/bar/login", createRequest("/foo", "/bar"))); - Assert.assertEquals("baz/login", UrlUtil.getServletPathRelative( - "/foo/bar/baz/login", createRequest("/foo", "/bar"))); - } - - private VaadinServletRequest createRequest(String contextPath, - String servletPath) { - if (!servletPath.equals("") && !servletPath.startsWith("/")) { - throw new IllegalArgumentException( - "A servlet path always starts with / except for the empty mapping \"\""); - } - if (!contextPath.equals("") && (!contextPath.startsWith("/") - || contextPath.endsWith("/"))) { - throw new IllegalArgumentException( - "A context path is either empty or starts, but not ends with, a slash"); - } - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Mockito.when(request.getServletPath()).thenReturn(servletPath); - Mockito.when(request.getContextPath()).thenReturn(contextPath); - return new VaadinServletRequest(request, - Mockito.mock(VaadinServletService.class)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/UsageStatisticsExporterTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/UsageStatisticsExporterTest.java deleted file mode 100644 index 0f2902005f4..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/UsageStatisticsExporterTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.vaadin.flow.internal; - -import java.util.stream.Collectors; - -import org.jsoup.internal.StringUtil; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.junit.Test; - -import elemental.json.Json; -import elemental.json.JsonObject; - -import static org.junit.Assert.assertEquals; - -public class UsageStatisticsExporterTest { - - @Test - public void should_append_script_element_to_the_body() { - Document document = new Document(""); - Element html = document.appendElement("html"); - html.appendElement("body"); - - UsageStatisticsExporter.exportUsageStatisticsToDocument(document); - - String entries = UsageStatistics.getEntries().map(entry -> { - JsonObject json = Json.createObject(); - - json.put("is", entry.getName()); - json.put("version", entry.getVersion()); - - return json.toString(); - }).collect(Collectors.joining(",")); - - String expected = StringUtil - .normaliseWhitespace("window.Vaadin = window.Vaadin || {};\n" - + "window.Vaadin.registrations = window.Vaadin.registrations || [];\n" - + "window.Vaadin.registrations.push(" + entries + ");"); - - Elements bodyInlineElements = document.body() - .getElementsByTag("script"); - String htmlContent = bodyInlineElements.get(0).childNode(0).outerHtml(); - htmlContent = htmlContent.replace("\r", ""); - htmlContent = htmlContent.replace("\n", " "); - assertEquals(StringUtil.normaliseWhitespace(expected), htmlContent); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/change/ListChangeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/change/ListChangeTest.java deleted file mode 100644 index 55b8f86b265..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/change/ListChangeTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.change; - -import java.util.Arrays; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateNodeTest; -import com.vaadin.flow.internal.nodefeature.AbstractNodeFeatureTest; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; -import com.vaadin.flow.internal.nodefeature.NodeFeatureRegistry; -import com.vaadin.flow.internal.nodefeature.NodeList; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.JsonArray; -import elemental.json.JsonObject; - -public class ListChangeTest { - private NodeList feature = AbstractNodeFeatureTest - .createFeature(ElementChildrenList.class); - - @Test - public void testBasicJson() { - StateNode child1 = StateNodeTest.createEmptyNode("child1"); - StateNode child2 = StateNodeTest.createEmptyNode("child2"); - ListAddChange change = new ListAddChange<>(feature, true, 0, - Arrays.asList(child1, child2)); - - JsonObject json = change.toJson(null); - - Assert.assertEquals(change.getNode().getId(), - (int) json.getNumber(JsonConstants.CHANGE_NODE)); - Assert.assertEquals(NodeFeatureRegistry.getId(feature.getClass()), - (int) json.getNumber(JsonConstants.CHANGE_FEATURE)); - Assert.assertEquals(JsonConstants.CHANGE_TYPE_SPLICE, - json.getString(JsonConstants.CHANGE_TYPE)); - Assert.assertEquals(0, - (int) json.getNumber(JsonConstants.CHANGE_SPLICE_INDEX)); - - JsonArray addNodes = json - .getArray(JsonConstants.CHANGE_SPLICE_ADD_NODES); - Assert.assertEquals(2, addNodes.length()); - - Assert.assertEquals(child1.getId(), (int) addNodes.getNumber(0)); - Assert.assertEquals(child2.getId(), (int) addNodes.getNumber(1)); - } - - @Test - public void testZeroRemoveNotInJson() { - ListAddChange change = new ListAddChange<>(feature, false, 1, - Arrays.asList()); - - JsonObject json = change.toJson(null); - - Assert.assertFalse(json.hasKey(JsonConstants.CHANGE_SPLICE_REMOVE)); - } - - @Test - public void testEmptyAddNotInJson() { - ListAddChange change = new ListAddChange<>(feature, false, 1, - Arrays.asList()); - - JsonObject json = change.toJson(null); - - Assert.assertFalse(json.hasKey(JsonConstants.CHANGE_SPLICE_ADD_NODES)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/change/MapPutChangeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/change/MapPutChangeTest.java deleted file mode 100644 index 848df742955..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/change/MapPutChangeTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.change; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateNodeTest; -import com.vaadin.flow.internal.nodefeature.AbstractNodeFeatureTest; -import com.vaadin.flow.internal.nodefeature.ElementPropertyMap; -import com.vaadin.flow.internal.nodefeature.NodeFeatureRegistry; -import com.vaadin.flow.internal.nodefeature.NodeMap; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonType; -import elemental.json.JsonValue; - -public class MapPutChangeTest { - private NodeMap feature = AbstractNodeFeatureTest - .createFeature(ElementPropertyMap.class); - - @Test - public void testJson() { - MapPutChange change = new MapPutChange(feature, "some", "string"); - - JsonObject json = change.toJson(null); - - Assert.assertEquals(change.getNode().getId(), - (int) json.getNumber(JsonConstants.CHANGE_NODE)); - Assert.assertEquals(NodeFeatureRegistry.getId(feature.getClass()), - (int) json.getNumber(JsonConstants.CHANGE_FEATURE)); - Assert.assertEquals(JsonConstants.CHANGE_TYPE_PUT, - json.getString(JsonConstants.CHANGE_TYPE)); - Assert.assertEquals("some", - json.getString(JsonConstants.CHANGE_MAP_KEY)); - Assert.assertEquals("string", - json.getString(JsonConstants.CHANGE_PUT_VALUE)); - } - - @Test - public void testJsonValueTypes() { - JsonValue stringValue = getValue("string"); - Assert.assertSame(JsonType.STRING, stringValue.getType()); - Assert.assertEquals("string", stringValue.asString()); - - JsonValue numberValue = getValue(Integer.valueOf(1)); - Assert.assertSame(JsonType.NUMBER, numberValue.getType()); - Assert.assertEquals(1, numberValue.asNumber(), 0); - - JsonValue booleanValue = getValue(Boolean.TRUE); - Assert.assertSame(JsonType.BOOLEAN, booleanValue.getType()); - Assert.assertTrue(booleanValue.asBoolean()); - - JsonObject jsonInput = Json.createObject(); - JsonValue jsonValue = getValue(jsonInput); - Assert.assertSame(JsonType.OBJECT, jsonValue.getType()); - Assert.assertSame(jsonInput, jsonValue); - } - - @Test - public void testNodeValueType() { - StateNode value = StateNodeTest.createEmptyNode("value"); - MapPutChange change = new MapPutChange(feature, "myKey", value); - - JsonObject json = change.toJson(null); - Assert.assertFalse(json.hasKey(JsonConstants.CHANGE_PUT_VALUE)); - - JsonValue nodeValue = json.get(JsonConstants.CHANGE_PUT_NODE_VALUE); - Assert.assertSame(JsonType.NUMBER, nodeValue.getType()); - Assert.assertEquals(value.getId(), (int) nodeValue.asNumber()); - } - - private JsonValue getValue(Object input) { - MapPutChange change = new MapPutChange(feature, "myKey", input); - JsonObject json = change.toJson(null); - return json.get(JsonConstants.CHANGE_PUT_VALUE); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/change/MapRemoveChangeTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/change/MapRemoveChangeTest.java deleted file mode 100644 index 680dfa3da20..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/change/MapRemoveChangeTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.change; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.nodefeature.AbstractNodeFeatureTest; -import com.vaadin.flow.internal.nodefeature.ElementPropertyMap; -import com.vaadin.flow.internal.nodefeature.NodeFeatureRegistry; -import com.vaadin.flow.internal.nodefeature.NodeMap; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.JsonObject; - -public class MapRemoveChangeTest { - private NodeMap feature = AbstractNodeFeatureTest - .createFeature(ElementPropertyMap.class); - - @Test - public void testJson() { - MapRemoveChange change = new MapRemoveChange(feature, "some"); - - JsonObject json = change.toJson(null); - - Assert.assertEquals(change.getNode().getId(), - (int) json.getNumber(JsonConstants.CHANGE_NODE)); - Assert.assertEquals(NodeFeatureRegistry.getId(feature.getClass()), - (int) json.getNumber(JsonConstants.CHANGE_FEATURE)); - Assert.assertEquals(JsonConstants.CHANGE_TYPE_REMOVE, - json.getString(JsonConstants.CHANGE_TYPE)); - Assert.assertEquals("some", - json.getString(JsonConstants.CHANGE_MAP_KEY)); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AbstractMapFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AbstractMapFeatureTest.java deleted file mode 100644 index c3332431738..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AbstractMapFeatureTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.junit.Assert; - -public abstract class AbstractMapFeatureTest - extends AbstractNodeFeatureTest { - - protected void testString(NodeMap mapFeature, String key, - Consumer setter, Supplier getter) { - String value1 = "foo"; - String value2 = "bar"; - - setter.accept(value1); - Assert.assertEquals(value1, getter.get()); - Assert.assertEquals(value1, mapFeature.get(key)); - - mapFeature.put(key, value2); - Assert.assertEquals(value2, getter.get()); - } - - protected void testInt(NodeMap mapFeature, String key, - Consumer setter, Supplier getter) { - Integer value1 = 37; - Integer value2 = 5844; - - setter.accept(value1); - Assert.assertEquals(value1, getter.get()); - Assert.assertEquals(value1, mapFeature.get(key)); - - mapFeature.put(key, value2); - Assert.assertEquals(value2, getter.get()); - } - - protected void testBoolean(NodeMap mapFeature, String key, - Consumer setter, Supplier getter) { - Boolean value1 = true; - Boolean value2 = false; - - setter.accept(value1); - Assert.assertEquals(value1, getter.get()); - Assert.assertEquals(value1, mapFeature.get(key)); - - mapFeature.put(key, value2); - Assert.assertEquals(value2, getter.get()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AbstractNodeFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AbstractNodeFeatureTest.java deleted file mode 100644 index 710bed866f9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AbstractNodeFeatureTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import java.lang.reflect.ParameterizedType; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.change.NodeChange; - -public abstract class AbstractNodeFeatureTest { - - public T createFeature() { - Class featureType = findFeatureType(); - - return createFeature(featureType); - } - - public static T createFeature( - Class featureType) { - StateNode node = new StateNode(featureType); - - return node.getFeature(featureType); - } - - @SuppressWarnings("unchecked") - private Class findFeatureType() { - ParameterizedType genericSuperclass = (ParameterizedType) getClass() - .getGenericSuperclass(); - - Class paramType = (Class) genericSuperclass - .getActualTypeArguments()[0]; - - Class featureType = paramType - .asSubclass(NodeFeature.class); - - return (Class) featureType; - } - - public List collectChanges(NodeFeature feature) { - List changes = new ArrayList<>(); - - feature.collectChanges(changes::add); - // Explicitly clear since collecting from one feature doesn't - feature.getNode().clearChanges(); - - return changes; - } - - protected void assertNodeEquals(StateNode node1, StateNode node2) { - Assert.assertEquals(node1.getId(), node2.getId()); - NodeFeatureRegistry.nodeFeatures.keySet().forEach(k -> { - Assert.assertEquals(node1.hasFeature(k), node2.hasFeature(k)); - if (node1.hasFeature(k)) { - assertFeaturesEquals(node1.getFeature(k), node2.getFeature(k)); - } - }); - - } - - @SuppressWarnings("rawtypes") - protected void assertFeaturesEquals(NodeFeature feature1, - NodeFeature feature2) { - Assert.assertEquals(feature1.getClass(), feature2.getClass()); - if (feature1 instanceof NodeMap) { - assertMapFeatureEquals((NodeMap) feature1, (NodeMap) feature2); - } else if (feature1 instanceof NodeList) { - assertListFeatureEquals((NodeList) feature1, (NodeList) feature2); - } else { - Assert.fail( - "Unknown feature type " + feature1.getClass().getName()); - } - } - - @SuppressWarnings("rawtypes") - protected void assertListFeatureEquals(NodeList feature1, - NodeList feature2) { - Assert.assertEquals(feature1.size(), feature2.size()); - for (int i = 0; i < feature1.size(); i++) { - Assert.assertEquals(feature1.get(i), feature2.get(i)); - } - } - - protected void assertMapFeatureEquals(NodeMap feature1, NodeMap feature2) { - Assert.assertEquals(feature1.keySet().size(), feature2.keySet().size()); - feature1.keySet().forEach(k -> { - Assert.assertEquals(feature1.get(k), feature2.get(k)); - }); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AttachExistingElementFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AttachExistingElementFeatureTest.java deleted file mode 100644 index 945b85145df..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/AttachExistingElementFeatureTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.dom.ChildElementConsumer; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.Node; -import com.vaadin.flow.internal.StateNode; - -public class AttachExistingElementFeatureTest { - - @Test - public void register_dataIsAvailaleByNode() { - StateNode node = new StateNode(); - AttachExistingElementFeature feature = new AttachExistingElementFeature( - node); - - Element element = Mockito.mock(Element.class); - StateNode child = Mockito.mock(StateNode.class); - ChildElementConsumer callback = Mockito - .mock(ChildElementConsumer.class); - Node parent = Mockito.mock(Node.class); - feature.register(parent, element, child, callback); - - Mockito.verify(child).setParent(node); - - Assert.assertEquals(callback, feature.getCallback(child)); - Assert.assertEquals(parent, feature.getParent(child)); - Assert.assertEquals(element, feature.getPreviousSibling(child)); - } - - @Test - public void forEachChild_register_registeredStatNodeIsAChild() { - StateNode node = new StateNode(); - AttachExistingElementFeature feature = new AttachExistingElementFeature( - node); - - Element element = Mockito.mock(Element.class); - StateNode child = Mockito.mock(StateNode.class); - ChildElementConsumer callback = Mockito - .mock(ChildElementConsumer.class); - Node parent = Mockito.mock(Node.class); - feature.register(parent, element, child, callback); - - List children = new ArrayList<>(1); - feature.forEachChild(children::add); - Assert.assertEquals(1, children.size()); - Assert.assertEquals(child, children.get(0)); - } - - @Test - public void unregister_dataIsNotAvailaleByNode() { - StateNode node = new StateNode(); - AttachExistingElementFeature feature = new AttachExistingElementFeature( - node); - - Element element = Mockito.mock(Element.class); - StateNode child = Mockito.mock(StateNode.class); - ChildElementConsumer callback = Mockito - .mock(ChildElementConsumer.class); - Node parent = Mockito.mock(Node.class); - feature.register(parent, element, child, callback); - - feature.unregister(child); - - Assert.assertNull(feature.getCallback(child)); - Assert.assertNull(feature.getParent(child)); - Assert.assertNull(feature.getPreviousSibling(child)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ClientCallableHandlersTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ClientCallableHandlersTest.java deleted file mode 100644 index f2861f5a6bb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ClientCallableHandlersTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.ClientCallable; -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateTree; - -public class ClientCallableHandlersTest { - - @Tag("div") - static class NonTemplateComponentWithoutEventHandler extends Component { - } - - @Tag("div") - static class NonTemplateComponentWithEventHandler extends Component { - - @ClientCallable - public void publishedMethod1() { - - } - } - - @Test - public void attach_noFeature() { - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - - StateNode stateNode = new StateNode(ClientCallableHandlers.class); - - tree.getRootNode().getFeature(ElementChildrenList.class).add(stateNode); - Assert.assertEquals(0, - stateNode.getFeature(ClientCallableHandlers.class).size()); - } - - @Test - public void attach_noComponent() { - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - - StateNode stateNode = new StateNode(ComponentMapping.class, - ClientCallableHandlers.class); - - tree.getRootNode().getFeature(ElementChildrenList.class).add(stateNode); - Assert.assertEquals(0, - stateNode.getFeature(ClientCallableHandlers.class).size()); - } - - @Test - public void nonTemplateComponentWithEventHandler() { - UI ui = new UI(); - NonTemplateComponentWithEventHandler component = new NonTemplateComponentWithEventHandler(); - ui.add(component); - - ClientCallableHandlers feature = component.getElement().getNode() - .getFeature(ClientCallableHandlers.class); - assertListFeature(feature, "publishedMethod1"); - } - - @Test - public void nonTemplateComponentWithoutEventHandler() { - UI ui = new UI(); - NonTemplateComponentWithoutEventHandler component = new NonTemplateComponentWithoutEventHandler(); - ui.add(component); - - ClientCallableHandlers feature = component.getElement().getNode() - .getFeature(ClientCallableHandlers.class); - assertListFeature(feature); - } - - private void assertListFeature(SerializableNodeList feature, - String... expected) { - Assert.assertEquals(expected.length, feature.size()); - for (int i = 0; i < expected.length; i++) { - Assert.assertEquals(expected[i], feature.get(i)); - } - - } - - private Stream getDeclaredMethods(Class clazz) { - // Code coverage jacoco adds nice unexpected private static method - // $jacocoInit which nobody needs - return Stream.of(clazz.getDeclaredMethods()) - .filter(method -> !Modifier.isStatic(method.getModifiers()) - && !Modifier.isPrivate(method.getModifiers())) - .map(Method::getName); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/DependencyListTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/DependencyListTest.java deleted file mode 100644 index 5e04e1c5ae4..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/DependencyListTest.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.DependencyList; -import com.vaadin.flow.internal.JsonUtils; -import com.vaadin.flow.shared.ui.Dependency; -import com.vaadin.flow.shared.ui.Dependency.Type; -import com.vaadin.flow.shared.ui.LoadMode; -import com.vaadin.tests.util.MockUI; - -import elemental.json.Json; -import elemental.json.JsonObject; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -@NotThreadSafe -public class DependencyListTest { - private static final String URL = "https://example.net/"; - - private MockUI ui; - private DependencyList deps; - - @Before - public void before() { - ui = MockUI.createUI(); - deps = ui.getInternals().getDependencyList(); - - assertEquals(0, deps.getPendingSendToClient().size()); - } - - @After - public void after() { - UI.setCurrent(null); - } - - @Test - public void addStyleSheetDependency_eager1() { - ui.getPage().addStyleSheet(URL); - validateDependency(URL, Type.STYLESHEET, LoadMode.EAGER); - } - - @Test - public void addStyleSheetDependency_eager2() { - ui.getPage().addStyleSheet(URL, LoadMode.EAGER); - validateDependency(URL, Type.STYLESHEET, LoadMode.EAGER); - } - - @Test - public void addStyleSheetDependency_lazy() { - ui.getPage().addStyleSheet(URL, LoadMode.LAZY); - validateDependency(URL, Type.STYLESHEET, LoadMode.LAZY); - } - - @Test - public void addStyleSheetDependency_inline() { - ui.getPage().addStyleSheet(URL, LoadMode.INLINE); - validateDependency(URL, Type.STYLESHEET, LoadMode.INLINE); - } - - @Test - public void addJavaScriptDependency_eager1() { - ui.getPage().addJavaScript(URL); - validateDependency(URL, Type.JAVASCRIPT, LoadMode.EAGER); - } - - @Test - public void addJavaScriptDependency_eager2() { - ui.getPage().addJavaScript(URL, LoadMode.EAGER); - validateDependency(URL, Type.JAVASCRIPT, LoadMode.EAGER); - } - - @Test - public void addJavaScriptDependency_lazy() { - ui.getPage().addJavaScript(URL, LoadMode.LAZY); - validateDependency(URL, Type.JAVASCRIPT, LoadMode.LAZY); - } - - @Test - public void addJavaScriptDependency_inline() { - ui.getPage().addJavaScript(URL, LoadMode.INLINE); - validateDependency(URL, Type.JAVASCRIPT, LoadMode.INLINE); - } - - private void validateDependency(String url, Type dependencyType, - LoadMode loadMode) { - JsonObject expectedJson = Json.createObject(); - expectedJson.put(Dependency.KEY_URL, url); - expectedJson.put(Dependency.KEY_TYPE, dependencyType.name()); - expectedJson.put(Dependency.KEY_LOAD_MODE, loadMode.name()); - - assertEquals("Expected to receive exactly one dependency", 1, - deps.getPendingSendToClient().size()); - assertTrue(String.format( - "Dependencies' json representations are different, expected = \n'%s'\n, actual = \n'%s'", - expectedJson.toJson(), - deps.getPendingSendToClient().iterator().next().toJson()), - JsonUtils.jsonEquals(expectedJson, deps.getPendingSendToClient() - .iterator().next().toJson())); - } - - @Test - public void specialUrls() { - assertUrlUnchanged("/foo?bar"); - assertUrlUnchanged("/foo/baz?bar=http://some.thing"); - assertUrlUnchanged("/foo/baz?bar=http://some.thing&ftp://bar"); - assertUrlUnchanged("http://foo?bar"); - assertUrlUnchanged("http://foo/baz"); - assertUrlUnchanged("http://foo/baz?bar"); - assertUrlUnchanged("http://foo/baz?bar=http://some.thing"); - assertUrlUnchanged("ftp://some.host/some/where"); - assertUrlUnchanged("https://some.host/some/where"); - assertUrlUnchanged("//same.protocol.some.host/some/where"); - assertUrlUnchanged("context://foo?bar=frontend://baz"); - } - - private void assertUrlUnchanged(String url) { - assertDependencyUrl(url, url); - } - - private void assertDependencyUrl(String expectedUrl, String dependencyUrl) { - addSimpleDependency(dependencyUrl); - assertEquals(expectedUrl, - deps.getPendingSendToClient().iterator().next().getUrl()); - deps.clearPendingSendToClient(); - } - - @Test - public void urlAddedOnlyOnce() { - addSimpleDependency("foo/bar.js"); - addSimpleDependency("foo/bar.js"); - assertEquals(1, deps.getPendingSendToClient().size()); - deps.clearPendingSendToClient(); - - addSimpleDependency("foo/bar.js"); - assertEquals(0, deps.getPendingSendToClient().size()); - } - - private void addSimpleDependency(String foo) { - deps.add(new Dependency(Type.JAVASCRIPT, foo, LoadMode.EAGER)); - } - - @Test - public void addSameDependencyInDifferentModes_usesMostEagerLoadMode() { - testAddingDuplicateDependencies(LoadMode.EAGER, LoadMode.EAGER, - LoadMode.EAGER); - testAddingDuplicateDependencies(LoadMode.EAGER, LoadMode.LAZY, - LoadMode.EAGER); - testAddingDuplicateDependencies(LoadMode.EAGER, LoadMode.INLINE, - LoadMode.INLINE); - - testAddingDuplicateDependencies(LoadMode.LAZY, LoadMode.EAGER, - LoadMode.EAGER); - testAddingDuplicateDependencies(LoadMode.LAZY, LoadMode.LAZY, - LoadMode.LAZY); - testAddingDuplicateDependencies(LoadMode.LAZY, LoadMode.INLINE, - LoadMode.INLINE); - - testAddingDuplicateDependencies(LoadMode.INLINE, LoadMode.EAGER, - LoadMode.INLINE); - testAddingDuplicateDependencies(LoadMode.INLINE, LoadMode.LAZY, - LoadMode.INLINE); - testAddingDuplicateDependencies(LoadMode.INLINE, LoadMode.INLINE, - LoadMode.INLINE); - - } - - private void testAddingDuplicateDependencies(LoadMode first, - LoadMode second, LoadMode expected) { - - String url = "foo/bar.js"; - Type type = Type.JAVASCRIPT; - - // need to clear so that there is no leftovers - deps = new DependencyList(); - deps.add(new Dependency(type, url, first)); - deps.add(new Dependency(type, url, second)); - - Collection pendingSendToClient = deps - .getPendingSendToClient(); - assertEquals("Expected to have only one dependency", 1, - pendingSendToClient.size()); - assertEquals("Wrong load mode resolved", - pendingSendToClient.iterator().next().getLoadMode(), expected); - } - - @Test - public void addDependencyPerformance() { - long start = System.currentTimeMillis(); - for (int i = 0; i < 10000; i++) { - addSimpleDependency("foo" + i + "/bar.js"); - } - long time = System.currentTimeMillis() - start; - - assertTrue("Adding 10K dependencies should take about 50ms. Took " - + time + "ms", time < 500); - } - - @Test - public void ensureDependenciesSentToClientHaveTheSameOrderAsAdded() { - Dependency eagerJs = new Dependency(Type.JAVASCRIPT, "eager.js", - LoadMode.EAGER); - Dependency eagerCss = new Dependency(Type.STYLESHEET, "eager.css", - LoadMode.EAGER); - Dependency lazyJs = new Dependency(Type.JAVASCRIPT, "lazy.js", - LoadMode.LAZY); - Dependency lazyCss = new Dependency(Type.STYLESHEET, "lazy.css", - LoadMode.LAZY); - assertEquals("Expected the dependency to be eager", LoadMode.EAGER, - eagerJs.getLoadMode()); - assertEquals("Expected the dependency to be eager", LoadMode.EAGER, - eagerCss.getLoadMode()); - assertEquals("Expected the dependency to be lazy", LoadMode.LAZY, - lazyJs.getLoadMode()); - assertEquals("Expected the dependency to be lazy", LoadMode.LAZY, - lazyCss.getLoadMode()); - - List dependencies = new ArrayList<>( - Arrays.asList(eagerJs, eagerCss, lazyJs, lazyCss)); - assertEquals("Expected to have 4 dependencies", 4, dependencies.size()); - - Collections.shuffle(dependencies); - dependencies.forEach(deps::add); - List pendingSendToClient = new ArrayList<>( - deps.getPendingSendToClient()); - - for (int i = 0; i < pendingSendToClient.size(); i++) { - Dependency actualDependency = pendingSendToClient.get(i); - Dependency expectedDependency = dependencies.get(i); - assertEquals( - "Expected to have the same dependency on the same position for list, but urls do not match", - expectedDependency.getUrl(), actualDependency.getUrl()); - assertEquals( - "Expected to have the same dependency on the same position for list, but load modes do not match", - expectedDependency.getLoadMode(), - actualDependency.getLoadMode()); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementDataTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementDataTest.java deleted file mode 100644 index 207022e0d88..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementDataTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.NodeChange; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class ElementDataTest extends AbstractNodeFeatureTest { - private final ElementData elementData = new StateNode( - Collections.singletonList(ElementData.class)) - .getFeature(ElementData.class); - - @Test - public void setGetTag() { - Assert.assertNull("Tag should initially be null", elementData.getTag()); - - elementData.setTag("myTag"); - - Assert.assertEquals("myTag", elementData.getTag()); - } - - @Test - public void setGetPayload() { - Assert.assertNull("Tag should initially be null", - elementData.getPayload()); - - JsonObject object = Json.createObject(); - elementData.setPayload(object); - - Assert.assertEquals(object, elementData.getPayload()); - } - - @Test - public void collectChanges_setTagOnly_onlyOneChanges() { - elementData.setTag("foo"); - List changes = new ArrayList<>(); - elementData.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - - MapPutChange change = (MapPutChange) changes.get(0); - - Assert.assertEquals(NodeProperties.TAG, change.getKey()); - Assert.assertEquals(elementData.getNode(), change.getNode()); - Assert.assertEquals("foo", change.getValue()); - } - - @Test - public void collectChanges_setPayloadOnly_onlyOneChanges() { - JsonObject object = Json.createObject(); - elementData.setPayload(object); - List changes = new ArrayList<>(); - elementData.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - MapPutChange change = (MapPutChange) changes.get(0); - - Assert.assertEquals(NodeProperties.PAYLOAD, change.getKey()); - Assert.assertEquals(elementData.getNode(), change.getNode()); - Assert.assertEquals(object, change.getValue()); - } - - @Test - public void collectChanges_setBothTagAndPayload_twoChanges() { - JsonObject object = Json.createObject(); - elementData.setPayload(object); - elementData.setTag("foo"); - - List changes = new ArrayList<>(); - elementData.collectChanges(changes::add); - - Assert.assertEquals(2, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - Assert.assertTrue(changes.get(1) instanceof MapPutChange); - - MapPutChange change = getChange(changes, NodeProperties.TAG); - Assert.assertEquals(NodeProperties.TAG, change.getKey()); - Assert.assertEquals(elementData.getNode(), change.getNode()); - Assert.assertEquals("foo", change.getValue()); - - change = getChange(changes, NodeProperties.PAYLOAD); - Assert.assertEquals(NodeProperties.PAYLOAD, change.getKey()); - Assert.assertEquals(elementData.getNode(), change.getNode()); - Assert.assertEquals(object, change.getValue()); - } - - private MapPutChange getChange(List changes, String key) { - Optional keyFound = changes.stream() - .filter(MapPutChange.class::isInstance) - .map(MapPutChange.class::cast) - .filter(chang -> chang.getKey().equals(key)).findFirst(); - Assert.assertTrue("No " + key + " change found", keyFound.isPresent()); - return keyFound.get(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementListenersTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementListenersTest.java deleted file mode 100644 index bbdad32ebbd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementListenersTest.java +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.io.Serializable; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.DisabledUpdateMode; -import com.vaadin.flow.dom.DomEvent; -import com.vaadin.flow.dom.DomEventListener; -import com.vaadin.flow.dom.DomListenerRegistration; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.shared.JsonConstants; -import com.vaadin.flow.shared.Registration; - -import elemental.json.Json; -import elemental.json.JsonObject; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; - -public class ElementListenersTest - extends AbstractNodeFeatureTest { - private static final DomEventListener noOp = e -> { - // no op - }; - - private ElementListenerMap ns; - - @Before - public void init() { - ns = createFeature(); - } - - @Test - public void addedListenerGetsEvent() { - - AtomicInteger eventCount = new AtomicInteger(); - - Registration handle = ns.add("foo", e -> eventCount.incrementAndGet()); - - Assert.assertEquals(0, eventCount.get()); - - ns.fireEvent(createEvent("foo")); - - Assert.assertEquals(1, eventCount.get()); - - handle.remove(); - - ns.fireEvent(createEvent("foo")); - - Assert.assertEquals(1, eventCount.get()); - } - - @Test - public void eventNameInClientData() { - Assert.assertFalse(ns.contains("foo")); - - Registration handle = ns.add("foo", noOp); - - Assert.assertEquals(0, getExpressions("foo").size()); - - handle.remove(); - - Assert.assertFalse(ns.contains("foo")); - } - - @Test - public void addAndRemoveEventData() { - ns.add("eventType", noOp).addEventData("data1").addEventData("data2"); - - Set expressions = getExpressions("eventType"); - Assert.assertTrue(expressions.contains("data1")); - Assert.assertTrue(expressions.contains("data2")); - Assert.assertFalse(expressions.contains("data3")); - - Registration handle = ns.add("eventType", new DomEventListener() { - /* - * Can't use the existing noOp instance since there would then not - * be any listeners left after calling remove() - */ - - @Override - public void handleEvent(DomEvent event) { - // no op - } - }).addEventData("data3"); - - expressions = getExpressions("eventType"); - Assert.assertTrue(expressions.contains("data1")); - Assert.assertTrue(expressions.contains("data2")); - Assert.assertTrue(expressions.contains("data3")); - - handle.remove(); - - expressions = getExpressions("eventType"); - Assert.assertTrue(expressions.contains("data1")); - Assert.assertTrue(expressions.contains("data2")); - // due to fix to #5090, data3 won't be present after removal - Assert.assertFalse(expressions.contains("data3")); - } - - @Test - public void settingsAreOnlyUpdated_should_ListenersSharingTheTypeOfRemovedListenerExist() { - ns = spy(createFeature()); - DomEventListener del1 = event -> { - }; - DomEventListener del2 = event -> { - }; - DomEventListener del3 = event -> { - }; - Registration handle1 = ns.add("eventType", del1).addEventData("data1"); - Registration handle2 = ns.add("eventType", del2).addEventData("data2"); - Registration handle3 = ns.add("eventTypeOther", del3) - .addEventData("data3"); - Mockito.reset(ns); - - Set expressions = getExpressions("eventType"); - expressions.addAll(getExpressions("eventTypeOther")); - - Assert.assertTrue(expressions.contains("data1")); - Assert.assertTrue(expressions.contains("data2")); - Assert.assertTrue(expressions.contains("data3")); - - handle1.remove(); - - Mockito.verify(ns, times(1)).put(eq("eventType"), - any(Serializable.class)); - - expressions = getExpressions("eventType"); - expressions.addAll(getExpressions("eventTypeOther")); - - Assert.assertFalse(expressions.contains("data1")); - Assert.assertTrue(expressions.contains("data2")); - Assert.assertTrue(expressions.contains("data3")); - - handle2.remove(); - // updating settings does not take place a second time - Mockito.verify(ns, times(1)).put(eq("eventType"), - any(Serializable.class)); - - expressions = getExpressions("eventType"); - expressions.addAll(getExpressions("eventTypeOther")); - - Assert.assertFalse(expressions.contains("data1")); - Assert.assertFalse(expressions.contains("data2")); - Assert.assertTrue(expressions.contains("data3")); - } - - @Test - public void addingRemovingAndAddingListenerOfTheSameType() { - DomEventListener del1 = event -> { - }; - DomEventListener del2 = event -> { - }; - Registration handle = ns.add("eventType", del1).addEventData("data1"); - - Set expressions = getExpressions("eventType"); - Assert.assertTrue(expressions.contains("data1")); - - handle.remove(); - expressions = getExpressions("eventType"); - Assert.assertFalse(expressions.contains("data1")); - - // re-add a listener for "eventType", using different eventData - handle = ns.add("eventType", del2).addEventData("data2"); - expressions = getExpressions("eventType"); - Assert.assertFalse(expressions.contains("data1")); - Assert.assertTrue(expressions.contains("data2")); - - handle.remove(); - expressions = getExpressions("eventType"); - Assert.assertFalse(expressions.contains("data1")); - Assert.assertFalse(expressions.contains("data2")); - } - - @Test - public void eventDataInEvent() { - AtomicReference eventDataReference = new AtomicReference<>(); - ns.add("foo", e -> { - Assert.assertNull(eventDataReference.get()); - eventDataReference.set(e.getEventData()); - }); - - Assert.assertNull(eventDataReference.get()); - - JsonObject eventData = Json.createObject(); - eventData.put("baz", true); - ns.fireEvent(new DomEvent(new Element("element"), "foo", eventData)); - - JsonObject capturedJson = eventDataReference.get(); - Assert.assertNotNull(capturedJson); - - Assert.assertEquals(1, capturedJson.keys().length); - Assert.assertEquals("true", capturedJson.get("baz").toJson()); - } - - @Test - public void disabledElement_listenerDoesntReceiveEvent() { - AtomicInteger eventCount = new AtomicInteger(); - - ns.add("foo", e -> eventCount.incrementAndGet()); - - Assert.assertEquals(0, eventCount.get()); - DomEvent event = createEvent("foo"); - event.getSource().setEnabled(false); - ns.fireEvent(event); - Assert.assertEquals(0, eventCount.get()); - } - - @Test - public void implicitlyDisabledElement_listenerDoesntReceiveEvent() { - AtomicInteger eventCount = new AtomicInteger(); - - ns.add("foo", e -> eventCount.incrementAndGet()); - - Assert.assertEquals(0, eventCount.get()); - DomEvent event = createEvent("foo"); - - Element parent = new Element("parent"); - parent.appendChild(event.getSource()); - parent.setEnabled(false); - - ns.fireEvent(event); - Assert.assertEquals(0, eventCount.get()); - } - - @Test - public void disabledElement_listenerWithAlwaysUpdateModeReceivesEvent() { - AtomicInteger eventCount = new AtomicInteger(); - - ns.add("foo", e -> eventCount.incrementAndGet()) - .setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - Assert.assertEquals(0, eventCount.get()); - DomEvent event = createEvent("foo"); - event.getSource().setEnabled(false); - ns.fireEvent(event); - Assert.assertEquals(1, eventCount.get()); - } - - @Test - public void serializable() { - ns.add("click", noOp).addEventData("eventdata"); - - ElementListenerMap roundtrip = SerializationUtils.roundtrip(ns); - - Set expressions = roundtrip.getExpressions("click"); - Assert.assertEquals(Collections.singleton("eventdata"), expressions); - } - - @Test - public void synchronizeProperty_hasSynchronizedProperty() { - DomListenerRegistration registration = ns.add("foo", noOp); - - Assert.assertNull(ns.getPropertySynchronizationMode("name")); - - registration.synchronizeProperty("anotherName"); - - Assert.assertNull(ns.getPropertySynchronizationMode("name")); - - registration.synchronizeProperty("name"); - - Assert.assertSame(DisabledUpdateMode.ONLY_WHEN_ENABLED, - ns.getPropertySynchronizationMode("name")); - } - - @Test - public void synchronizeProperty_alwaysMode() { - DomListenerRegistration registration = ns.add("foo", noOp) - .setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - registration.synchronizeProperty("name"); - - Assert.assertSame(DisabledUpdateMode.ALWAYS, - ns.getPropertySynchronizationMode("name")); - } - - @Test - public void synchronizeProperty_bothModes() { - DomListenerRegistration registration1 = ns.add("foo", noOp) - .setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - registration1.synchronizeProperty("name"); - - DomListenerRegistration registration2 = ns.add("foo", noOp); - registration2.synchronizeProperty("name"); - - Assert.assertSame(DisabledUpdateMode.ALWAYS, - ns.getPropertySynchronizationMode("name")); - } - - @Test - public void synchronizeProperty_hasExpressionToken() { - DomListenerRegistration registration = ns.add("foo", noOp); - - Assert.assertEquals(Collections.emptySet(), getExpressions("foo")); - - registration.synchronizeProperty("name"); - - Assert.assertEquals( - Collections.singleton( - JsonConstants.SYNCHRONIZE_PROPERTY_TOKEN + "name"), - getExpressions("foo")); - } - - @Test(expected = IllegalArgumentException.class) - public void synchronizeProperty_nullArgument_illegalArgumentException() { - DomListenerRegistration registration = ns.add("foo", noOp); - - registration.synchronizeProperty(null); - } - - @Test(expected = IllegalArgumentException.class) - public void synchronizeProperty_emptyArgument_illegalArgumentException() { - DomListenerRegistration registration = ns.add("foo", noOp); - - registration.synchronizeProperty(""); - } - - @Test - public void mapEventTargetToElement_targetNodeIdInJsonData_elementMapped() { - Element parent = new Element("parent"); - Element child = new Element("child"); - Element grandChild = new Element("grandChild"); - parent.appendChild(child.appendChild(grandChild)); - new StateTree(new UI().getInternals(), ElementChildrenList.class) - .getUI().getElement().appendChild(parent); - final String eventType = "click"; - - AtomicReference capturedTarget = new AtomicReference<>(); - final DomListenerRegistration registration = parent - .addEventListener(eventType, e -> { - capturedTarget.set(e.getEventTarget().orElse(null)); - }); - final ElementListenerMap listenerMap = parent.getNode() - .getFeature(ElementListenerMap.class); - Set expressions = getExpressions(listenerMap, eventType); - Assert.assertEquals(0, expressions.size()); - - registration.mapEventTargetElement(); - expressions = getExpressions(listenerMap, eventType); - - Assert.assertEquals(1, expressions.size()); - Assert.assertEquals(JsonConstants.MAP_STATE_NODE_EVENT_DATA, - expressions.iterator().next()); - - // child - final JsonObject eventData = Json.createObject(); - eventData.put(JsonConstants.MAP_STATE_NODE_EVENT_DATA, - child.getNode().getId()); - listenerMap.fireEvent(new DomEvent(parent, eventType, eventData)); - Assert.assertEquals(child, capturedTarget.get()); - - // nothing reported -> empty optional - listenerMap.fireEvent( - new DomEvent(parent, eventType, Json.createObject())); - Assert.assertNull("no element should be reported", - capturedTarget.get()); - - // grandchild - eventData.put(JsonConstants.MAP_STATE_NODE_EVENT_DATA, - grandChild.getNode().getId()); - listenerMap.fireEvent(new DomEvent(parent, eventType, eventData)); - Assert.assertEquals(grandChild, capturedTarget.get()); - - // -1 -> empty optional - eventData.put(JsonConstants.MAP_STATE_NODE_EVENT_DATA, -1); - listenerMap.fireEvent(new DomEvent(parent, eventType, eventData)); - Assert.assertNull("no element should be reported", - capturedTarget.get()); - } - - @Test - public void addEventDataElement_targetNodeInJsonData_elementMapped() { - Element parent = new Element("parent"); - Element child = new Element("child"); - Element sibling = new Element("sibling"); - parent.appendChild(child); - new StateTree(new UI().getInternals(), ElementChildrenList.class) - .getUI().getElement().appendChild(parent, sibling); - final String eventType = "click"; - final String expression = "expression"; - final String key = JsonConstants.MAP_STATE_NODE_EVENT_DATA + expression; - - AtomicReference capturedTarget = new AtomicReference<>(); - final DomListenerRegistration registration = parent - .addEventListener(eventType, capturedTarget::set); - final ElementListenerMap listenerMap = parent.getNode() - .getFeature(ElementListenerMap.class); - - Set expressions = getExpressions(listenerMap, eventType); - Assert.assertEquals(0, expressions.size()); - - registration.addEventDataElement(expression); - expressions = getExpressions(listenerMap, eventType); - - Assert.assertEquals(1, expressions.size()); - Assert.assertEquals(key, expressions.iterator().next()); - - final JsonObject eventData = Json.createObject(); - eventData.put(key, child.getNode().getId()); - listenerMap.fireEvent(new DomEvent(parent, eventType, eventData)); - Assert.assertEquals(child, - capturedTarget.get().getEventDataElement(expression).get()); - - // nothing reported -> empty optional - listenerMap.fireEvent( - new DomEvent(parent, eventType, Json.createObject())); - Assert.assertFalse("no element should be reported", capturedTarget.get() - .getEventDataElement(expression).isPresent()); - - // sibling - eventData.put(key, sibling.getNode().getId()); - listenerMap.fireEvent(new DomEvent(parent, eventType, eventData)); - Assert.assertEquals(sibling, - capturedTarget.get().getEventDataElement(expression).get()); - } - - @Test - public void addEventDataElement_eventTarget_usesMapEventTargetInstead() { - Element parent = new Element("parent"); - Element child = new Element("child"); - parent.appendChild(child); - new StateTree(new UI().getInternals(), ElementChildrenList.class) - .getUI().getElement().appendChild(parent); - - final String eventType = "click"; - AtomicReference capturedTarget = new AtomicReference<>(); - final DomListenerRegistration registration = parent - .addEventListener(eventType, capturedTarget::set); - final ElementListenerMap listenerMap = parent.getNode() - .getFeature(ElementListenerMap.class); - - registration.addEventDataElement("event.target"); - Set expressions = getExpressions(listenerMap, eventType); - - Assert.assertEquals(1, expressions.size()); - Assert.assertEquals(JsonConstants.MAP_STATE_NODE_EVENT_DATA, - expressions.iterator().next()); - - final JsonObject eventData = Json.createObject(); - eventData.put(JsonConstants.MAP_STATE_NODE_EVENT_DATA, - child.getNode().getId()); - listenerMap.fireEvent(new DomEvent(parent, eventType, eventData)); - Assert.assertEquals(child, capturedTarget.get().getEventTarget().get()); - Assert.assertEquals(child, - capturedTarget.get().getEventDataElement("event.target").get()); - } - - @Test - public void eventDataKeyNotPresentNotFail() { - AtomicInteger eventCount = new AtomicInteger(); - DomListenerRegistration registration = ns.add("foo", - e -> eventCount.incrementAndGet()); - registration.setFilter("filterKey"); - - ns.fireEvent(createEvent("foo")); - Assert.assertEquals(0, eventCount.get()); - - JsonObject eventData = Json.createObject(); - eventData.put("filterKey", true); - ns.fireEvent(new DomEvent(new Element("element"), "foo", eventData)); - Assert.assertEquals(1, eventCount.get()); - } - - // Helper for accessing package private API from other tests - public static Set getExpressions( - ElementListenerMap elementListenerMap, String eventName) { - return new HashSet<>(elementListenerMap.getExpressions(eventName)); - } - - private Set getExpressions(String name) { - return getExpressions(ns, name); - } - - private static DomEvent createEvent(String type) { - return new DomEvent(new Element("fake"), type, Json.createObject()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementPropertyMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementPropertyMapTest.java deleted file mode 100644 index 487f7e89c76..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ElementPropertyMapTest.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.dom.DomListenerRegistration; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.PropertyChangeEvent; -import com.vaadin.flow.dom.PropertyChangeListener; -import com.vaadin.flow.dom.impl.BasicElementStateProvider; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.shared.Registration; - -public class ElementPropertyMapTest { - - @Test - public void addPropertyChangeListener_fireServerEvent_listenerIsNotified() { - listenerIsNotified(false); - } - - @Test - public void addPropertyChangeListener_fireClientEvent_listenerIsNotified() { - listenerIsNotified(true); - } - - @Test - public void removeProperty_fireEvent_listenerIsNotNotified() { - ElementPropertyMap map = createSimplePropertyMap(); - - map.setProperty("foo", "bar"); - - AtomicReference event = new AtomicReference<>(); - PropertyChangeListener listener = ev -> { - Assert.assertNull(event.get()); - event.set(ev); - }; - map.addPropertyChangeListener("foo", listener); - - map.remove("foo"); - Assert.assertNull(event.get().getValue()); - Assert.assertEquals("bar", event.get().getOldValue()); - Assert.assertEquals("foo", event.get().getPropertyName()); - Assert.assertEquals(Element.get(map.getNode()), - event.get().getSource()); - Assert.assertTrue(event.get().isUserOriginated()); - } - - @Test - public void removePropertyChangeListener_fireEvent_listenerIsNotNotified() { - ElementPropertyMap map = createSimplePropertyMap(); - PropertyChangeListener listener = ev -> { - Assert.fail(); - }; - Registration registration = map.addPropertyChangeListener("foo", - listener); - registration.remove(); - - // listener is not called. Otherwise its assertion fails. - map.setProperty("foo", "bar", true); - } - - @Test - public void addSeveralPropertyChangeListeners_fireEvent_listenersAreNotified() { - ElementPropertyMap map = createSimplePropertyMap(); - AtomicBoolean first = new AtomicBoolean(); - AtomicBoolean second = new AtomicBoolean(); - PropertyChangeListener listener1 = ev -> first.set(!first.get()); - PropertyChangeListener listener2 = ev -> second.set(!second.get()); - map.addPropertyChangeListener("foo", listener1); - map.addPropertyChangeListener("foo", listener2); - - map.setProperty("foo", "bar", true); - - Assert.assertTrue(first.get()); - Assert.assertTrue(second.get()); - } - - @Test - public void resolveModelList_modelListStateNodeHasReportedFeature() { - ElementPropertyMap map = createSimplePropertyMap(); - map.resolveModelList("foo"); - - StateNode stateNode = (StateNode) map.get("foo"); - Assert.assertTrue(stateNode.isReportedFeature(ModelList.class)); - } - - @Test - public void resolveModelMap_modelMapStateNodeHasReportedFeature() { - ElementPropertyMap map = createSimplePropertyMap(); - map.resolveModelMap("foo"); - - StateNode stateNode = (StateNode) map.get("foo"); - Assert.assertTrue( - stateNode.isReportedFeature(ElementPropertyMap.class)); - } - - @Test - public void put_ignoreSameValue() { - ElementPropertyMap map = createSimplePropertyMap(); - - AtomicReference value = new AtomicReference<>(); - map.addPropertyChangeListener("foo", event -> { - Assert.assertNull(value.get()); - value.set(event.getValue()); - }); - map.setProperty("foo", "bar"); - - Assert.assertEquals("bar", value.get()); - - // Doesn't throw assertion error because listener is not called - map.setProperty("foo", "bar"); - } - - @Test - public void basicUpdateFromClientFilter() { - ElementPropertyMap map = createSimplePropertyMap(); - - Set clientFilterQueries = new HashSet<>(); - // Allow updating the same property only once - map.setUpdateFromClientFilter(name -> clientFilterQueries.add(name)); - - Assert.assertTrue(map.mayUpdateFromClient("foo", "bar")); - Assert.assertFalse(map.mayUpdateFromClient("foo", "bar")); - } - - @Test - public void updateSynchronizedPropertyDespiteFilter() { - ElementPropertyMap map = createSimplePropertyMap(); - - map.setUpdateFromClientFilter(name -> false); - Assert.assertFalse(map.mayUpdateFromClient("foo", "bar")); - - DomListenerRegistration domListenerRegistration = Element - .get(map.getNode()) - .addPropertyChangeListener("foo", "event", event -> { - }); - Assert.assertTrue(map.mayUpdateFromClient("foo", "bar")); - - domListenerRegistration.remove(); - Assert.assertFalse(map.mayUpdateFromClient("foo", "bar")); - - DomListenerRegistration registration = Element.get(map.getNode()) - .addEventListener("dummy", event -> { - }).synchronizeProperty("foo"); - Assert.assertTrue(map.mayUpdateFromClient("foo", "bar")); - - registration.remove(); - Assert.assertFalse(map.mayUpdateFromClient("foo", "bar")); - } - - @Test - public void updateFromClientFilter_replaceFilter() { - ElementPropertyMap map = createSimplePropertyMap(); - - map.setUpdateFromClientFilter("foo"::equals); - - Assert.assertTrue(map.mayUpdateFromClient("foo", "a")); - Assert.assertFalse(map.mayUpdateFromClient("bar", "a")); - - map.setUpdateFromClientFilter("bar"::equals); - - Assert.assertFalse(map.mayUpdateFromClient("foo", "a")); - Assert.assertTrue(map.mayUpdateFromClient("bar", "a")); - } - - @Test - public void childPropertyUpdateFilter_setFilterBeforeChild() { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode child = new StateNode(ElementPropertyMap.class); - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - map.setUpdateFromClientFilter("foo.bar"::equals); - map.put("foo", child); - - Assert.assertTrue(childModel.mayUpdateFromClient("bar", "a")); - Assert.assertFalse(childModel.mayUpdateFromClient("baz", "a")); - } - - @Test - public void deferredUpdateFromClient_filterAllowsUpdate() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode child = new StateNode(ElementPropertyMap.class); - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - map.setUpdateFromClientFilter("foo.bar"::equals); - map.put("foo", child); - - assertDeferredUpdate_putResult(childModel, "bar"); - } - - @Test(expected = PropertyChangeDeniedException.class) - public void deferredUpdateFromClient_noFilter_throws() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode child = new StateNode(ElementPropertyMap.class); - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - map.put("foo", child); - childModel.deferredUpdateFromClient("bar", "a"); - } - - @Test - public void deferredUpdateFromClient_filterDisallowsUpdate() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode child = new StateNode(ElementPropertyMap.class); - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - map.setUpdateFromClientFilter(key -> false); - map.put("foo", child); - - assertDeferredUpdate_noOp(childModel, "bar"); - } - - @Test - public void listChildPropertyUpdateFilter_setFilterBeforeChild() { - ElementPropertyMap map = createSimplePropertyMap(); - ModelList list = map.resolveModelList("foo"); - StateNode child = new StateNode(ElementPropertyMap.class); - - map.setUpdateFromClientFilter("foo.bar"::equals); - list.add(child); - - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - Assert.assertTrue(childModel.mayUpdateFromClient("bar", "a")); - Assert.assertFalse(childModel.mayUpdateFromClient("baz", "a")); - } - - @Test - public void deferredUpdateFromClient_listChild_filterAllowsUpdate() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - ModelList list = map.resolveModelList("foo"); - StateNode child = new StateNode(ElementPropertyMap.class); - - map.setUpdateFromClientFilter("foo.bar"::equals); - list.add(child); - - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - assertDeferredUpdate_putResult(childModel, "bar"); - } - - @Test(expected = PropertyChangeDeniedException.class) - public void deferredUpdateFromClient_listItem_noFilter_throws() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - ModelList list = map.resolveModelList("foo"); - StateNode child = new StateNode(ElementPropertyMap.class); - - list.add(child); - - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - childModel.deferredUpdateFromClient("bar", "a"); - } - - @Test - public void deferredUpdateFromClient_listChild_filterDisallowsUpdate() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - ModelList list = map.resolveModelList("foo"); - StateNode child = new StateNode(ElementPropertyMap.class); - - map.setUpdateFromClientFilter(key -> false); - list.add(child); - - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - assertDeferredUpdate_noOp(childModel, "bar"); - } - - @Test - public void childPropertyUpdateFilter_setFilterAfterChild() { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode child = new StateNode(ElementPropertyMap.class); - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - map.put("foo", child); - map.setUpdateFromClientFilter("foo.bar"::equals); - - Assert.assertTrue(childModel.mayUpdateFromClient("bar", "a")); - Assert.assertFalse(childModel.mayUpdateFromClient("baz", "a")); - } - - @Test - public void childPropertyUpdateFilter_renameProperty() { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode child = new StateNode(ElementPropertyMap.class); - ElementPropertyMap childModel = ElementPropertyMap.getModel(child); - - map.put("foo", child); - map.setUpdateFromClientFilter("foo.bar"::equals); - - Assert.assertTrue(childModel.mayUpdateFromClient("bar", "a")); - - map.remove("foo"); - Assert.assertFalse(childModel.mayUpdateFromClient("bar", "a")); - - map.put("bar", child); - Assert.assertFalse(childModel.mayUpdateFromClient("bar", "a")); - } - - @Test - public void childPropertyUpdateFilter_deepNesting() { - ElementPropertyMap map = createSimplePropertyMap(); - - map.setUpdateFromClientFilter("a.b.c.d.e.f.g.h.i.j.property"::equals); - - for (int i = 0; i < 10; i++) { - StateNode child = new StateNode(ElementPropertyMap.class); - map.setProperty(Character.toString((char) ('a' + i)), child); - - map = ElementPropertyMap.getModel(child); - } - - Assert.assertTrue(map.mayUpdateFromClient("property", "foo")); - } - - @Test(expected = PropertyChangeDeniedException.class) - public void deferredUpdateFromClient_updateNotAllowed_throw() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - - map.deferredUpdateFromClient("foo", "value"); - } - - @Test - public void deferredUpdateFromClient_filterDisallowUpdate_eventIsSynchronized() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - Element.get(map.getNode()).addEventListener("dummy", event -> { - - }).synchronizeProperty("foo"); - - map.setUpdateFromClientFilter(key -> false); - - assertDeferredUpdate_putResult(map, "foo"); - } - - @Test(expected = PropertyChangeDeniedException.class) - public void deferredUpdateFromClient_filterAllowsUpdate_propertyIsForbidden_throw() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - map.put("classList", "a"); - - map.setUpdateFromClientFilter(key -> true); - - map.deferredUpdateFromClient("classList", "value"); - } - - @Test - public void deferredUpdateFromClient_clientFiltersOutUpdate_noOpRunnable() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - map.setUpdateFromClientFilter(name -> !name.equals("foo")); - - AtomicReference eventCapture = new AtomicReference<>(); - map.addPropertyChangeListener("foo", eventCapture::set); - - Runnable runnable = map.deferredUpdateFromClient("foo", "value"); - MatcherAssert.assertThat(runnable.getClass().getName(), - CoreMatchers.not(CoreMatchers.equalTo( - ElementPropertyMap.class.getName() + "$PutResult"))); - runnable.run(); - Assert.assertNull(eventCapture.get()); - } - - @Test - public void deferredUpdateFromClient_clientFilterAcceptUpdate_putResultRunnable() - throws PropertyChangeDeniedException { - ElementPropertyMap map = createSimplePropertyMap(); - map.setUpdateFromClientFilter(name -> name.equals("foo")); - - AtomicReference eventCapture = new AtomicReference<>(); - map.addPropertyChangeListener("foo", eventCapture::set); - - Runnable runnable = assertDeferredUpdate_putResult(map, "foo"); - runnable.run(); - Assert.assertNotNull(eventCapture.get()); - } - - @Test - public void producePutChange_innerHTMLProperty_valueIsTheSame_returnsTrue() { - ElementPropertyMap map = createSimplePropertyMap(); - map.setProperty("innerHTML", "foo"); - - Assert.assertTrue(map.producePutChange("innerHTML", true, "foo")); - Assert.assertTrue(map.producePutChange("innerHTML", false, "foo")); - } - - @Test - public void producePutChange_notInnerHTMLProperty_valueIsTheSame_returnsFalse() { - ElementPropertyMap map = createSimplePropertyMap(); - map.setProperty("foo", "bar"); - - Assert.assertFalse(map.producePutChange("foo", true, "bar")); - } - - private void listenerIsNotified(boolean clientEvent) { - ElementPropertyMap map = createSimplePropertyMap(); - StateNode node = map.getNode(); - - AtomicReference event = new AtomicReference<>(); - PropertyChangeListener listener = ev -> { - Assert.assertNull(event.get()); - event.set(ev); - }; - map.addPropertyChangeListener("foo", listener); - map.setProperty("foo", "bar", !clientEvent); - - Assert.assertNull(event.get().getOldValue()); - Assert.assertEquals("bar", event.get().getValue()); - Assert.assertEquals("foo", event.get().getPropertyName()); - Assert.assertEquals(Element.get(node), event.get().getSource()); - Assert.assertEquals(clientEvent, event.get().isUserOriginated()); - - // listener is not called. Otherwise its assertion fails. - map.setProperty("bar", "foo"); - } - - private Runnable assertDeferredUpdate_putResult(ElementPropertyMap map, - String property) throws PropertyChangeDeniedException { - Runnable runnable = map.deferredUpdateFromClient(property, "a"); - MatcherAssert.assertThat(runnable.getClass().getName(), CoreMatchers - .equalTo(ElementPropertyMap.class.getName() + "$PutResult")); - return runnable; - } - - private void assertDeferredUpdate_noOp(ElementPropertyMap map, - String property) throws PropertyChangeDeniedException { - Runnable runnable = map.deferredUpdateFromClient(property, "a"); - MatcherAssert.assertThat(runnable.getClass().getName(), - CoreMatchers.not(CoreMatchers.equalTo( - ElementPropertyMap.class.getName() + "$PutResult"))); - } - - private static ElementPropertyMap createSimplePropertyMap() { - return BasicElementStateProvider.createStateNode("div") - .getFeature(ElementPropertyMap.class); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/InertDataTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/InertDataTest.java deleted file mode 100644 index 5c3b66b7134..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/InertDataTest.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.internal.StateNode; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class InertDataTest extends AbstractNodeFeatureTest { - - private StateNode parent; - private StateNode child; - private StateNode grandchild; - - @Before - public void setup() { - parent = createNode(null); - child = createNode(parent); - grandchild = createNode(child); - } - - @Test - public void inertData_defaults() { - Element element = ElementFactory.createDiv(); - Assert.assertFalse("Elements should not have InertData by default", - element.getNode().getFeatureIfInitialized(InertData.class) - .isPresent()); - final InertData inertData = element.getNode() - .getFeature(InertData.class); - Assert.assertFalse(inertData.isInertSelf()); - Assert.assertFalse(inertData.isIgnoreParentInert()); - Assert.assertTrue(inertData.allowsChanges()); - } - - @Test - public void inertData_hasShadowRoot_handlesInertCheck() { - parent = createNode(null); - StateNode shadow = new StateNode(ElementChildrenList.class, - ShadowRootHost.class); - parent.getFeature(ElementChildrenList.class).add(0, shadow); - - grandchild = createNode(shadow); - - final InertData parentFeature = parent.getFeature(InertData.class); - parentFeature.setInertSelf(true); - parentFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parentFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - } - - @Test - public void inertData_inheritingInert_allPermutations() { - final InertData childFeature = child.getFeature(InertData.class); - childFeature.setIgnoreParentInert(true); - Assert.assertFalse(childFeature.isInert()); - childFeature.generateChangesFromEmpty(); - - final InertData parentFeature = parent.getFeature(InertData.class); - parentFeature.setInertSelf(true); - parentFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parentFeature.isInert()); - Assert.assertFalse(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - - childFeature.setIgnoreParentInert(false); - childFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parentFeature.isInert()); - Assert.assertTrue(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - - childFeature.setIgnoreParentInert(true); - childFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parentFeature.isInert()); - Assert.assertFalse(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - - childFeature.setInertSelf(true); - childFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parentFeature.isInert()); - Assert.assertTrue(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - - parentFeature.setInertSelf(false); - parentFeature.generateChangesFromEmpty(); - - Assert.assertFalse(parentFeature.isInert()); - Assert.assertTrue(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - - childFeature.setInertSelf(false); - childFeature.generateChangesFromEmpty(); - - Assert.assertFalse(parentFeature.isInert()); - Assert.assertFalse(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - - // both parent and child have inert data and it should cascade - // top->down - childFeature.setIgnoreParentInert(false); - parentFeature.setInertSelf(true); - parentFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parentFeature.isInert()); - Assert.assertTrue(childFeature.isInert()); - Assert.assertFalse(grandchild.getFeatureIfInitialized(InertData.class) - .isPresent()); - } - - @Test - public void inertDataUpdates_hierarchyWithGaps_updatesCascaded() { - StateNode greatgrandchild = createNode(grandchild); - - final InertData greatgrandchildFeature = greatgrandchild - .getFeature(InertData.class); - greatgrandchildFeature.setInertSelf(false); - greatgrandchildFeature.generateChangesFromEmpty(); - - Assert.assertFalse(greatgrandchild.isInert()); - - final InertData parentFeature = parent.getFeature(InertData.class); - parentFeature.setInertSelf(true); - parentFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertTrue(grandchild.isInert()); - Assert.assertTrue(greatgrandchild.isInert()); - - final InertData grandchildFeature = grandchild - .getFeature(InertData.class); - grandchildFeature.setIgnoreParentInert(true); - grandchildFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - Assert.assertFalse(greatgrandchild.isInert()); - - parentFeature.setInertSelf(false); - parentFeature.generateChangesFromEmpty(); - - Assert.assertFalse(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - Assert.assertFalse(greatgrandchild.isInert()); - - parentFeature.setInertSelf(true); - parentFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - Assert.assertFalse(greatgrandchild.isInert()); - - grandchildFeature.setIgnoreParentInert(false); - grandchildFeature.generateChangesFromEmpty(); - - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertTrue(grandchild.isInert()); - Assert.assertTrue(greatgrandchild.isInert()); - - parentFeature.setInertSelf(false); - parentFeature.generateChangesFromEmpty(); - - Assert.assertFalse(parent.isInert()); - Assert.assertFalse(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - Assert.assertFalse(greatgrandchild.isInert()); - - parentFeature.setInertSelf(true); - grandchildFeature.setIgnoreParentInert(true); - - parentFeature.generateChangesFromEmpty(); - // even though changes are not yet collected from grandchild, - // value is correct due to parent changes cascading - Assert.assertTrue(parent.isInert()); - Assert.assertTrue(child.isInert()); - Assert.assertFalse(grandchild.isInert()); - Assert.assertFalse(greatgrandchild.isInert()); - } - - private static StateNode createNode(StateNode parent) { - final StateNode stateNode = new StateNode(ElementChildrenList.class, - InertData.class); - if (parent != null) { - parent.getFeature(ElementChildrenList.class).add(0, stateNode); - } - return stateNode; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ListFeatureSetViewTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ListFeatureSetViewTest.java deleted file mode 100644 index 495050e3c75..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ListFeatureSetViewTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.change.AbstractListChange; -import com.vaadin.flow.internal.nodefeature.NodeList.SetView; - -public class ListFeatureSetViewTest { - - private TestFeature feature; - private SetView set; - - private static class TestFeature extends SerializableNodeList { - private final ArrayList> changes = new ArrayList<>(); - - public TestFeature() { - super(Mockito.mock(StateNode.class)); - } - - @Override - protected List> getChangeTracker() { - // Default implementation calls unmocked method in StateNode - return changes; - } - } - - private static class TestSetView extends NodeList.SetView { - public TestSetView(NodeList list) { - super(list); - } - - @Override - protected void validate(String string) { - if (string.length() > 5) { - throw new IllegalArgumentException( - "All strings must be less than 5 characters"); - } - } - } - - @Before - public void setup() { - feature = new TestFeature(); - set = new TestSetView(feature); - } - - @Test - public void testSetViewAdd() { - set.add("0"); - assertContents("0"); - set.add("1"); - assertContents("0", "1"); - set.add("2"); - assertContents("0", "1", "2"); - } - - @Test - public void testSetViewSize() { - set.add("0"); - Assert.assertEquals(1, set.size()); - set.add("1"); - Assert.assertEquals(2, set.size()); - set.remove("1"); - Assert.assertEquals(1, set.size()); - set.remove("1"); // Not in the list - Assert.assertEquals(1, set.size()); - set.remove("0"); - Assert.assertEquals(0, set.size()); - } - - @Test - public void testSetViewRemove() { - set.add("0"); - set.add("1"); - set.remove("0"); - assertContents("1"); - set.remove("1"); - assertContents(); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetViewValidateAdd() { - set.add("as89w4573"); - } - - @Test - public void testSetViewClear() { - set.add("a"); - set.add("b"); - set.add("c"); - set.clear(); - assertContents(); - set.clear(); - } - - @Test - public void testSetViewIteratorIterate() { - set.add("a"); - set.add("b"); - set.add("c"); - - Iterator i = set.iterator(); - Assert.assertEquals("a", i.next()); - Assert.assertEquals("b", i.next()); - Assert.assertEquals("c", i.next()); - Assert.assertFalse(i.hasNext()); - } - - @Test - public void testSetViewIteratorRemove() { - set.add("a"); - set.add("b"); - set.add("c"); - - Iterator i = set.iterator(); - i.next(); - i.next(); - i.remove(); - assertContents("a", "c"); - - } - - @Test - public void testSetViewContains() { - set.add("a"); - set.add("b"); - set.add("c"); - - Assert.assertTrue(set.contains("a")); - Assert.assertTrue(set.contains("b")); - Assert.assertTrue(set.contains("c")); - Assert.assertFalse(set.contains("d")); - } - - @Test - public void testSetViewSameFeatureEquals() { - set.add("a"); - - TestSetView otherSet = new TestSetView(feature); - - Assert.assertEquals(set, otherSet); - Assert.assertEquals(set.hashCode(), otherSet.hashCode()); - } - - @Test - public void testSetViewDifferentFeatureEquals() { - set.add("a"); - TestFeature otherFeature = new TestFeature(); - TestSetView otherSet = new TestSetView(otherFeature); - otherSet.add("a"); - - Assert.assertEquals(set, otherSet); - Assert.assertEquals(set.hashCode(), otherSet.hashCode()); - - } - - private void assertContents(String... expected) { - String[] actual = new String[feature.size()]; - for (int i = 0; i < feature.size(); i++) { - actual[i] = feature.get(i); - } - Assert.assertArrayEquals(expected, actual); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/LoadingIndicatorConfigurationMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/LoadingIndicatorConfigurationMapTest.java deleted file mode 100644 index cceaa4c2653..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/LoadingIndicatorConfigurationMapTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import org.junit.Assert; -import org.junit.Test; - -public class LoadingIndicatorConfigurationMapTest - extends AbstractMapFeatureTest { - private final LoadingIndicatorConfigurationMap map = createFeature(); - - @Test - public void defaults() { - Assert.assertEquals( - LoadingIndicatorConfigurationMap.FIRST_DELAY_DEFAULT, - map.getFirstDelay()); - Assert.assertEquals( - LoadingIndicatorConfigurationMap.SECOND_DELAY_DEFAULT, - map.getSecondDelay()); - Assert.assertEquals( - LoadingIndicatorConfigurationMap.THIRD_DELAY_DEFAULT, - map.getThirdDelay()); - Assert.assertEquals( - LoadingIndicatorConfigurationMap.DEFAULT_THEME_APPLIED_DEFAULT, - map.isApplyDefaultTheme()); - } - - @Test - public void setGetFirstDelay() { - testInt(map, LoadingIndicatorConfigurationMap.FIRST_DELAY_KEY, - map::setFirstDelay, map::getFirstDelay); - } - - @Test - public void setGetSecondDelay() { - testInt(map, LoadingIndicatorConfigurationMap.SECOND_DELAY_KEY, - map::setSecondDelay, map::getSecondDelay); - } - - @Test - public void setGetThirdDelay() { - testInt(map, LoadingIndicatorConfigurationMap.THIRD_DELAY_KEY, - map::setThirdDelay, map::getThirdDelay); - } - - @Test - public void setGetDefaultThemeApplied() { - testBoolean(map, - LoadingIndicatorConfigurationMap.DEFAULT_THEME_APPLIED_KEY, - map::setApplyDefaultTheme, map::isApplyDefaultTheme); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeFeatureTest.java deleted file mode 100644 index d1933462f09..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeFeatureTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateNodeTest; -import com.vaadin.flow.internal.nodefeature.PushConfigurationMap.PushConfigurationParametersMap; - -public class NodeFeatureTest { - private static abstract class UnregisteredNodeFeature extends NodeFeature { - public UnregisteredNodeFeature(StateNode node) { - super(node); - } - } - - @Test(expected = AssertionError.class) - public void testCreateNullTypeThrows() { - NodeFeatureRegistry.create(null, StateNodeTest.createEmptyNode()); - } - - @Test(expected = AssertionError.class) - public void testCreateNullNodeThrows() { - NodeFeatureRegistry.create(ElementData.class, null); - } - - @Test(expected = AssertionError.class) - public void testCreateUnknownFeatureThrows() { - NodeFeatureRegistry.create(UnregisteredNodeFeature.class, - StateNodeTest.createEmptyNode()); - } - - private static Map, Integer> buildExpectedIdMap() { - Map, Integer> expectedIds = new HashMap<>(); - - expectedIds.put(ElementData.class, NodeFeatures.ELEMENT_DATA); - expectedIds.put(ElementPropertyMap.class, - NodeFeatures.ELEMENT_PROPERTIES); - expectedIds.put(ElementAttributeMap.class, - NodeFeatures.ELEMENT_ATTRIBUTES); - expectedIds.put(ElementChildrenList.class, - NodeFeatures.ELEMENT_CHILDREN); - expectedIds.put(ElementListenerMap.class, - NodeFeatures.ELEMENT_LISTENERS); - expectedIds.put(PushConfigurationMap.class, - NodeFeatures.UI_PUSHCONFIGURATION); - expectedIds.put(PushConfigurationParametersMap.class, - NodeFeatures.UI_PUSHCONFIGURATION_PARAMETERS); - expectedIds.put(TextNodeMap.class, NodeFeatures.TEXT_NODE); - expectedIds.put(PollConfigurationMap.class, - NodeFeatures.POLL_CONFIGURATION); - expectedIds.put(ReconnectDialogConfigurationMap.class, - NodeFeatures.RECONNECT_DIALOG_CONFIGURATION); - expectedIds.put(LoadingIndicatorConfigurationMap.class, - NodeFeatures.LOADING_INDICATOR_CONFIGURATION); - expectedIds.put(ElementClassList.class, NodeFeatures.CLASS_LIST); - expectedIds.put(ElementStylePropertyMap.class, - NodeFeatures.ELEMENT_STYLE_PROPERTIES); - expectedIds.put(ComponentMapping.class, NodeFeatures.COMPONENT_MAPPING); - expectedIds.put(ModelList.class, NodeFeatures.TEMPLATE_MODELLIST); - expectedIds.put(PolymerServerEventHandlers.class, - NodeFeatures.POLYMER_SERVER_EVENT_HANDLERS); - expectedIds.put(PolymerEventListenerMap.class, - NodeFeatures.POLYMER_EVENT_LISTENERS); - expectedIds.put(ClientCallableHandlers.class, - NodeFeatures.CLIENT_DELEGATE_HANDLERS); - expectedIds.put(ShadowRootData.class, NodeFeatures.SHADOW_ROOT_DATA); - expectedIds.put(ShadowRootHost.class, NodeFeatures.SHADOW_ROOT_HOST); - expectedIds.put(AttachExistingElementFeature.class, - NodeFeatures.ATTACH_EXISTING_ELEMENT); - expectedIds.put(BasicTypeValue.class, NodeFeatures.BASIC_TYPE_VALUE); - expectedIds.put(VirtualChildrenList.class, - NodeFeatures.VIRTUAL_CHILDREN); - expectedIds.put(ReturnChannelMap.class, - NodeFeatures.RETURN_CHANNEL_MAP); - expectedIds.put(InertData.class, NodeFeatures.INERT_DATA); - - return expectedIds; - } - - @Test - public void testGetIdValues() { - // Verifies that the ids are the same as on the client side - Map, Integer> expectedIds = buildExpectedIdMap(); - - Assert.assertEquals("The number of expected features is not up to date", - expectedIds.size(), NodeFeatureRegistry.nodeFeatures.size()); - - expectedIds.forEach((type, expectedId) -> { - Assert.assertEquals("Unexpected id for " + type.getName(), - expectedId.intValue(), NodeFeatureRegistry.getId(type)); - }); - } - - @Test - public void testGetById() { - Map, Integer> expectedIds = buildExpectedIdMap(); - - expectedIds.forEach((expectedType, id) -> { - Assert.assertEquals("Unexpected type for id " + id, expectedType, - NodeFeatureRegistry.getFeature(id)); - }); - } - - @Test - public void priorityOrder() { - List> priorityOrder = buildExpectedIdMap() - .keySet().stream() - .sorted(NodeFeatureRegistry.PRIORITY_COMPARATOR) - .collect(Collectors.toList()); - - List> expectedOrder = Arrays.asList( - /* Primary features */ - ElementData.class, TextNodeMap.class, ModelList.class, - BasicTypeValue.class, - - /* Common element features */ - ElementChildrenList.class, ElementPropertyMap.class, - - /* Component mapped features */ - ComponentMapping.class, ClientCallableHandlers.class, - - /* Supplementary element stuff */ - ElementClassList.class, ElementAttributeMap.class, - ElementListenerMap.class, VirtualChildrenList.class, - - /* Supplementary generic stuff */ - ReturnChannelMap.class, - - /* PolymerTemplate stuff */ - PolymerEventListenerMap.class, PolymerServerEventHandlers.class, - - /* Rarely used element stuff */ - ElementStylePropertyMap.class, ShadowRootData.class, - ShadowRootHost.class, AttachExistingElementFeature.class, - InertData.class, - - /* Only used for the root node */ - PushConfigurationMap.class, - PushConfigurationParametersMap.class, - LoadingIndicatorConfigurationMap.class, - PollConfigurationMap.class, - ReconnectDialogConfigurationMap.class); - - Assert.assertEquals(expectedOrder.size(), priorityOrder.size()); - - for (int i = 0; i < priorityOrder.size(); i++) { - if (priorityOrder.get(i) != expectedOrder.get(i)) { - Assert.fail("Invalid priority ordering at index " + i - + ". Expected " + expectedOrder.get(i).getSimpleName() - + " but got " + priorityOrder.get(i).getSimpleName()); - } - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeListAddRemoveTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeListAddRemoveTest.java deleted file mode 100644 index b9a68938c2e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeListAddRemoveTest.java +++ /dev/null @@ -1,549 +0,0 @@ -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.internal.change.AbstractListChange; -import com.vaadin.flow.internal.change.ListAddChange; -import com.vaadin.flow.internal.change.ListClearChange; -import com.vaadin.flow.internal.change.ListRemoveChange; -import com.vaadin.flow.internal.change.NodeAttachChange; -import com.vaadin.flow.internal.change.NodeChange; - -public class NodeListAddRemoveTest - extends AbstractNodeFeatureTest { - protected ElementClassList nodeList = createFeature(); - - private List resetToRemoveAfterAddCase() { - nodeList.clear(); - collectChanges(nodeList); - return addOriginalItems(4); - } - - @Test - public void clear_onlyListClearChange() { - resetToRemoveAfterAddCase(); - - nodeList.clear(); - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - verifyCleared(changes); - Assert.assertEquals(0, nodeList.size()); - } - - @Test - public void remove_add_changesAreNotAdjusted() { - List items = resetToRemoveAfterAddCase(); - - // remove an item before the last one - nodeList.remove(items.size() - 2); - - String removed = items.get(items.size() - 2); - // add it back to the end - nodeList.add(removed); - - List changes = collectChanges(nodeList); - - // normal behavior: one remove and one add change in order - Assert.assertEquals(2, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListRemoveChange); - Assert.assertTrue(changes.get(1) instanceof ListAddChange); - - ListRemoveChange remove = (ListRemoveChange) changes.get(0); - Assert.assertEquals(items.size() - 2, remove.getIndex()); - Assert.assertEquals(removed, remove.getRemovedItem()); - - ListAddChange add = (ListAddChange) changes.get(1); - Assert.assertEquals(items.size() - 1, add.getIndex()); - Assert.assertEquals(1, add.getNewItems().size()); - Assert.assertEquals(removed, add.getNewItems().get(0)); - } - - @Test - public void add_immediatelyRemove_changesDiscarded() { - List items = resetToRemoveAfterAddCase(); - - String newItem = "foo"; - nodeList.add(newItem); - int index = items.size(); - nodeList.remove(index); - - List changes = collectChanges(nodeList); - - // changes are discarded - Assert.assertEquals(0, changes.size()); - } - - @Test - public void addAll_immediatelyRemove_changeIsAdjusted() { - resetToRemoveAfterAddCase(); - - List items = new ArrayList<>(); - // this makes one change with 3 items in it - addItemsAll(items, 3); - - // remove the second item from recently added - nodeList.remove(nodeList.size() - 2); - - // As a result: "remove" change is discarded and the "add" is adjusted - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - - ListAddChange add = (ListAddChange) changes.get(0); - Assert.assertEquals(nodeList.size() - 2, add.getIndex()); - Assert.assertEquals(2, add.getNewItems().size()); - items.remove(1); - Assert.assertEquals(items, add.getNewItems()); - } - - @Test - public void add_addInBetweenAndRemove_changesAreAdjusted() { - List items = resetToRemoveAfterAddCase(); - - String newItem = "foo"; - nodeList.add(newItem); - - nodeList.add("bar"); - nodeList.add("bar1"); - - int index = items.size(); - String item = nodeList.get(index); - nodeList.remove(index); - // verify that nodelist is adjusted immediately to avoid memory leaks - Optional> optionalChange = nodeList - .getChangeTracker().stream().filter(change -> { - ListAddChange addChange = (ListAddChange) change; - return addChange.getNewItems().contains(item); - }).findFirst(); - Assert.assertFalse(optionalChange.isPresent()); - Assert.assertEquals(2, nodeList.getChangeTracker().size()); - - List changes = collectChanges(nodeList); - - // remove is discarded, the fist add is discarded, others are adjusted - Assert.assertEquals(2, changes.size()); - verifyAdded(changes, Arrays.asList("bar", "bar1"), index, index + 1); - } - - @Test - public void insertBefore_addAndRemove_changesAreDiscarded() { - resetToRemoveAfterAddCase(); - - nodeList.add("foo"); - - int index = nodeList.size() - 1; - // Now insert an item at the index - nodeList.add(index, "bar"); - - // remove the second item from recently added - nodeList.remove(nodeList.size() - 1); - - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - verifyAdded(changes, Arrays.asList("bar"), index); - } - - @Test - public void insertAfter_addAllAndRemove_changesAreAdjusted() { - resetToRemoveAfterAddCase(); - - List items = new ArrayList<>(); - // this makes one change with 3 items in it - addItemsAll(items, 3); - - int index = nodeList.size() - 1; - // Now insert an item at the index - nodeList.add(index, "bar"); - - // remove the first item from the added above (via "all") - nodeList.remove(index - 2); - - // As a result: "remove" change is discarded and the "add" are adjusted - List changes = collectChanges(nodeList); - Assert.assertEquals(2, changes.size()); - - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - Assert.assertTrue(changes.get(1) instanceof ListAddChange); - - ListAddChange add = (ListAddChange) changes.get(0); - Assert.assertEquals(index - 2, add.getIndex()); - Assert.assertEquals(2, add.getNewItems().size()); - items.remove(0); - Assert.assertEquals(items, add.getNewItems()); - - add = (ListAddChange) changes.get(1); - Assert.assertEquals(index - 1, add.getIndex()); - Assert.assertEquals(1, add.getNewItems().size()); - Assert.assertEquals("bar", add.getNewItems().get(0)); - } - - @Test - public void addOperationAfterDelete_addRemove_subsequentOoperationsAreNotAffected() { - List items = resetToRemoveAfterAddCase(); - - nodeList.add("foo"); - int index = items.size(); - nodeList.remove(index); - - String newItem = "bar"; - nodeList.add(newItem); - - // As a result: "remove" and "add" before it are discarded and the "add" - // operation is not affected - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - - verifyAdded(changes, Arrays.asList(newItem), index); - } - - @Test - public void removeOperationAfterDelete_addRemove_subsequentOperationsAreNotAffected() { - List items = resetToRemoveAfterAddCase(); - - nodeList.add("foo"); - int index = items.size(); - nodeList.remove(index); - - nodeList.remove(index - 1); - // As a result: "remove" and "add" before it are discarded and the last - // "remove" operation is not affected - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListRemoveChange); - - verifyRemoved(changes, Arrays.asList(items.get(index - 1)), index - 1); - } - - @Test - public void removeInBetween_addRemove_removeIsNotAdjusted() { - List items = resetToRemoveAfterAddCase(); - - int index = items.size(); - nodeList.add("foo"); - - // remove the item that has been added BEFORE. - nodeList.remove(index - 1); - - // remove previously added element - nodeList.remove(index - 1); - - // As a result: "remove" and its corresponding "add" are discarded and - // the "remove" in between operation is adjusted - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListRemoveChange); - - verifyRemoved(changes, Arrays.asList(items.get(index - 1)), index - 1); - } - - @Test - public void clearInBetween_addRemove_removeIsAdjustedProperly() { - resetToRemoveAfterAddCase(); - - // First add some item - nodeList.add("foo"); - - // Now clear everything - nodeList.clear(); - - // Now add and remove an item : after clear any add operation should not - // matter anymore - nodeList.add("bar"); - nodeList.remove(0); - - List changes = collectChanges(nodeList); - // only one clear changes: add is compensated by remove - Assert.assertEquals(1, changes.size()); - Assert.assertEquals(ListClearChange.class, changes.get(0).getClass()); - // what's important: no any exception causes by incorrect index - // (IndexOutOfBoundsException) - } - - @Test - public void clear_collectChanges_allPreviousEventsAreRemoved() { - List items = resetToRemoveAfterAddCase(); - - int index = items.size(); - - nodeList.add("foo"); - nodeList.add("bar"); - nodeList.remove(index); - - nodeList.clear(); - - nodeList.add("baz"); - - List changes = collectChanges(nodeList); - - Assert.assertEquals(2, changes.size()); - MatcherAssert.assertThat(changes.get(0), - CoreMatchers.instanceOf(ListClearChange.class)); - MatcherAssert.assertThat(changes.get(1), - CoreMatchers.instanceOf(ListAddChange.class)); - - Assert.assertEquals(1, nodeList.size()); - Assert.assertEquals("baz", nodeList.get(0)); - } - - @Test - public void clear_collectChanges_resetChangeTracker_clearEventIsCollected() { - resetToRemoveAfterAddCase(); - - nodeList.add("foo"); - - nodeList.clear(); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - // attach the feature node to the tree - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - nodeList.add("bar"); - - List changes = new ArrayList<>(); - // this call will remove the clear change which has happened before - // attach, but it should still be collected - nodeList.getNode().collectChanges(changes::add); - - Assert.assertEquals(3, changes.size()); - MatcherAssert.assertThat(changes.get(0), - CoreMatchers.instanceOf(NodeAttachChange.class)); - MatcherAssert.assertThat(changes.get(1), - CoreMatchers.instanceOf(ListClearChange.class)); - MatcherAssert.assertThat(changes.get(2), - CoreMatchers.instanceOf(ListAddChange.class)); - - nodeList.add("baz"); - - changes.clear(); - nodeList.getNode().collectChanges(changes::add); - // Now there is no anymore clear change (so the previous one is not - // preserved) - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - } - - @Test - public void clear_collectChanges_resetChangeTracker_reattach_clearEventIsCollected() { - resetToRemoveAfterAddCase(); - - nodeList.add("foo"); - - nodeList.clear(); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - // attach the feature node to the tree - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - nodeList.add("bar"); - - // detach the feature node to the tree - - tree.getRootNode().getFeature(ElementChildrenList.class).remove(0); - // if there was no changes collection after detach (and node is attached - // again) then the node has not been detached de-facto: detach-attach is - // no-op in this case, so to avoid no-op the changes should be collected - // in between - nodeList.getNode().collectChanges(change -> { - }); - - // reattach it back - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - List changes = new ArrayList<>(); - nodeList.getNode().collectChanges(changes::add); - - Assert.assertEquals(3, changes.size()); - Assert.assertEquals(NodeAttachChange.class, changes.get(0).getClass()); - Assert.assertEquals(ListClearChange.class, changes.get(1).getClass()); - Assert.assertEquals(ListAddChange.class, changes.get(2).getClass()); - - changes.clear(); - - nodeList.add("baz"); - - nodeList.getNode().collectChanges(changes::add); - // Now there is no anymore clear change (so the previous one is not - // preserved) - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - } - - @Test - public void clearNodeList_clearChanges_generateChangesFromEmpty_clearChangeIsCollected() { - // removes all children - nodeList.clear(); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - // attach the feature node to the tree - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - List changes = new ArrayList<>(); - nodeList.getNode().collectChanges(changes::add); - - Assert.assertEquals(2, changes.size()); - Assert.assertEquals(NodeAttachChange.class, changes.get(0).getClass()); - Assert.assertEquals(ListClearChange.class, changes.get(1).getClass()); - } - - @Test - public void clearNodeList_clearChanges_reatach_generateChangesFromEmpty_clearChangeIsCollected() { - // removes all children - nodeList.clear(); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - // attach the feature node to the tree - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - nodeList.getNode().collectChanges(change -> { - }); - - // detach the feature node to the tree - - tree.getRootNode().getFeature(ElementChildrenList.class).remove(0); - // if there was no changes collection after detach (and node is attached - // again) then the node has not been detached de-facto: detach-attach is - // no-op in this case, so to avoid no-op the changes should be collected - // in between - nodeList.getNode().collectChanges(change -> { - }); - - // reattach it back - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - List changes = new ArrayList<>(); - nodeList.getNode().collectChanges(changes::add); - - Assert.assertEquals(2, changes.size()); - Assert.assertEquals(NodeAttachChange.class, changes.get(0).getClass()); - Assert.assertEquals(ListClearChange.class, changes.get(1).getClass()); - } - - @Test - public void collectChanges_clearNodeListIsDoneFirst_noClearEventinCollectedChanges() { - // removes all children - nodeList.clear(); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - // attach the feature node to the tree - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - List changes = new ArrayList<>(); - nodeList.getNode().collectChanges(changes::add); - - changes.clear(); - - nodeList.add("foo"); - - nodeList.getNode().collectChanges(changes::add); - Assert.assertEquals(1, changes.size()); - Assert.assertEquals(ListAddChange.class, changes.get(0).getClass()); - } - - @Test - public void clear_modifyList_collectChanges_clearChangeIsCollected() { - nodeList.clear(); - nodeList.add("foo"); - - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - // attach the feature node to the tree - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(nodeList.getNode()); - - List changes = new ArrayList<>(); - nodeList.getNode().collectChanges(changes::add); - - Assert.assertEquals(3, changes.size()); - Assert.assertEquals(NodeAttachChange.class, changes.get(0).getClass()); - Assert.assertEquals(ListClearChange.class, changes.get(1).getClass()); - Assert.assertEquals(ListAddChange.class, changes.get(2).getClass()); - } - - private List addOriginalItems(int numberOfOriginalItems) { - List items = new ArrayList<>(); - for (int i = 0; i < numberOfOriginalItems; i++) { - String item = "o-" + i; - nodeList.add(item); - items.add(item); - } - collectChanges(nodeList); - verifyNodeListContent(items.toArray()); - - return items; - } - - private void addItemsAll(List listCaptureAdded, int numberOfItems) { - List items = new ArrayList<>(); - int indexInList = listCaptureAdded.size(); - for (int i = 0; i < numberOfItems; i++) { - String item = "a-" + indexInList + ":" + i + "/" + numberOfItems; - items.add(item); - indexInList++; - } - nodeList.addAll(items); - listCaptureAdded.addAll(items); - } - - private void verifyNodeListContent(Object... items) { - for (int i = 0; i < items.length; i++) { - Assert.assertEquals(items[i], nodeList.get(i)); - } - } - - private void verifyCleared(List changes) { - Assert.assertEquals(1, changes.size()); - NodeChange nodeChange = changes.get(0); - MatcherAssert.assertThat(nodeChange, - CoreMatchers.instanceOf(ListClearChange.class)); - } - - private void verifyRemoved(List changes, List items, - Integer... indexes) { - Assert.assertTrue(changes.size() > 0); - for (int i = 0; i < indexes.length; i++) { - NodeChange nodeChange = changes.get(i); - MatcherAssert.assertThat(nodeChange, - CoreMatchers.instanceOf(ListRemoveChange.class)); - ListRemoveChange change = (ListRemoveChange) nodeChange; - Assert.assertEquals(indexes[i].intValue(), change.getIndex()); - Assert.assertEquals(items.get(i), change.getRemovedItem()); - } - } - - private void verifyAdded(List changes, List items, - Integer... indexes) { - for (int i = 0; i < indexes.length; i++) { - NodeChange nodeChange = changes.get(i); - MatcherAssert.assertThat(nodeChange, - CoreMatchers.instanceOf(ListAddChange.class)); - ListAddChange change = (ListAddChange) nodeChange; - Assert.assertEquals(indexes[i].intValue(), change.getIndex()); - Assert.assertEquals(1, change.getNewItems().size()); - Assert.assertEquals(items.get(i), change.getNewItems().get(0)); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeListEmptyRequiredFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeListEmptyRequiredFeatureTest.java deleted file mode 100644 index c6e067a538b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeListEmptyRequiredFeatureTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.change.EmptyChange; -import com.vaadin.flow.internal.change.ListAddChange; -import com.vaadin.flow.internal.change.NodeChange; - -public class NodeListEmptyRequiredFeatureTest { - - private StateNode node; - - private NodeList nodeList; - - @Before - public void setUp() { - node = new StateNode(Arrays.asList(ElementChildrenList.class)) { - @Override - public boolean isAttached() { - return true; - } - }; - nodeList = node.getFeature(ElementChildrenList.class); - } - - @Test - public void generateChangesFromEmpty_featureHasChangesToCollect() { - nodeList.generateChangesFromEmpty(); - - AtomicReference change = new AtomicReference<>(); - node.collectChanges(change::set); - - Assert.assertTrue(change.get() instanceof EmptyChange); - - nodeList.generateChangesFromEmpty(); - change.set(null); - node.collectChanges(change::set); - Assert.assertNull(change.get()); - } - - @Test - public void generateChangesFromEmpty_noEmptyChange() { - nodeList.add(new StateNode()); - node.clearChanges(); - nodeList.generateChangesFromEmpty(); - - List changes = new ArrayList<>(); - node.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - } - - @Test - public void collectChanges_featureHasEmptyChange() { - AtomicReference change = new AtomicReference<>(); - nodeList.collectChanges(change::set); - - Assert.assertTrue(change.get() instanceof EmptyChange); - - change.set(null); - nodeList.collectChanges(change::set); - Assert.assertNull(change.get()); - } - - @Test - public void collectChanges_noEmptyChange() { - nodeList.add(new StateNode()); - - List changes = new ArrayList<>(); - node.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof ListAddChange); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeMapEmptyRequiredFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeMapEmptyRequiredFeatureTest.java deleted file mode 100644 index 782930a428a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeMapEmptyRequiredFeatureTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.change.EmptyChange; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.NodeChange; - -public class NodeMapEmptyRequiredFeatureTest { - - private StateNode node; - - private NodeMap nodeMap; - - @Before - public void setUp() { - node = new StateNode(Arrays.asList(ElementPropertyMap.class)) { - @Override - public boolean isAttached() { - return true; - } - }; - nodeMap = node.getFeature(ElementPropertyMap.class); - } - - @Test - public void generateChangesFromEmpty_featureHasChangesToCollect() { - nodeMap.generateChangesFromEmpty(); - - AtomicReference change = new AtomicReference<>(); - node.collectChanges(change::set); - - Assert.assertTrue(change.get() instanceof EmptyChange); - - nodeMap.generateChangesFromEmpty(); - change.set(null); - node.collectChanges(change::set); - Assert.assertNull(change.get()); - } - - @Test - public void generateChangesFromEmpty_noEmptyChange() { - nodeMap.put("foo", "bar"); - node.clearChanges(); - nodeMap.generateChangesFromEmpty(); - - List changes = new ArrayList<>(); - node.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - } - - @Test - public void collectChanges_featureHasEmptyChange() { - AtomicReference change = new AtomicReference<>(); - nodeMap.collectChanges(change::set); - - Assert.assertTrue(change.get() instanceof EmptyChange); - - change.set(null); - nodeMap.collectChanges(change::set); - Assert.assertNull(change.get()); - } - - @Test - public void collectChanges_noEmptyChange() { - nodeMap.put("foo", "bar"); - - List changes = new ArrayList<>(); - node.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeMapTest.java deleted file mode 100644 index b6404e0ffa5..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeMapTest.java +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateNodeTest; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.MapRemoveChange; -import com.vaadin.flow.internal.change.NodeChange; -import com.vaadin.flow.server.Command; - -import elemental.json.Json; -import elemental.json.JsonValue; - -// Using ElementStylePropertyMap since it closely maps to the underlying map -public class NodeMapTest - extends AbstractNodeFeatureTest { - private static final String KEY = "key"; - private ElementStylePropertyMap nodeMap = createFeature(); - - private static class AlwaysProduceChangeMap extends NodeMap { - - AlwaysProduceChangeMap(StateNode node) { - super(node); - } - - @Override - protected boolean producePutChange(String key, boolean hadValueEarlier, - Serializable newValue) { - return true; - } - - } - - private static class NeverProduceChangeMap extends NodeMap { - - NeverProduceChangeMap(StateNode node) { - super(node); - } - - @Override - protected boolean producePutChange(String key, boolean hadValueEarlier, - Serializable newValue) { - return false; - } - - } - - @Test - public void testBasicFunctionality() { - Assert.assertFalse(nodeMap.contains(KEY)); - Assert.assertNull(nodeMap.get(KEY)); - - nodeMap.put(KEY, "value"); - Assert.assertTrue(nodeMap.contains(KEY)); - Assert.assertEquals("value", nodeMap.get(KEY)); - - nodeMap.remove(KEY); - Assert.assertFalse(nodeMap.contains(KEY)); - Assert.assertNull(nodeMap.get(KEY)); - } - - @Test - public void testCollectChange() { - List initialChanges = collectChanges(nodeMap); - Assert.assertEquals(0, initialChanges.size()); - - nodeMap.put(KEY, "value"); - List putChanges = collectChanges(nodeMap); - Assert.assertEquals(1, putChanges.size()); - - MapPutChange putChange = (MapPutChange) putChanges.get(0); - Assert.assertEquals(KEY, putChange.getKey()); - Assert.assertEquals("value", putChange.getValue()); - - nodeMap.put(KEY, null); - List putNullChanges = collectChanges(nodeMap); - Assert.assertEquals(1, putNullChanges.size()); - - MapPutChange putNullChange = (MapPutChange) putNullChanges.get(0); - Assert.assertEquals(KEY, putNullChange.getKey()); - Assert.assertEquals(null, putNullChange.getValue()); - - nodeMap.remove(KEY); - - List removeChanges = collectChanges(nodeMap); - Assert.assertEquals(1, removeChanges.size()); - - MapRemoveChange removeChange = (MapRemoveChange) removeChanges.get(0); - Assert.assertEquals(KEY, removeChange.getKey()); - } - - @Test - public void testNoChangeEvent() { - nodeMap.put(KEY, "value", false); - List changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - nodeMap.put(KEY, "value", true); - changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - nodeMap.put(KEY, "bar", true); - changes = collectChanges(nodeMap); - Assert.assertEquals(1, changes.size()); - } - - @Test - public void testNoChangeOverwritesOldChanges() { - nodeMap.put(KEY, "value", true); - nodeMap.put(KEY, "foobar", false); - List changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - - nodeMap.put(KEY, "urk"); - changes = collectChanges(nodeMap); - Assert.assertEquals(1, changes.size()); - Assert.assertEquals("urk", ((MapPutChange) changes.get(0)).getValue()); - - } - - @Test - public void testCoalescePutRemove() { - nodeMap.put(KEY, "value"); - nodeMap.remove(KEY); - - List changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - } - - @Test - public void testCoalesceDoublePut() { - nodeMap.put(KEY, "value1"); - nodeMap.put(KEY, "value2"); - - List changes = collectChanges(nodeMap); - Assert.assertEquals(1, changes.size()); - Assert.assertEquals("value2", - ((MapPutChange) changes.get(0)).getValue()); - } - - @Test - public void testCoalescePutSame() { - nodeMap.put(KEY, "value"); - collectChanges(nodeMap); - - nodeMap.put(KEY, "otherValue"); - nodeMap.put(KEY, "value"); - List changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - } - - @Test - public void testCoalesceRemovePut() { - nodeMap.put(KEY, "value"); - collectChanges(nodeMap); - - nodeMap.remove(KEY); - nodeMap.put(KEY, "value"); - - List changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - } - - @Test - public void testResetChanges() { - nodeMap.put(KEY, "value"); - collectChanges(nodeMap); - - nodeMap.generateChangesFromEmpty(); - - List changes = collectChanges(nodeMap); - Assert.assertEquals(1, changes.size()); - Assert.assertEquals("value", - ((MapPutChange) changes.get(0)).getValue()); - } - - @Test - public void testCoalesceRemoveReset() { - nodeMap.put(KEY, "value"); - collectChanges(nodeMap); - - nodeMap.generateChangesFromEmpty(); - nodeMap.remove(KEY); - - List changes = collectChanges(nodeMap); - Assert.assertEquals(0, changes.size()); - } - - @Test - public void testNullKeyThrows() { - assertFailsAssert("get(null)", () -> nodeMap.get(null)); - assertFailsAssert("contains(null)", () -> nodeMap.contains(null)); - assertFailsAssert("put(null, x)", () -> nodeMap.put(null, "")); - assertFailsAssert("remove(null)", () -> nodeMap.remove(null)); - } - - private static void assertFailsAssert(String name, Command command) { - boolean threw = false; - try { - command.execute(); - } catch (AssertionError expected) { - threw = true; - } - Assert.assertTrue(name + " should throw AssertionError", threw); - } - - @Test - public void testPutAttachDetachChildren() { - StateNode child = StateNodeTest.createEmptyNode("child"); - - Assert.assertNull(child.getParent()); - - nodeMap.put(KEY, child); - - Assert.assertSame(nodeMap.getNode(), child.getParent()); - - nodeMap.put(KEY, "foo"); - - Assert.assertNull(child.getParent()); - } - - @Test - public void testRemoveDetachChildren() { - StateNode child = StateNodeTest.createEmptyNode("child"); - - nodeMap.put(KEY, child); - - Assert.assertSame(nodeMap.getNode(), child.getParent()); - - nodeMap.remove(KEY); - - Assert.assertNull(child.getParent()); - } - - @Test - public void testSerializable() { - nodeMap.put("string", "bar"); - nodeMap.put("null", null); - nodeMap.put("boolean", Boolean.TRUE); - nodeMap.put("number", Double.valueOf(5)); - - nodeMap.put("jsonString", Json.create("bar")); - nodeMap.put("jsonNull", Json.createNull()); - nodeMap.put("jsonBoolean", Json.create(true)); - nodeMap.put("jsonNumber", Json.create(5)); - nodeMap.put("jsonObject", Json.createObject()); - nodeMap.put("jsonArray", Json.createArray()); - - Map values = new HashMap<>(); - nodeMap.keySet().forEach(key -> values.put(key, nodeMap.get(key))); - - NodeMap copy = SerializationUtils - .deserialize(SerializationUtils.serialize(nodeMap)); - - Assert.assertNotSame(nodeMap, copy); - - Assert.assertEquals(values.keySet(), copy.keySet()); - // Also verify that original value wasn't changed by the serialization - Assert.assertEquals(values.keySet(), nodeMap.keySet()); - - values.keySet().forEach(key -> { - if (key.startsWith("json")) { - // Json values are not equals - JsonValue originalValue = (JsonValue) nodeMap.get(key); - JsonValue copyValue = (JsonValue) copy.get(key); - - Assert.assertEquals(originalValue.toJson(), copyValue.toJson()); - } else { - Assert.assertEquals(nodeMap.get(key), copy.get(key)); - } - - // Verify original was not touched - Assert.assertSame(values.get(key), nodeMap.get(key)); - }); - } - - @Test - public void testGetIntDefaultValue() { - Assert.assertEquals(12, nodeMap.getOrDefault(KEY, 12)); - - nodeMap.put(KEY, 24); - Assert.assertEquals(24, nodeMap.getOrDefault(KEY, 12)); - - nodeMap.put(KEY, null); - Assert.assertEquals(12, nodeMap.getOrDefault(KEY, 12)); - - nodeMap.remove(KEY); - Assert.assertEquals(12, nodeMap.getOrDefault(KEY, 12)); - } - - @Test - public void testGetBooleanDefaultValue() { - Assert.assertTrue(nodeMap.getOrDefault(KEY, true)); - Assert.assertFalse(nodeMap.getOrDefault(KEY, false)); - - nodeMap.put(KEY, true); - Assert.assertTrue(nodeMap.getOrDefault(KEY, false)); - - nodeMap.put(KEY, null); - Assert.assertTrue(nodeMap.getOrDefault(KEY, true)); - Assert.assertFalse(nodeMap.getOrDefault(KEY, false)); - - nodeMap.remove(KEY); - Assert.assertTrue(nodeMap.getOrDefault(KEY, true)); - Assert.assertFalse(nodeMap.getOrDefault(KEY, false)); - } - - @Test - public void testGetStringDefaultValue() { - Assert.assertEquals("default", nodeMap.getOrDefault(KEY, "default")); - - nodeMap.put(KEY, "assigned"); - Assert.assertEquals("assigned", nodeMap.getOrDefault(KEY, "default")); - - nodeMap.put(KEY, null); - Assert.assertEquals("default", nodeMap.getOrDefault(KEY, "default")); - - nodeMap.remove(KEY); - Assert.assertEquals("default", nodeMap.getOrDefault(KEY, "default")); - } - - @Test - public void testClear() { - nodeMap.put("foo", 1); - nodeMap.put("bar", 1); - nodeMap.put("baz", 1); - nodeMap.clear(); - Assert.assertEquals(0, nodeMap.getPropertyNames().count()); - Assert.assertFalse(nodeMap.hasProperty("foo")); - Assert.assertFalse(nodeMap.hasProperty("bar")); - Assert.assertFalse(nodeMap.hasProperty("baz")); - } - - @Test - public void put_sameValue_hasNoEffect() { - StateTree tree = new StateTree(new UI().getInternals(), - ElementChildrenList.class); - StateNode child = new StateNode(); - - AtomicBoolean listenerIsCalled = new AtomicBoolean(); - child.addAttachListener(() -> { - Assert.assertFalse(listenerIsCalled.get()); - listenerIsCalled.set(true); - }); - - nodeMap.put("foo", child); - - tree.getRootNode().getFeature(ElementChildrenList.class) - .add(child.getParent()); - - Assert.assertTrue(listenerIsCalled.get()); - - // The attach listener is not called one more time - nodeMap.put("foo", child); - } - - @Test - public void put_replaceSingleValue_stillUseSingleValue() { - nodeMap.put("foo", "bar"); - - Assert.assertTrue(nodeMap.usesSingleMap()); - - nodeMap.put("foo", "baz"); - - Assert.assertTrue(nodeMap.usesSingleMap()); - } - - @Test - public void streamSingleNullValue() { - nodeMap.put("foo", null); - - Assert.assertTrue(nodeMap.usesSingleMap()); - - nodeMap.forEachChild(child -> { - Assert.fail( - "Should not happen, but forEachChild shouldn't explode either"); - }); - } - - @Test - public void collectChanges_sameValue_alwaysCollect_allValueChangesCollected() { - StateNode node = new StateNode(ElementPropertyMap.class); - AlwaysProduceChangeMap map = new AlwaysProduceChangeMap(node); - - assertChangeCollected(map); - // change the same property one more time: it still should be collected - assertChangeCollected(map); - } - - @Test - public void put_sameValue_alwaysProduceChange_nodeIsDirty() { - UI ui = new UI(); - StateNode node = new StateNode(ElementPropertyMap.class); - StateTree tree = ui.getInternals().getStateTree(); - tree.getRootNode().getFeature(ElementChildrenList.class).add(node); - AlwaysProduceChangeMap map = new AlwaysProduceChangeMap(node); - - // clear dirty nodes - tree.collectChanges(change -> { - }); - - map.put("foo", "bar"); - - Set nodes = tree.collectDirtyNodes(); - Assert.assertTrue(nodes.contains(node)); - - // clear dirty nodes - tree.collectChanges(change -> { - }); - - Assert.assertTrue(tree.collectDirtyNodes().isEmpty()); - - // set once again the same value - map.put("foo", "bar"); - - nodes = tree.collectDirtyNodes(); - Assert.assertTrue(nodes.contains(node)); - } - - @Test - public void put_sameValue_neverProduceChange_nodeIsNotDirty() { - UI ui = new UI(); - StateNode node = new StateNode(ElementPropertyMap.class); - StateTree tree = ui.getInternals().getStateTree(); - tree.getRootNode().getFeature(ElementChildrenList.class).add(node); - NeverProduceChangeMap map = new NeverProduceChangeMap(node); - - // clear dirty nodes - tree.collectChanges(change -> { - }); - - map.put("foo", "bar"); - - Set nodes = tree.collectDirtyNodes(); - Assert.assertFalse(nodes.contains(node)); - - // clear dirty nodes - tree.collectChanges(change -> { - }); - - Assert.assertTrue(tree.collectDirtyNodes().isEmpty()); - - // set another value - map.put("foo", "baz"); - - nodes = tree.collectDirtyNodes(); - Assert.assertFalse(nodes.contains(node)); - } - - @Test - public void collectChanges_sameValue_neverCollect_noValueChanges() { - StateNode node = new StateNode(ElementPropertyMap.class); - NeverProduceChangeMap map = new NeverProduceChangeMap(node); - - assertChangeIsNotCollected(map, "bar"); - // change the same property one more time to another value: it still - // should not be collected - assertChangeIsNotCollected(map, "baz"); - } - - private void assertChangeIsNotCollected(NeverProduceChangeMap map, - String value) { - map.put("foo", value); - - List changes = new ArrayList<>(); - map.collectChanges(changes::add); - - Assert.assertTrue(changes.isEmpty()); - } - - private void assertChangeCollected(AlwaysProduceChangeMap map) { - map.put("foo", "bar"); - - List changes = new ArrayList<>(); - map.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertEquals(MapPutChange.class, changes.get(0).getClass()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeValueEmptyRequiredFeatureTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeValueEmptyRequiredFeatureTest.java deleted file mode 100644 index 07683e4a229..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/NodeValueEmptyRequiredFeatureTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.change.EmptyChange; -import com.vaadin.flow.internal.change.MapPutChange; -import com.vaadin.flow.internal.change.NodeChange; - -public class NodeValueEmptyRequiredFeatureTest { - - private StateNode node; - - private NodeValue nodeValue; - - @Before - public void setUp() { - node = new StateNode(Arrays.asList(BasicTypeValue.class)) { - @Override - public boolean isAttached() { - return true; - } - }; - nodeValue = node.getFeature(BasicTypeValue.class); - } - - @Test - public void generateChangesFromEmpty_featureHasChangesToCollect() { - nodeValue.generateChangesFromEmpty(); - - AtomicReference change = new AtomicReference<>(); - node.collectChanges(change::set); - - Assert.assertTrue(change.get() instanceof EmptyChange); - - nodeValue.generateChangesFromEmpty(); - change.set(null); - node.collectChanges(change::set); - Assert.assertNull(change.get()); - } - - @Test - public void generateChangesFromEmpty_noEmptyChange() { - nodeValue.setValue("foo"); - node.clearChanges(); - nodeValue.generateChangesFromEmpty(); - - List changes = new ArrayList<>(); - node.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - } - - @Test - public void collectChanges_featureHasEmptyChange() { - nodeValue.generateChangesFromEmpty(); - - AtomicReference change = new AtomicReference<>(); - nodeValue.collectChanges(change::set); - - Assert.assertTrue(change.get() instanceof EmptyChange); - - change.set(null); - nodeValue.collectChanges(change::set); - Assert.assertNull(change.get()); - } - - @Test - public void collectChanges_noEmptyChange() { - nodeValue.setValue("foo"); - - List changes = new ArrayList<>(); - node.collectChanges(changes::add); - - Assert.assertEquals(1, changes.size()); - Assert.assertTrue(changes.get(0) instanceof MapPutChange); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PollConfigurationMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PollConfigurationMapTest.java deleted file mode 100644 index 165ea270470..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PollConfigurationMapTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.vaadin.flow.internal.nodefeature; - -import org.junit.Assert; -import org.junit.Test; - -public class PollConfigurationMapTest - extends AbstractMapFeatureTest { - - private final PollConfigurationMap map = createFeature(); - - @Test - public void setDefaultPollInterval() { - Assert.assertEquals(-1, map.getPollInterval()); - } - - @Test - public void setGetPollInterval() { - super.testInt(map, PollConfigurationMap.POLL_INTERVAL_KEY, - map::setPollInterval, map::getPollInterval); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PolymerServerEventHandlersTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PolymerServerEventHandlersTest.java deleted file mode 100644 index 1e46eca04ee..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PolymerServerEventHandlersTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.EventData; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.polymertemplate.EventHandler; -import com.vaadin.flow.component.polymertemplate.RepeatIndex; -import com.vaadin.flow.component.template.internal.DeprecatedPolymerTemplate; -import com.vaadin.flow.dom.impl.BasicElementStateProvider; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.ConstantPoolKey; -import com.vaadin.flow.internal.HasCurrentService; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.server.VaadinService; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.impl.JreJsonArray; -import net.jcip.annotations.NotThreadSafe; - -/** - * @author Vaadin Ltd - * @since 1.0. - */ -@NotThreadSafe -public class PolymerServerEventHandlersTest extends HasCurrentService { - private StateNode stateNode; - private PolymerServerEventHandlers handlers; - private Collection methodCollector; - private Map correctlyAnnotatedHandlers; - private Map wronglyAnnotatedHandlers; - - private static class AbstractTemplate extends Component - implements DeprecatedPolymerTemplate { - - } - - @Tag("polymer") - private static class CorrectAnnotationUsage extends AbstractTemplate { - - @EventHandler - public void noParams() { - } - - @EventHandler - public void eventDataParam(@EventData("test") String test) { - } - - @EventHandler - public void repeatIndexParam1(@RepeatIndex int index) { - } - - @EventHandler - public void repeatIndexParam2(@RepeatIndex Integer index) { - } - - @EventHandler - public void eventDataAndRepeatIndexOnDifferentParams( - @EventData("test") String test, @RepeatIndex int index) { - } - - } - - private static class WrongAnnotationUsage { - @EventHandler - public void notAnnotatedParam(int iCauseExceptions) { - } - - @EventHandler - public void wrongTypeOfRepeatIndexParam( - @RepeatIndex String iCauseThemToo) { - } - - @EventHandler - public void eventDataAndRepeatIndexOnOneParam( - @EventData("test") @RepeatIndex int meToo) { - } - } - - private static Map getEventHandlerNamesAndMethods( - Class clazz) { - return Stream.of(clazz.getMethods()) - .filter(method -> Objects - .nonNull(method.getAnnotation(EventHandler.class))) - .collect( - Collectors.toMap(Method::getName, Function.identity())); - } - - @Before - public void setUp() { - Collection> features = BasicElementStateProvider - .getFeatures(); - stateNode = new StateNode(features.toArray(new Class[features.size()])); - stateNode.getFeature(ElementData.class).setTag("test"); - handlers = new PolymerServerEventHandlers(stateNode); - methodCollector = new ArrayList<>(); - correctlyAnnotatedHandlers = getEventHandlerNamesAndMethods( - CorrectAnnotationUsage.class); - wronglyAnnotatedHandlers = getEventHandlerNamesAndMethods( - WrongAnnotationUsage.class); - - } - - @Override - protected VaadinService createService() { - VaadinService service = Mockito.mock(VaadinService.class); - DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(configuration.isProductionMode()).thenReturn(true); - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - - return service; - } - - private void addAndVerifyMethod(Method method) { - handlers.addHandlerMethod(method, methodCollector); - - assertEquals(1, methodCollector.size()); - assertEquals(method, methodCollector.iterator().next()); - assertEquals(method.getParameters().length, - extractParametersData(method).length()); - } - - private JreJsonArray extractParametersData(Method method) { - ConstantPoolKey parametersData = (ConstantPoolKey) stateNode - .getFeature(PolymerEventListenerMap.class) - .get(method.getName()); - assertNotNull(parametersData); - - JsonObject json = Json.createObject(); - parametersData.export(json); - return json.get(parametersData.getId()); - } - - @Test - public void testNoParamsMethod() { - addAndVerifyMethod(correctlyAnnotatedHandlers.get("noParams")); - } - - @Test - public void testCorrectMethodWithDifferentAnnotations() - throws NoSuchFieldException, IllegalAccessException { - // Insert component without using ComponentMapping::setComponent as we - // only want to map and test the method - // `eventDataAndRepeatIndexOnDifferentParams` - Field component = ComponentMapping.class.getDeclaredField("component"); - component.setAccessible(true); - component.set(stateNode.getFeature(ComponentMapping.class), - new CorrectAnnotationUsage()); - addAndVerifyMethod(correctlyAnnotatedHandlers - .get("eventDataAndRepeatIndexOnDifferentParams")); - } - - @Test - public void testEventDataParam() - throws NoSuchFieldException, IllegalAccessException { - // Insert component without using ComponentMapping::setComponent as we - // only want to map and test the method `eventDataParam` - Field component = ComponentMapping.class.getDeclaredField("component"); - component.setAccessible(true); - component.set(stateNode.getFeature(ComponentMapping.class), - new CorrectAnnotationUsage()); - addAndVerifyMethod(correctlyAnnotatedHandlers.get("eventDataParam")); - } - - @Test - public void testRepeatIndexParam1() { - addAndVerifyMethod(correctlyAnnotatedHandlers.get("repeatIndexParam1")); - } - - @Test - public void testRepeatIndexParam2() { - addAndVerifyMethod(correctlyAnnotatedHandlers.get("repeatIndexParam2")); - } - - @Test(expected = IllegalStateException.class) - public void testNotAnnotatedParam() { - addAndVerifyMethod(wronglyAnnotatedHandlers.get("notAnnotatedParam")); - } - - @Test(expected = IllegalStateException.class) - public void testWrongTypeOfRepeatIndexParam() { - addAndVerifyMethod( - wronglyAnnotatedHandlers.get("wrongTypeOfRepeatIndexParam")); - } - - @Test(expected = IllegalStateException.class) - public void testMultipleAnnotationsOnOneParam() { - addAndVerifyMethod(wronglyAnnotatedHandlers - .get("eventDataAndRepeatIndexOnOneParam")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PushConfigurationMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PushConfigurationMapTest.java deleted file mode 100644 index 5da1eb7b2d0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/PushConfigurationMapTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.vaadin.flow.internal.nodefeature; - -import java.util.Arrays; -import java.util.Collection; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.shared.ui.Transport; - -public class PushConfigurationMapTest - extends AbstractNodeFeatureTest { - - private PushConfigurationMap ns = createFeature(); - - @Test - public void transportWebsocket() { - ns.setTransport(Transport.WEBSOCKET); - Assert.assertEquals(Transport.WEBSOCKET.getIdentifier(), - ns.getParameter("transport")); - Assert.assertFalse( - ns.contains(PushConfigurationMap.ALWAYS_USE_XHR_TO_SERVER)); - Assert.assertEquals(Transport.WEBSOCKET, ns.getTransport()); - } - - @Test - public void transportLongPolling() { - ns.setTransport(Transport.LONG_POLLING); - Assert.assertEquals(Transport.LONG_POLLING.getIdentifier(), - ns.getParameter("transport")); - Assert.assertFalse( - ns.contains(PushConfigurationMap.ALWAYS_USE_XHR_TO_SERVER)); - Assert.assertEquals(Transport.LONG_POLLING, ns.getTransport()); - } - - @Test - public void transportLongWebsocketXHR() { - ns.setTransport(Transport.WEBSOCKET_XHR); - Assert.assertEquals(Transport.WEBSOCKET.getIdentifier(), - ns.getParameter("transport")); - Assert.assertTrue((Boolean) ns - .get(PushConfigurationMap.ALWAYS_USE_XHR_TO_SERVER)); - Assert.assertEquals(Transport.WEBSOCKET_XHR, ns.getTransport()); - } - - @Test - public void fallbackTransportLongPolling() { - ns.setFallbackTransport(Transport.LONG_POLLING); - Assert.assertEquals(Transport.LONG_POLLING.getIdentifier(), - ns.getParameter("fallbackTransport")); - Assert.assertEquals(Transport.LONG_POLLING, ns.getFallbackTransport()); - } - - @Test - public void fallbackTransportWebsocket() { - ns.setFallbackTransport(Transport.WEBSOCKET); - Assert.assertEquals(Transport.WEBSOCKET.getIdentifier(), - ns.getParameter("fallbackTransport")); - Assert.assertEquals(Transport.WEBSOCKET, ns.getFallbackTransport()); - } - - @Test(expected = IllegalArgumentException.class) - public void fallbackTransportWebsocketXHR() { - ns.setFallbackTransport(Transport.WEBSOCKET_XHR); - } - - @Test - public void parameterNames() { - ns.setParameter("foo", "bar"); - Assert.assertArrayEquals(new String[] { "foo" }, - ns.getParameterNames().toArray()); - - ns.setTransport(Transport.WEBSOCKET); - ns.setFallbackTransport(Transport.LONG_POLLING); - - String[] expected = new String[] { "foo", "transport", - "fallbackTransport" }; - Collection paramNames = ns.getParameterNames(); - String[] actual = paramNames.toArray(new String[paramNames.size()]); - - // getParmeterNames does not guarantee order - Arrays.sort(expected); - Arrays.sort(actual); - Assert.assertArrayEquals(expected, actual); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ReconnectDialogConfigurationMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ReconnectDialogConfigurationMapTest.java deleted file mode 100644 index 99740e817ca..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ReconnectDialogConfigurationMapTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; - -public class ReconnectDialogConfigurationMapTest - extends AbstractMapFeatureTest { - - private StateNode node = new StateNode( - ReconnectDialogConfigurationMap.class); - private final ReconnectDialogConfigurationMap map = new ReconnectDialogConfigurationMap( - node); - - @Test - public void defaults() { - Assert.assertEquals(ReconnectDialogConfigurationMap.DIALOG_TEXT_DEFAULT, - map.getDialogText()); - Assert.assertEquals( - ReconnectDialogConfigurationMap.DIALOG_TEXT_GAVE_UP_DEFAULT, - map.getDialogTextGaveUp()); - Assert.assertEquals( - ReconnectDialogConfigurationMap.RECONNECT_ATTEMPTS_DEFAULT, - map.getReconnectAttempts()); - Assert.assertEquals( - ReconnectDialogConfigurationMap.RECONNECT_INTERVAL_DEFAULT, - map.getReconnectInterval()); - } - - @Test - public void setGetDialogText() { - testString(map, ReconnectDialogConfigurationMap.DIALOG_TEXT_KEY, - map::setDialogText, map::getDialogText); - } - - @Test - public void setGetDialogTextGaveUp() { - testString(map, ReconnectDialogConfigurationMap.DIALOG_TEXT_GAVE_UP_KEY, - map::setDialogTextGaveUp, map::getDialogTextGaveUp); - } - - @Test - public void setGetReconnectAttempts() { - testInt(map, ReconnectDialogConfigurationMap.RECONNECT_ATTEMPTS_KEY, - map::setReconnectAttempts, map::getReconnectAttempts); - } - - @Test - public void setGetReconnectInterval() { - testInt(map, ReconnectDialogConfigurationMap.RECONNECT_INTERVAL_KEY, - map::setReconnectInterval, map::getReconnectInterval); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ReturnChannelMapTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ReturnChannelMapTest.java deleted file mode 100644 index e10a4c32f0b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/ReturnChannelMapTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.dom.DisabledUpdateMode; -import com.vaadin.flow.internal.StateNode; - -import elemental.json.Json; -import elemental.json.JsonArray; - -public class ReturnChannelMapTest { - private StateNode node = new StateNode(ReturnChannelMap.class); - private ReturnChannelMap returnChannelMap = node - .getFeature(ReturnChannelMap.class); - - @Test - public void registerHandler_regstrationHasCorrectData() { - ReturnChannelRegistration registration = returnChannelMap - .registerChannel((arguments, channel) -> { - }); - - Assert.assertEquals("Node id should match", node.getId(), - registration.getStateNodeId()); - Assert.assertSame("Registration should be findable based on id", - registration, - returnChannelMap.get(registration.getChannelId())); - Assert.assertEquals( - "Default disabled update mode should be to allow when enabled", - DisabledUpdateMode.ONLY_WHEN_ENABLED, - registration.getDisabledUpdateMode()); - } - - @Test - public void twoArgsHandler_invoked() { - AtomicReference observedArguments = new AtomicReference<>(); - AtomicReference observedRegistration = new AtomicReference<>(); - - ReturnChannelRegistration registration = returnChannelMap - .registerChannel((arguments, channel) -> { - Assert.assertNotNull("Arguments should not be null", - arguments); - Assert.assertNull("There should be no previous arguments", - observedArguments.getAndSet(arguments)); - Assert.assertNull("There should be no previous channel", - observedRegistration.getAndSet(channel)); - }); - - Assert.assertNull("Handler should not yet be invoked", - observedArguments.get()); - - JsonArray arguments = Json.createArray(); - registration.invoke(arguments); - - Assert.assertSame(arguments, observedArguments.get()); - Assert.assertSame(registration, observedRegistration.get()); - } - - @Test - public void shorthandHandler_invoked() { - AtomicReference observedArguments = new AtomicReference<>(); - - ReturnChannelRegistration registration = returnChannelMap - .registerChannel(arguments -> { - Assert.assertNotNull("Arguments should not be null", - arguments); - Assert.assertNull("There should be no previous arguments", - observedArguments.getAndSet(arguments)); - }); - - Assert.assertNull("Handler should not yet be invoked", - observedArguments.get()); - - JsonArray arguments = Json.createArray(); - registration.invoke(arguments); - - Assert.assertSame(arguments, observedArguments.get()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/SerializableNodeListTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/SerializableNodeListTest.java deleted file mode 100644 index 33aeffdc10e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/SerializableNodeListTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.change.ListRemoveChange; -import com.vaadin.flow.internal.change.NodeChange; - -public class SerializableNodeListTest - extends AbstractNodeFeatureTest { - - private ElementClassList nodeList = createFeature(); - - @Test - public void testSerializable() { - nodeList.add("bar"); - nodeList.add(null); - - List values = new ArrayList<>(); - int size = nodeList.size(); - for (int i = 0; i < size; i++) { - values.add(nodeList.get(i)); - } - - NodeList copy = SerializationUtils - .deserialize(SerializationUtils.serialize(nodeList)); - - Assert.assertNotSame(nodeList, copy); - - Assert.assertEquals(values.size(), copy.size()); - for (int i = 0; i < size; i++) { - Assert.assertEquals(values.get(i), copy.get(i)); - } - // Also verify that original value wasn't changed by the serialization - Assert.assertEquals(values.size(), nodeList.size()); - for (int i = 0; i < size; i++) { - Assert.assertEquals(values.get(i), nodeList.get(i)); - } - - } - - @Test - public void testRemoveUsingIterator() { - nodeList.add("1"); - nodeList.add("2"); - nodeList.add("3"); - nodeList.add("4"); - nodeList.add("5"); - collectChanges(nodeList); - - Iterator i = nodeList.iterator(); - i.next(); - i.remove(); - List changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - Assert.assertEquals(0, - ((ListRemoveChange) changes.get(0)).getIndex()); - - i.next(); - i.next(); - i.remove(); - changes = collectChanges(nodeList); - Assert.assertEquals(1, changes.size()); - Assert.assertEquals(1, - ((ListRemoveChange) changes.get(0)).getIndex()); - - List actual = new ArrayList<>(); - for (int j = 0; j < nodeList.size(); j++) { - actual.add(nodeList.get(j)); - } - Assert.assertArrayEquals(new String[] { "2", "4", "5" }, - actual.toArray()); - - } - - @Test - public void clearUsingIterator() { - nodeList.add("1"); - nodeList.add("2"); - collectChanges(nodeList); - - Iterator i = nodeList.iterator(); - i.next(); - i.remove(); - i.next(); - i.remove(); - - List changes = collectChanges(nodeList); - Assert.assertEquals(2, changes.size()); - Assert.assertEquals(0, - ((ListRemoveChange) changes.get(0)).getIndex()); - Assert.assertEquals(0, - ((ListRemoveChange) changes.get(1)).getIndex()); - Assert.assertEquals(0, nodeList.size()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/StateNodeNodeListTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/StateNodeNodeListTest.java deleted file mode 100644 index 2f1c6a4b658..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/StateNodeNodeListTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.internal.nodefeature; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.lang3.SerializationUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateNodeTest; -import com.vaadin.flow.internal.change.ListAddChange; -import com.vaadin.flow.internal.change.ListRemoveChange; -import com.vaadin.flow.internal.change.NodeChange; - -public class StateNodeNodeListTest - extends AbstractNodeFeatureTest { - private NodeList nodeList = createFeature(); - - @Test - public void testAddingAndRemoving() { - StateNode value1 = StateNodeTest.createEmptyNode("value1"); - StateNode value2 = StateNodeTest.createEmptyNode("value2"); - - nodeList.add(value1); - - Assert.assertEquals(1, nodeList.size()); - Assert.assertSame(value1, nodeList.get(0)); - - List firstAddChanges = collectChanges(nodeList); - Assert.assertEquals(1, firstAddChanges.size()); - ListAddChange firstAddChange = (ListAddChange) firstAddChanges - .get(0); - Assert.assertEquals(0, firstAddChange.getIndex()); - Assert.assertEquals(Arrays.asList(value1), - firstAddChange.getNewItems()); - - nodeList.add(0, value2); - Assert.assertEquals(2, nodeList.size()); - Assert.assertSame(value2, nodeList.get(0)); - Assert.assertSame(value1, nodeList.get(1)); - - List secondAddChanges = collectChanges(nodeList); - Assert.assertEquals(1, secondAddChanges.size()); - ListAddChange secondAddChange = (ListAddChange) secondAddChanges - .get(0); - Assert.assertEquals(0, secondAddChange.getIndex()); - Assert.assertEquals(Arrays.asList(value2), - secondAddChange.getNewItems()); - - StateNode removedItem = nodeList.remove(0); - - Assert.assertEquals(1, nodeList.size()); - Assert.assertSame(value1, nodeList.get(0)); - Assert.assertSame(value2, removedItem); - - List removeChanges = collectChanges(nodeList); - Assert.assertEquals(1, removeChanges.size()); - ListRemoveChange removeChange = (ListRemoveChange) removeChanges - .get(0); - Assert.assertEquals(0, removeChange.getIndex()); - } - - @Test - public void testChangesAfterReset() { - StateNode value1 = StateNodeTest.createEmptyNode("value1"); - StateNode value2 = StateNodeTest.createEmptyNode("value2"); - - nodeList.add(value1); - nodeList.add(value2); - - nodeList.getNode().clearChanges(); - - nodeList.generateChangesFromEmpty(); - - List changes = collectChanges(nodeList); - - Assert.assertEquals(1, changes.size()); - ListAddChange change = (ListAddChange) changes.get(0); - Assert.assertEquals(0, change.getIndex()); - Assert.assertEquals(Arrays.asList(value1, value2), - change.getNewItems()); - } - - @Test - public void testAttachDetachChildren() { - StateNode child = StateNodeTest.createEmptyNode("child"); - - Assert.assertNull(child.getParent()); - - nodeList.add(child); - - Assert.assertSame(nodeList.getNode(), child.getParent()); - - nodeList.remove(0); - - Assert.assertNull(child.getParent()); - } - - @Test - public void testIndexOf() { - StateNode one = StateNodeTest.createEmptyNode("one"); - StateNode two = StateNodeTest.createEmptyNode("two"); - StateNode three = StateNodeTest.createEmptyNode("three"); - - nodeList.add(one); - nodeList.add(two); - Assert.assertEquals(0, nodeList.indexOf(one)); - Assert.assertEquals(1, nodeList.indexOf(two)); - Assert.assertEquals(-1, nodeList.indexOf(three)); - } - - @Test - public void testClear() { - StateNode one = StateNodeTest.createEmptyNode("one"); - StateNode two = StateNodeTest.createEmptyNode("two"); - - nodeList.add(one); - nodeList.add(two); - Assert.assertEquals(2, nodeList.size()); - nodeList.clear(); - Assert.assertEquals(0, nodeList.size()); - } - - @Test(expected = AssertionError.class) - public void nullNotAllowed() { - nodeList.add(null); - } - - @Test - public void testSerializable() { - StateNode one = StateNodeTest.createTestNode("one", - ElementClassList.class); - one.getFeature(ElementClassList.class).add("foo"); - one.getFeature(ElementClassList.class).add("bar"); - StateNode two = StateNodeTest.createTestNode("two", - ElementClassList.class); - two.getFeature(ElementClassList.class).add("baz"); - nodeList.add(one); - nodeList.add(two); - - List values = new ArrayList<>(); - int size = nodeList.size(); - for (int i = 0; i < size; i++) { - values.add(nodeList.get(i)); - } - - NodeList copy = SerializationUtils - .deserialize(SerializationUtils.serialize(nodeList)); - - Assert.assertNotSame(nodeList, copy); - - Assert.assertEquals(values.size(), copy.size()); - for (int i = 0; i < size; i++) { - assertNodeEquals(values.get(i), copy.get(i)); - } - // Also verify that original value wasn't changed by the serialization - Assert.assertEquals(values.size(), nodeList.size()); - for (int i = 0; i < size; i++) { - assertNodeEquals(values.get(i), nodeList.get(i)); - } - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/VirtualChildrenListTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/VirtualChildrenListTest.java deleted file mode 100644 index 96ddef1142b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/VirtualChildrenListTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import com.vaadin.flow.internal.StateNode; -import org.junit.Assert; -import org.junit.Test; - -import elemental.json.JsonObject; - -public class VirtualChildrenListTest { - - private StateNode node = new StateNode(VirtualChildrenList.class); - private VirtualChildrenList list = node - .getFeature(VirtualChildrenList.class); - - private StateNode child = new StateNode(ElementData.class); - - @Test - public void insert_atIndexWithType_payloadIsSetAndElementIsInserted() { - list.add(0, child, "foo", (String) null); - - Assert.assertEquals(child, list.get(0)); - - JsonObject payload = (JsonObject) child.getFeature(ElementData.class) - .getPayload(); - Assert.assertNotNull(payload); - - Assert.assertEquals("foo", payload.get(NodeProperties.TYPE).asString()); - - StateNode anotherChild = new StateNode(ElementData.class); - list.add(0, anotherChild, "bar", (String) null); - - Assert.assertEquals(anotherChild, list.get(0)); - - payload = (JsonObject) anotherChild.getFeature(ElementData.class) - .getPayload(); - Assert.assertNotNull(payload); - - Assert.assertEquals("bar", payload.get(NodeProperties.TYPE).asString()); - } - - @Test - public void insert_atIndexWithPayload_payloadIsSetAndElementIsInserted() { - list.add(0, child, "foo", "bar"); - - Assert.assertEquals(child, list.get(0)); - - JsonObject payload = (JsonObject) child.getFeature(ElementData.class) - .getPayload(); - Assert.assertNotNull(payload); - - Assert.assertEquals("foo", payload.get(NodeProperties.TYPE).asString()); - Assert.assertEquals("bar", - payload.get(NodeProperties.PAYLOAD).asString()); - } - - @Test - public void iteratorAndSize_addTwoItems_methodsReturnCorrectValues() { - list.append(child, "foo"); - StateNode anotherChild = new StateNode(ElementData.class); - list.append(anotherChild, "bar"); - - Assert.assertEquals(2, list.size()); - - Set set = StreamSupport - .stream(Spliterators.spliteratorUnknownSize(list.iterator(), - Spliterator.ORDERED), false) - .collect(Collectors.toSet()); - Assert.assertEquals(2, set.size()); - - set.remove(child); - set.remove(anotherChild); - - Assert.assertEquals(0, set.size()); - } - - @Test - public void remove_withIndex_removesNodeAndPayload() { - list.append(child, "foo"); - - Assert.assertEquals(child, list.get(0)); - - list.remove(0); - - Assert.assertEquals(0, list.size()); - Assert.assertEquals(-1, list.indexOf(child)); - - JsonObject payload = (JsonObject) child.getFeature(ElementData.class) - .getPayload(); - Assert.assertNull(payload); - } - - @Test(expected = UnsupportedOperationException.class) - public void clear_throw() { - list.append(child, "foo"); - list.clear(); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/VisibilityDataTest.java b/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/VisibilityDataTest.java deleted file mode 100644 index 96dc9bc4284..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/internal/nodefeature/VisibilityDataTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.internal.nodefeature; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.internal.StateNode; - -public class VisibilityDataTest { - - @Test - public void setVisible() { - StateNode node = new StateNode(ElementData.class); - ElementData data = node.getFeature(ElementData.class); - - Assert.assertNull(data.get(NodeProperties.VISIBLE)); - Assert.assertTrue(data.isVisible()); - - data.put(NodeProperties.VISIBLE, true); - Assert.assertTrue(data.isVisible()); - - data.put(NodeProperties.VISIBLE, false); - Assert.assertFalse(data.isVisible()); - } - - @Test - public void allowsChanges_delegateToIsVisible() { - ElementData data = Mockito.mock(ElementData.class); - - Mockito.doCallRealMethod().when(data).allowsChanges(); - - Mockito.when(data.isVisible()).thenReturn(true); - - Assert.assertTrue(data.allowsChanges()); - - Mockito.when(data.isVisible()).thenReturn(false); - - Assert.assertFalse(data.allowsChanges()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/DefaultRouteResolverTest.java b/flow-server/src/test/java/com/vaadin/flow/router/DefaultRouteResolverTest.java deleted file mode 100644 index 7510d83db01..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/DefaultRouteResolverTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.router.internal.DefaultRouteResolver; -import com.vaadin.flow.router.internal.ResolveRequest; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.RouteRegistry; - -public class DefaultRouteResolverTest extends RoutingTestBase { - - private RouteResolver resolver; - - @Override - public void init() throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - super.init(); - resolver = new DefaultRouteResolver(); - CurrentInstance.clearAll(); - } - - @Test - public void basic_route_navigation_target_resolved_correctly() - throws InvalidRouteConfigurationException { - - setRoutes(router.getRegistry(), - Stream.of(RootNavigationTarget.class, FooNavigationTarget.class, - FooBarNavigationTarget.class, - GreetingNavigationTarget.class) - .collect(Collectors.toSet())); - - Assert.assertEquals(RootNavigationTarget.class, - resolveNavigationTarget("")); - Assert.assertEquals(FooNavigationTarget.class, - resolveNavigationTarget("foo")); - Assert.assertEquals(FooBarNavigationTarget.class, - resolveNavigationTarget("foo/bar")); - } - - private void setRoutes(RouteRegistry registry, - Set> routes) { - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(registry); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - routes.forEach(routeConfiguration::setAnnotatedRoute); - }); - } - - @Test - public void no_route_found_resolves_to_null() { - Assert.assertNull( - "Attempting to resolve an invalid location should return null", - resolver.resolve(new ResolveRequest(router, - new Location("Not a configured location")))); - } - - @Test - public void string_url_parameter_correctly_set_to_state() - throws InvalidRouteConfigurationException { - setRoutes(router.getRegistry(), - Collections.singleton(GreetingNavigationTarget.class)); - - Assert.assertEquals(Collections.singletonList("World"), - resolveNavigationState("greeting/World").getUrlParameters() - .get()); - } - - @Test - public void route_precedence_with_parameters() - throws InvalidRouteConfigurationException { - setRoutes(router.getRegistry(), - Stream.of(GreetingNavigationTarget.class, - OtherGreetingNavigationTarget.class) - .collect(Collectors.toSet())); - - Assert.assertEquals(GreetingNavigationTarget.class, - resolveNavigationTarget("greeting/World")); - Assert.assertEquals(OtherGreetingNavigationTarget.class, - resolveNavigationTarget("greeting/other/World")); - } - - @Test - public void wrong_number_of_parameters_does_not_match() - throws InvalidRouteConfigurationException { - setRoutes(router.getRegistry(), - Collections.singleton(GreetingNavigationTarget.class)); - - Assert.assertEquals(null, - resolveNavigationState("greeting/World/something")); - Assert.assertEquals(null, resolveNavigationState("greeting")); - } - - private Class resolveNavigationTarget(String path) { - return resolveNavigationState(path).getNavigationTarget(); - } - - private NavigationState resolveNavigationState(String path) { - return resolver.resolve(new ResolveRequest(router, new Location(path))); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/ErrorParameterTest.java b/flow-server/src/test/java/com/vaadin/flow/router/ErrorParameterTest.java deleted file mode 100644 index 9f48b596ec7..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/ErrorParameterTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import org.junit.Assert; -import org.junit.Test; - -public class ErrorParameterTest { - @Test - public void matchingExceptionType() { - NullPointerException exception = new NullPointerException(); - - ErrorParameter errorParameter = new ErrorParameter<>( - NullPointerException.class, exception); - - Assert.assertSame(exception, errorParameter.getException()); - Assert.assertSame(exception, errorParameter.getCaughtException()); - } - - @Test - public void superExceptionType() { - NullPointerException exception = new NullPointerException(); - - ErrorParameter errorParameter = new ErrorParameter<>( - RuntimeException.class, exception); - - Assert.assertSame(exception, errorParameter.getException()); - Assert.assertSame(exception, errorParameter.getCaughtException()); - } - - @Test - public void matchingCauseType() { - NullPointerException cause = new NullPointerException(); - IllegalStateException exception = new IllegalStateException(cause); - - ErrorParameter errorParameter = new ErrorParameter<>( - NullPointerException.class, exception); - - Assert.assertSame(cause, errorParameter.getException()); - Assert.assertSame(exception, errorParameter.getCaughtException()); - } - - @Test - public void superMatchingCauseType() { - NullPointerException cause = new NullPointerException() { - - }; - IllegalStateException exception = new IllegalStateException(cause); - - ErrorParameter errorParameter = new ErrorParameter<>( - NullPointerException.class, exception); - - Assert.assertSame(cause, errorParameter.getException()); - Assert.assertSame(exception, errorParameter.getCaughtException()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/EventUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/router/EventUtilTest.java deleted file mode 100644 index 32c49db0dd0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/EventUtilTest.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Composite; -import com.vaadin.flow.component.HasElement; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.di.DefaultInstantiator; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.i18n.LocaleChangeEvent; -import com.vaadin.flow.i18n.LocaleChangeObserver; -import com.vaadin.flow.internal.nodefeature.NodeProperties; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; - -import static org.mockito.Mockito.when; - -/** - * Test event util functionality. - */ -public class EventUtilTest { - - private UI ui; - - @Tag(Tag.DIV) - public static class Foo extends Component { - } - - @Tag(Tag.DIV) - public static class Bar extends Component { - } - - @Tag("nested") - public static class LeaveObserver extends Component - implements BeforeLeaveObserver { - @Override - public void beforeLeave(BeforeLeaveEvent event) { - } - } - - @Tag("nested") - public static class EnterObserver extends Component - implements BeforeEnterObserver { - @Override - public void beforeEnter(BeforeEnterEvent event) { - } - } - - @Tag("nested") - public static class AfterObserver extends Component - implements AfterNavigationObserver { - @Override - public void afterNavigation(AfterNavigationEvent event) { - } - } - - @Tag("nested-locale") - public static class Locale extends Component - implements LocaleChangeObserver { - @Override - public void localeChange(LocaleChangeEvent event) { - - } - } - - public static class CompositeWrapper extends Composite { - - } - - @Before - public void setUp() { - VaadinSession session = Mockito.mock(VaadinSession.class); - ui = new UI() { - @Override - public VaadinSession getSession() { - return session; - } - }; - VaadinService service = Mockito.mock(VaadinService.class); - when(session.getService()).thenReturn(service); - DefaultInstantiator instantiator = new DefaultInstantiator(service); - when(service.getInstantiator()).thenReturn(instantiator); - UI.setCurrent(ui); - } - - @After - public void tearDown() { - UI.setCurrent(null); - } - - @Test - public void collectBeforeNavigationObserversFromUI() throws Exception { - UI ui = UI.getCurrent(); - Element node = ui.getElement(); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - Component.from(nested, LeaveObserver.class); - - List beforeNavigationObservers = EventUtil - .collectBeforeLeaveObservers(ui); - - Assert.assertEquals("Wrong amount of listener instances found", 1, - beforeNavigationObservers.size()); - } - - @Test - public void collectBeforeNavigationObserversFromUI_elementHasVirtualChildren() - throws Exception { - UI ui = UI.getCurrent(); - Element node = ui.getElement(); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendVirtualChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - - node.getStateProvider().appendVirtualChild(node.getNode(), - new Element("attached-by-id"), NodeProperties.INJECT_BY_ID, - "id"); - - Component.from(nested, LeaveObserver.class); - - List beforeNavigationObservers = EventUtil - .collectBeforeLeaveObservers(ui); - - Assert.assertEquals("Wrong amount of listener instances found", 1, - beforeNavigationObservers.size()); - } - - @Test - public void collectBeforeNavigationObserversFromChains() throws Exception { - Foo foo = new Foo(); - EnterObserver toBeDetached = new EnterObserver(); - foo.getElement().appendChild(new EnterObserver().getElement(), - toBeDetached.getElement()); - Bar bar = new Bar(); - - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new EnterObserver().getElement()); - - bar.getElement().appendChild(new Foo().getElement(), nested); - - EnterObserver toBeAttached = new EnterObserver(); - - Collection oldChain = Arrays.asList(foo, - toBeDetached); - Collection newChain = Arrays.asList(foo, - toBeAttached); - List beforeNavigationObservers = EventUtil - .collectBeforeEnterObservers(oldChain, newChain); - - Assert.assertEquals("Wrong amount of listener instances found", 2, - beforeNavigationObservers.size()); - } - - @Test - public void collectAfterNavigationObservers() { - UI ui = UI.getCurrent(); - - Element menu = new Element("menu"); - menu.appendChild(new AfterObserver().getElement()); - - Element node = ui.getElement(); - node.appendChild(new Element("main"), menu); - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - Component.from(nested, AfterObserver.class); - - List beforeNavigationObservers = EventUtil - .collectAfterNavigationObservers(ui); - - Assert.assertEquals("Wrong amount of listener instances found", 2, - beforeNavigationObservers.size()); - } - - @Test - public void inspectChildrenHierarchy() throws Exception { - Element node = new Element("root"); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - - List elements = new ArrayList<>(); - - EventUtil.inspectHierarchy(node, elements, element -> true); - - Assert.assertEquals("Missing elements from list.", 6, elements.size()); - } - - @Test - public void inspectChildrenHierarchy_selective() throws Exception { - Element node = new Element("root"); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - - List elements = new ArrayList<>(); - - EventUtil.inspectHierarchy(node, elements, - element -> !nested.equals(element)); - - Assert.assertEquals("Missing elements from list.", 3, elements.size()); - } - - @Test - public void inspectMixedChildrenHierarchy() throws Exception { - Element node = new Element("root"); - node.appendVirtualChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendVirtualChild(new Element("nested-virtual-child"), - new Element("nested-virtual-child-2")); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - nested.getStateProvider().appendVirtualChild(nested.getNode(), - new Element("attached-by-id"), NodeProperties.INJECT_BY_ID, - "id"); - nested.getStateProvider().appendVirtualChild(nested.getNode(), - new Element("attached-by-id"), - NodeProperties.TEMPLATE_IN_TEMPLATE, ""); - - node.appendChild(nested); - - List elements = new ArrayList<>(); - - EventUtil.inspectHierarchy(node, elements, element -> true); - - Assert.assertEquals("Missing elements from list.", 10, elements.size()); - } - - @Test - public void getImplementingComponents() throws Exception { - Element node = new Element("root"); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - Component.from(nested, EnterObserver.class); - - List elements = new ArrayList<>(); - - EventUtil.inspectHierarchy(node, elements, element -> true); - - List listenerComponents = EventUtil - .getImplementingComponents(elements.stream(), - BeforeEnterObserver.class) - .collect(Collectors.toList()); - - Assert.assertEquals("Wrong amount of listener instances found", 1, - listenerComponents.size()); - } - - @Test - public void getImplementingComponents_elementHasVirtualChildren() - throws Exception { - Element node = new Element("root"); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.getStateProvider().appendVirtualChild(node.getNode(), nested, - NodeProperties.TEMPLATE_IN_TEMPLATE, ""); - Component.from(nested, EnterObserver.class); - - List elements = new ArrayList<>(); - - EventUtil.inspectHierarchy(node, elements, element -> true); - - List listenerComponents = EventUtil - .getImplementingComponents(elements.stream(), - BeforeEnterObserver.class) - .collect(Collectors.toList()); - - Assert.assertEquals("Wrong amount of listener instances found", 1, - listenerComponents.size()); - } - - @Test - public void collectLocaleChangeObserverFromElement() throws Exception { - Element node = new Element("root"); - node.appendChild(new Element("main"), new Element("menu")); - Element nested = new Element("nested-locale"); - nested.appendChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendChild(nested); - Component.from(nested, Locale.class); - - List beforeNavigationObservers = EventUtil - .collectLocaleChangeObservers(node); - - Assert.assertEquals("Wrong amount of listener instances found", 1, - beforeNavigationObservers.size()); - } - - @Test - public void collectLocaleChangeObserverFromElement_elementHasVirtualChildren() - throws Exception { - Element node = new Element("root"); - node.appendChild(new Element("main"), new Element("menu")); - node.appendVirtualChild(new Element("main-virtual"), - new Element("menu-virtual")); - Element nested = new Element("nested-locale"); - nested.appendVirtualChild(new Element("nested-child"), - new Element("nested-child-2")); - - node.appendVirtualChild(nested); - Component.from(nested, Locale.class); - - List beforeNavigationObservers = EventUtil - .collectLocaleChangeObservers(node); - - Assert.assertEquals("Wrong amount of listener instances found", 1, - beforeNavigationObservers.size()); - } - - @Test - public void collectLocaleChangeObserverFromComponentList() - throws Exception { - Foo foo = new Foo(); - foo.getElement().appendChild(new Locale().getElement()); - Bar bar = new Bar(); - - Element nested = new Element("nested-locale"); - nested.appendChild(new Element("nested-child"), - new Locale().getElement()); - - bar.getElement().appendChild(new Foo().getElement(), nested); - - List beforeNavigationObservers = EventUtil - .collectLocaleChangeObservers(Arrays.asList(foo, bar)); - - Assert.assertEquals("Wrong amount of listener instances found", 2, - beforeNavigationObservers.size()); - } - - @Test - public void collectLocaleChangeObserverFromComponentList_elementHasVirtualChildren() - throws Exception { - Foo foo = new Foo(); - foo.getElement().appendChild(new Locale().getElement()); - Bar bar = new Bar(); - - Element nested = new Element("nested-locale"); - nested.appendChild(new Element("nested-child"), - new Locale().getElement()); - - bar.getElement().appendChild(new Foo().getElement(), nested); - - List beforeNavigationObservers = EventUtil - .collectLocaleChangeObservers(Arrays.asList(foo, bar)); - - Assert.assertEquals("Wrong amount of listener instances found", 2, - beforeNavigationObservers.size()); - } - - @Test - public void getImplementingComponents_hasComposite_originalComponentIsReturned() { - CompositeWrapper wrapper = new CompositeWrapper(); - List components = EventUtil - .getImplementingComponents(Stream.of(wrapper.getElement()), - BeforeEnterObserver.class) - .distinct().collect(Collectors.toList()); - Assert.assertEquals(1, components.size()); - Assert.assertEquals(EnterObserver.class, components.get(0).getClass()); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/HighlightConditionsTest.java b/flow-server/src/test/java/com/vaadin/flow/router/HighlightConditionsTest.java deleted file mode 100644 index 67bf9a9c6ee..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/HighlightConditionsTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -public class HighlightConditionsTest { - - @Test - public void locationPrefix_defaultRoute_emptyLocationMatches() { - HighlightCondition condition = HighlightConditions - .locationPrefix(); - RouterLink link = Mockito.mock(RouterLink.class); - AfterNavigationEvent event = Mockito.mock(AfterNavigationEvent.class); - - Mockito.when(link.getHref()).thenReturn(""); - Location location = new Location(""); - Mockito.when(event.getLocation()).thenReturn(location); - Assert.assertTrue(condition.shouldHighlight(link, event)); - } - - @Test - public void locationPrefix_defaultRoute_nonEmptyLocationDoesNotMatch() { - HighlightCondition condition = HighlightConditions - .locationPrefix(); - RouterLink link = Mockito.mock(RouterLink.class); - AfterNavigationEvent event = Mockito.mock(AfterNavigationEvent.class); - - Mockito.when(link.getHref()).thenReturn(""); - Location location = new Location("foo"); - Mockito.when(event.getLocation()).thenReturn(location); - Assert.assertFalse(condition.shouldHighlight(link, event)); - } - - @Test - public void locationPrefix_notDefaultRoute_prefixMatches() { - HighlightCondition condition = HighlightConditions - .locationPrefix(); - RouterLink link = Mockito.mock(RouterLink.class); - AfterNavigationEvent event = Mockito.mock(AfterNavigationEvent.class); - - Mockito.when(link.getHref()).thenReturn("foo"); - Location location = new Location("foobar"); - Mockito.when(event.getLocation()).thenReturn(location); - Assert.assertTrue(condition.shouldHighlight(link, event)); - } - - @Test - public void locationPrefix_notDefaultRoute_nonPrefixDoesNotMatch() { - HighlightCondition condition = HighlightConditions - .locationPrefix(); - RouterLink link = Mockito.mock(RouterLink.class); - AfterNavigationEvent event = Mockito.mock(AfterNavigationEvent.class); - - Mockito.when(link.getHref()).thenReturn("foo"); - Location location = new Location("bar"); - Mockito.when(event.getLocation()).thenReturn(location); - Assert.assertFalse(condition.shouldHighlight(link, event)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/InternalServerErrorTest.java b/flow-server/src/test/java/com/vaadin/flow/router/InternalServerErrorTest.java deleted file mode 100644 index 62447ad3a74..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/InternalServerErrorTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.VaadinService; - -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe -public class InternalServerErrorTest { - - private BeforeEnterEvent event = Mockito.mock(BeforeEnterEvent.class); - - private VaadinService service = Mockito.mock(VaadinService.class); - - private DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - - @Before - public void setUp() { - VaadinService.setCurrent(service); - - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - - Location location = new Location("bar"); - Mockito.when(event.getLocation()).thenReturn(location); - } - - @After - public void tearDown() { - VaadinService.setCurrent(null); - } - - @Test - public void productionMode_noWarningAndStacktrace() { - Mockito.when(configuration.isProductionMode()).thenReturn(true); - - InternalServerError testInstance = new InternalServerError(); - - testInstance.setErrorParameter(event, new ErrorParameter<>( - Exception.class, new NullPointerException("foo"))); - - Assert.assertEquals( - "Only a text node with exception message should be shown", 1, - testInstance.getElement().getChildCount()); - } - - @Test - public void nonProductionMode_noLogBinding_showWaringAndStacktrace() { - Mockito.when(configuration.isProductionMode()).thenReturn(false); - - InternalServerError testInstance = new InternalServerError() { - - @Override - protected boolean hasLogBinding() { - return false; - } - }; - - testInstance.setErrorParameter(event, new ErrorParameter<>( - Exception.class, new NullPointerException("foo"))); - - Assert.assertEquals( - "3 elements should be shown: exception text, warning about log binding absence and exception stacktrace", - 3, testInstance.getElement().getChildCount()); - - Element warning = testInstance.getElement().getChild(1); - Assert.assertEquals("div", warning.getTag()); - Assert.assertTrue(warning.getText().contains("SLF4J")); - - Element stacktrace = testInstance.getElement().getChild(2); - Assert.assertEquals("pre", stacktrace.getTag()); - Assert.assertTrue(stacktrace.getText() - .contains(NullPointerException.class.getName())); - Assert.assertTrue(stacktrace.getText().contains("foo")); - } - - @Test - public void nonProductionMode_hasLogBinding_showStacktraceAndNoWarning() { - Mockito.when(configuration.isProductionMode()).thenReturn(false); - - InternalServerError testInstance = new InternalServerError() { - - @Override - protected boolean hasLogBinding() { - return true; - } - }; - - testInstance.setErrorParameter(event, new ErrorParameter<>( - Exception.class, new NullPointerException("foo"))); - - Assert.assertEquals( - "2 elements should be shown: exception text and exception stacktrace", - 2, testInstance.getElement().getChildCount()); - - Element stacktrace = testInstance.getElement().getChild(1); - Assert.assertEquals("pre", stacktrace.getTag()); - Assert.assertTrue(stacktrace.getText() - .contains(NullPointerException.class.getName())); - Assert.assertTrue(stacktrace.getText().contains("foo")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/LocationTest.java b/flow-server/src/test/java/com/vaadin/flow/router/LocationTest.java deleted file mode 100644 index 8a0e3888d80..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/LocationTest.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.junit.Assert.assertEquals; - -public class LocationTest { - @Test - public void parseLocation() { - Location location = new Location("foo/bar/baz"); - - assertEquals(Arrays.asList("foo", "bar", "baz"), - location.getSegments()); - assertEquals("foo/bar/baz", location.getPath()); - } - - @Test - public void parseLocationWithEndingSlash() { - Location location = new Location("foo/bar/"); - - assertEquals(Arrays.asList("foo", "bar", ""), location.getSegments()); - } - - @Test - public void parseLocationStartingWithSlash() { - Location location = new Location("/foo/bar/"); - assertEquals(Arrays.asList("foo", "bar", ""), location.getSegments()); - } - - @Test - public void parseNullLocation() { - Location location = new Location((String) null); - assertEquals(Arrays.asList(""), location.getSegments()); - } - - @Test - public void parseNullLocationWithParameters() { - Location location = new Location((String) null, - QueryParameters.fromString("foo")); - assertEquals(Arrays.asList(""), location.getSegments()); - } - - @Test - public void parseLocationWithQueryStringOnly() { - Location location = new Location("?hey=hola&zz="); - assertEquals("", location.getPath()); - Map> queryMap = new HashMap<>(); - queryMap.put("hey", Collections.singletonList("hola")); - queryMap.put("zz", Collections.emptyList()); - - assertEquals(Collections.singletonList("hola"), - location.getQueryParameters().getParameters().get("hey")); - assertEquals(Collections.singletonList(""), - location.getQueryParameters().getParameters().get("zz")); - } - - @Test - public void parseLocationWithQueryString_noValue() { - Location location = new Location("path?query"); - - assertEquals("path", location.getPath()); - assertEquals( - Collections.singletonMap("query", - Collections.singletonList("")), - location.getQueryParameters().getParameters()); - assertEquals("path?query", location.getPathWithQueryParameters()); - } - - @Test - public void parseLocationWithQueryString_emptyValue() { - Location location = new Location("path?query="); - - assertEquals("path", location.getPath()); - assertEquals( - Collections.singletonMap("query", - Collections.singletonList("")), - location.getQueryParameters().getParameters()); - assertEquals("path?query", location.getPathWithQueryParameters()); - } - - @Test - public void locationFromSegments() { - Location location = new Location(Arrays.asList("one", "two")); - assertEquals(Arrays.asList("one", "two"), location.getSegments()); - assertEquals("one/two", location.getPath()); - } - - @Test - public void queryValue_decodedCorrectly() { - QueryParameters queryParameters = new Location("home?value+part") - .getQueryParameters(); - Assert.assertEquals("'+' should be decoded in map", "value part", - queryParameters.getParameters().keySet().iterator().next()); - Assert.assertEquals("'+' should not be decoded in query param string", - "value%20part", queryParameters.getQueryString()); - - queryParameters = new Location("home?someValue1%2BsomeValue2") - .getQueryParameters(); - Assert.assertEquals("'%2B' should be decoded in map", - "someValue1+someValue2", - queryParameters.getParameters().keySet().iterator().next()); - Assert.assertEquals("'%2B' should not be decoded in query param string", - "someValue1%2BsomeValue2", queryParameters.getQueryString()); - - queryParameters = new Location("home?%25HF").getQueryParameters(); - Assert.assertEquals("'%25' should be decoded in map", "%HF", - queryParameters.getParameters().keySet().iterator().next()); - Assert.assertEquals("'%25' should not be decoded in query param string", - "%25HF", queryParameters.getQueryString()); - - queryParameters = new Location("home?p=%26&q=%20").getQueryParameters(); - Assert.assertEquals("'%26' should be decoded in map", "&", - queryParameters.getParameters().get("p").get(0)); - Assert.assertEquals("'%20' should be decoded in map", " ", - queryParameters.getParameters().get("q").get(0)); - Assert.assertEquals( - "'%26' and '%20' should not be decoded in query param string", - "p=%26&q=%20", queryParameters.getQueryString()); - } - - @Test - public void subLocation() { - Location location = new Location(Arrays.asList("one", "two", "three")); - - assertEquals("one", location.getFirstSegment()); - - Optional subLocation = location.getSubLocation(); - assertEquals(Arrays.asList("two", "three"), - subLocation.get().getSegments()); - assertEquals("two/three", subLocation.get().getPath()); - - } - - @Test(expected = IllegalArgumentException.class) - public void emptyLocation() { - new Location(Collections.emptyList()); - } - - @Test - public void noSubLocation_emptyOptional() { - Location location = new Location("foo"); - Optional maybeSubLocation = location.getSubLocation(); - - Assert.assertFalse(maybeSubLocation.isPresent()); - } - - @Test - public void spaceInLocation() { - Location location = new Location("foo bar"); - assertEquals("foo bar", location.getFirstSegment()); - } - - @Test - public void umlautInLocation() { - Location location = new Location("foo/åäö/bar"); - - assertEquals("foo", location.getSegments().get(0)); - assertEquals("åäö", location.getSegments().get(1)); - assertEquals("bar", location.getSegments().get(2)); - } - - @Test - public void toggleTrailingSlash() { - assertEquals("foo", - new Location("foo/").toggleTrailingSlash().getPath()); - assertEquals("foo/", - new Location("foo").toggleTrailingSlash().getPath()); - } - - @Test(expected = IllegalArgumentException.class) - public void toggleTrailingSlash_emtpyLocation() { - // Does not make sense to change the location to "/" - new Location("").toggleTrailingSlash(); - } - - @Test - public void locationWithParametersPath_emptyParams() { - String initialPath = "foo/bar/"; - Location location = new Location(initialPath); - - String pathWithParameters = location.getPathWithQueryParameters(); - - assertEquals(initialPath, pathWithParameters); - assertEquals(location.getPath(), pathWithParameters); - } - - @Test - public void locationWithParametersPath_withTrailingSlash() { - String initialPath = "foo/bar/"; - QueryParameters queryParams = getQueryParameters(); - Location location = new Location(initialPath, queryParams); - - String pathWithParameters = location.getPathWithQueryParameters(); - - assertEquals(initialPath + '?' + queryParams.getQueryString(), - pathWithParameters); - } - - @Test - public void locationWithParametersPath_withoutTrailingSlash() { - String initialPath = "foo/bar"; - QueryParameters queryParams = getQueryParameters(); - Location location = new Location(initialPath, queryParams); - - String pathWithParameters = location.getPathWithQueryParameters(); - - assertEquals(initialPath + '?' + queryParams.getQueryString(), - pathWithParameters); - } - - private static QueryParameters getQueryParameters() { - Map inputParameters = new HashMap<>(); - inputParameters.put("one", new String[] { "1", "11" }); - inputParameters.put("two", new String[] { "2", "22" }); - inputParameters.put("three", new String[] { "3" }); - - return QueryParameters.full(inputParameters); - } - - @Test - public void locationWithParamsInUrl() { - String initialPath = "foo/bar/"; - QueryParameters queryParams = getQueryParameters(); - Location location = new Location(initialPath, queryParams); - - assertEquals("foo/bar/", location.getPath()); - assertEquals(queryParams.getParameters(), - location.getQueryParameters().getParameters()); - } - - @Test - public void locationWithParamsInUrlAndParameters() { - Location location = new Location("foo/bar/?one&two=222", - getQueryParameters()); - assertEquals(Arrays.asList("foo", "bar", ""), location.getSegments()); - Assert.assertEquals( - "Query parameters should be taken from the constructor parameter, not from path", - "one=1&one=11&two=2&two=22&three=3", - location.getQueryParameters().getQueryString()); - } - - @Test - public void locationWithParamWithAndWithoutValue() { - Location location = new Location("foo?param¶m=bar"); - Assert.assertEquals("param¶m=bar", - location.getQueryParameters().getQueryString()); - - location = new Location("foo?param=bar¶m"); - Assert.assertEquals("param=bar¶m", - location.getQueryParameters().getQueryString()); - } - - @Test - public void locationWithParamAndEmptyValue() { - Location location = new Location("foo?param=¶m=bar"); - - Assert.assertEquals("param¶m=bar", - location.getQueryParameters().getQueryString()); - } - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Test - public void locationNameShouldBeAbleToHaveDotDot() { - Location location = new Location("..element"); - assertEquals("..element", location.getFirstSegment()); - - location = new Location("el..ement"); - assertEquals("el..ement", location.getFirstSegment()); - } - - @Test - public void locationShouldBeRelative() { - expectedEx.expect(InvalidLocationException.class); - expectedEx.expectMessage("Relative path cannot contain .. segments"); - - new Location("../element"); - } - - @Test - public void locationShouldNotEndWithDotDotSegment() { - expectedEx.expect(InvalidLocationException.class); - expectedEx.expectMessage("Relative path cannot contain .. segments"); - - new Location("element/.."); - } - - @Test - public void dotDotLocationShouldNotWork() { - expectedEx.expect(InvalidLocationException.class); - expectedEx.expectMessage("Relative path cannot contain .. segments"); - - new Location(".."); - } - - @Test - public void pathShouldBeEmpty() { - assertEquals("", new Location("").getPathWithQueryParameters()); - } - - @Test - public void locationWithUrlEncodedCharacters() { - Location location = new Location( - "foo?bar=a%20b%20%C3%B1%20%26%20%3F&baz=xyz"); - Assert.assertEquals(Arrays.asList("a b ñ & ?"), - location.getQueryParameters().getParameters().get("bar")); - Assert.assertEquals(Arrays.asList("xyz"), - location.getQueryParameters().getParameters().get("baz")); - Assert.assertEquals("bar=a%20b%20%C3%B1%20%26%20%3F&baz=xyz", - location.getQueryParameters().getQueryString()); - } - - @Test - public void colonInLocationPath_locationIsParsed() { - Location location = new Location("abc:foo/bar?baz"); - Assert.assertEquals("abc:foo/bar", location.getPath()); - Assert.assertEquals("baz", - location.getQueryParameters().getQueryString()); - } - - @Test - public void locationWithFragment_fragmentRetainedForPathWithQueryParameters() { - String locationString = "foo#fragment"; - Location location = new Location(locationString); - Assert.assertEquals(locationString, - location.getPathWithQueryParameters()); - - locationString = "foo/#fragment"; - location = new Location(locationString); - Assert.assertEquals(locationString, - location.getPathWithQueryParameters()); - - locationString = "foo?bar#fragment"; - location = new Location(locationString); - Assert.assertEquals(locationString, - location.getPathWithQueryParameters()); - - locationString = "foo/?bar=baz#fragment"; - location = new Location(locationString); - Assert.assertEquals(locationString, - location.getPathWithQueryParameters()); - - locationString = "foo#"; - location = new Location(locationString); - Assert.assertEquals(locationString, - location.getPathWithQueryParameters()); - - locationString = "foo/?bar=baz#"; - location = new Location(locationString); - Assert.assertEquals(locationString, - location.getPathWithQueryParameters()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/ParameterDeserializerTest.java b/flow-server/src/test/java/com/vaadin/flow/router/ParameterDeserializerTest.java deleted file mode 100644 index f0ed8d68149..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/ParameterDeserializerTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class ParameterDeserializerTest { - - @Test - public void testSimple() { - assertFalse(ParameterDeserializer.isAnnotatedParameter(Simple.class, - OptionalParameter.class)); - assertTrue(ParameterDeserializer.isAnnotatedParameter( - SimpleAnnotated.class, OptionalParameter.class)); - } - - @Test - public void testInterface() { - assertFalse(ParameterDeserializer.isAnnotatedParameter(Normal.class, - OptionalParameter.class)); - assertTrue(ParameterDeserializer.isAnnotatedParameter( - NormalAnnotated.class, OptionalParameter.class)); - } - - @Test - public void parameterizedViaClass() { - assertFalse(ParameterDeserializer.isAnnotatedParameter( - ParameterizedViaSuperClass.class, OptionalParameter.class)); - assertTrue(ParameterDeserializer.isAnnotatedParameter( - ParameterizedAnnotatedViaSuperClass.class, - OptionalParameter.class)); - } - - @Test - public void parameterizedViaInterface() { - assertFalse(ParameterDeserializer.isAnnotatedParameter( - ParameterizedClass.class, OptionalParameter.class)); - assertTrue(ParameterDeserializer.isAnnotatedParameter( - ParameterizedAnnotatedClass.class, OptionalParameter.class)); - } - - @Test - public void testGenericInterface() { - assertFalse(ParameterDeserializer.isAnnotatedParameter(Generic.class, - OptionalParameter.class)); - assertTrue(ParameterDeserializer.isAnnotatedParameter( - GenericAnnotated.class, OptionalParameter.class)); - } - - public static class Simple implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - public static class ParameterizedSuperClass - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - public static class ParameterizedViaSuperClass - extends ParameterizedSuperClass { - - } - - public static class ParameterizedAnnotatedViaSuperClass - extends ParameterizedSuperClass { - - @Override - public void setParameter(BeforeEvent event, - @OptionalParameter String parameter) { - } - } - - public static class ParameterizedClass - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - public static class ParameterizedAnnotatedClass - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, - @OptionalParameter String parameter) { - } - } - - public static class SimpleAnnotated implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, - @OptionalParameter String parameter) { - } - } - - public interface NormalInterface extends HasUrlParameter { - @Override - default void setParameter(BeforeEvent event, String parameter) { - } - } - - public static class Normal implements NormalInterface { - } - - public interface NormalInterfaceAnnotated extends HasUrlParameter { - @Override - default void setParameter(BeforeEvent event, - @OptionalParameter String parameter) { - } - } - - public static class NormalAnnotated implements NormalInterfaceAnnotated { - } - - public interface GenericInterface extends HasUrlParameter { - @Override - default void setParameter(BeforeEvent event, T parameter) { - } - } - - public static class Generic implements GenericInterface { - } - - public interface GenericInterfaceAnnotated extends HasUrlParameter { - @Override - default void setParameter(BeforeEvent event, - @OptionalParameter T parameter) { - } - } - - public static class GenericAnnotated - implements GenericInterfaceAnnotated { - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/QueryParametersTest.java b/flow-server/src/test/java/com/vaadin/flow/router/QueryParametersTest.java deleted file mode 100644 index 5cd60df42a9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/QueryParametersTest.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.router; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -public class QueryParametersTest { - - private final String simpleInputQueryString = "one=1&two=2&three=3&four&five=4%2F5%266%2B7&six=one+%2B+one%20%3D%20two"; - - private final String complexInputQueryString = "one=1&one=11&two=2&two=22&three=3&four&five=4%2F5%266%2B7&six=one+%2B+one%20%3D%20two"; - - private Map getSimpleInputParameters() { - Map inputParameters = new HashMap<>(); - inputParameters.put("one", "1"); - inputParameters.put("two", "2"); - inputParameters.put("three", "3"); - return inputParameters; - } - - private Map getFullInputParameters() { - Map inputParameters = new HashMap<>(); - inputParameters.put("one", new String[] { "1", "11" }); - inputParameters.put("two", new String[] { "2", "22" }); - inputParameters.put("three", new String[] { "3" }); - return inputParameters; - } - - private void checkListsForImmutability(Collection> lists) { - for (List list : lists) { - try { - list.add("whatever"); - fail("No list should have been mutable"); - } catch (UnsupportedOperationException expected) { - // exception expected - } - } - } - - @Test - public void emptyParameters() { - QueryParameters emptyParams = QueryParameters.empty(); - - assertEquals(Collections.emptyMap(), emptyParams.getParameters()); - } - - @Test - public void emptyParametersToQueryString() { - QueryParameters emptyParams = QueryParameters.empty(); - - assertEquals("", emptyParams.getQueryString()); - } - - @Test(expected = UnsupportedOperationException.class) - public void underlyingMapUnmodifiable_empty() { - QueryParameters.empty().getParameters().put("one", - Collections.emptyList()); - } - - @Test - public void simpleParameters() { - QueryParameters simpleParams = QueryParameters - .simple(getSimpleInputParameters()); - - Map> expectedFullParams = new HashMap<>(); - expectedFullParams.put("one", Collections.singletonList("1")); - expectedFullParams.put("two", Collections.singletonList("2")); - expectedFullParams.put("three", Collections.singletonList("3")); - assertEquals(expectedFullParams, simpleParams.getParameters()); - } - - @Test - public void simpleParametersFromQueryString() { - QueryParameters simpleParams = QueryParameters - .fromString(simpleInputQueryString); - - Map> expectedFullParams = new HashMap<>(); - expectedFullParams.put("one", Collections.singletonList("1")); - expectedFullParams.put("two", Collections.singletonList("2")); - expectedFullParams.put("three", Collections.singletonList("3")); - expectedFullParams.put("four", Collections.singletonList("")); - expectedFullParams.put("five", Collections.singletonList("4/5&6+7")); - expectedFullParams.put("six", - Collections.singletonList("one + one = two")); - assertEquals(expectedFullParams, simpleParams.getParameters()); - } - - @Test - public void simpleParametersToQueryString() { - QueryParameters simpleParams = QueryParameters - .simple(getSimpleInputParameters()); - - String queryString = simpleParams.getQueryString(); - assertTrue(queryString.contains("one=1")); - assertTrue(queryString.contains("two=2")); - assertTrue(queryString.contains("three=3")); - assertTrue(queryString.contains("&")); - assertNumberOfOccurences(queryString, 2, "&"); - } - - @Test(expected = UnsupportedOperationException.class) - public void underlyingMapUnmodifiable_simple() { - QueryParameters params = QueryParameters - .simple(getSimpleInputParameters()); - params.getParameters().put("one", Collections.emptyList()); - } - - @Test - public void underlyingListsUnmodifiable_simple() { - checkListsForImmutability(QueryParameters - .simple(getSimpleInputParameters()).getParameters().values()); - } - - @Test - public void complexParameters() { - QueryParameters fullParams = QueryParameters - .full(getFullInputParameters()); - - Map> expectedFullParams = new HashMap<>(); - expectedFullParams.put("one", Arrays.asList("1", "11")); - expectedFullParams.put("two", Arrays.asList("2", "22")); - expectedFullParams.put("three", Collections.singletonList("3")); - assertEquals(expectedFullParams, fullParams.getParameters()); - } - - @Test - public void complexParametersFromQueryString() { - QueryParameters fullParams = QueryParameters - .fromString(complexInputQueryString); - - Map> expectedFullParams = new HashMap<>(); - expectedFullParams.put("one", Arrays.asList("1", "11")); - expectedFullParams.put("two", Arrays.asList("2", "22")); - expectedFullParams.put("three", Collections.singletonList("3")); - expectedFullParams.put("four", Collections.singletonList("")); - expectedFullParams.put("five", Collections.singletonList("4/5&6+7")); - expectedFullParams.put("six", - Collections.singletonList("one + one = two")); - assertEquals(expectedFullParams, fullParams.getParameters()); - } - - @Test - public void complexParametersToQueryString() { - QueryParameters fullParams = QueryParameters - .full(getFullInputParameters()); - - String queryString = fullParams.getQueryString(); - assertTrue(queryString.contains("one=1")); - assertTrue(queryString.contains("one=11")); - assertTrue(queryString.contains("two=2")); - assertTrue(queryString.contains("two=22")); - assertTrue(queryString.contains("three=3")); - assertNumberOfOccurences(queryString, 4, "&"); - } - - private void assertNumberOfOccurences(String stringToCheck, - int expectedNumber, String element) { - assertEquals(1, element.length()); - int actualNumbetOfOccurences = stringToCheck.length() - - stringToCheck.replace(element, "").length(); - assertEquals(expectedNumber, actualNumbetOfOccurences); - } - - @Test(expected = UnsupportedOperationException.class) - public void underlyingMapUnmodifiable_full() { - QueryParameters.full(getFullInputParameters()).getParameters() - .put("one", Collections.emptyList()); - } - - @Test - public void underlyingListsUnmodifiable_full() { - checkListsForImmutability(QueryParameters.full(getFullInputParameters()) - .getParameters().values()); - } - - @Test - public void parameterWithoutValue() { - QueryParameters params = new QueryParameters( - Collections.singletonMap("foo", Collections.singletonList(""))); - Assert.assertEquals("foo", params.getQueryString()); - - params = new QueryParameters( - Collections.singletonMap("foo", Arrays.asList("", "bar"))); - Assert.assertEquals("foo&foo=bar", params.getQueryString()); - - params = new QueryParameters( - Collections.singletonMap("foo", Arrays.asList("bar", ""))); - Assert.assertEquals("foo=bar&foo", params.getQueryString()); - } - - @Test - public void parameterWithEmptyValue() { - QueryParameters fullParams = new QueryParameters( - Collections.singletonMap("foo", Collections.singletonList(""))); - Assert.assertEquals("foo", fullParams.getQueryString()); - } - - @Test - public void toStringValidation() { - String toString = QueryParameters.of("foo", "bar").toString(); - Assert.assertEquals("QueryParameters(foo=bar)", toString); - } - - @Test - public void equalsAndHashCode() { - QueryParameters qp1 = QueryParameters.of("foo", "bar"); - QueryParameters qp2 = QueryParameters.fromString("foo=bar"); - QueryParameters qp3 = QueryParameters.fromString("bar=foo"); - Assert.assertEquals(qp1, qp2); - Assert.assertNotEquals(qp3, qp2); - Assert.assertEquals(qp1.hashCode(), qp2.hashCode()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouteConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouteConfigurationTest.java deleted file mode 100644 index f14a490c6fd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouteConfigurationTest.java +++ /dev/null @@ -1,616 +0,0 @@ -package com.vaadin.flow.router; - -import jakarta.servlet.ServletContext; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.CountDownLatch; - -import com.vaadin.flow.router.internal.HasUrlParameterFormat; -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.Command; -import com.vaadin.flow.server.MockServletContext; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.RouteRegistry; -import com.vaadin.flow.server.SessionRouteRegistry; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServlet; -import com.vaadin.flow.server.VaadinServletContext; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; - -@NotThreadSafe -public class RouteConfigurationTest { - - private ApplicationRouteRegistry registry; - private MockService vaadinService; - private VaadinSession session; - private ServletContext servletContext; - private VaadinServletContext vaadinContext; - - @Before - public void init() { - servletContext = new MockServletContext(); - vaadinContext = new MockVaadinContext(servletContext); - registry = ApplicationRouteRegistry.getInstance(vaadinContext); - - vaadinService = Mockito.mock(MockService.class); - Mockito.when(vaadinService.getRouteRegistry()).thenReturn(registry); - Mockito.when(vaadinService.getContext()).thenReturn(vaadinContext); - - VaadinService.setCurrent(vaadinService); - - session = new MockVaadinSession(vaadinService) { - @Override - public VaadinService getService() { - return vaadinService; - } - }; - } - - /** - * Get registry by handing the session lock correctly. - * - * @param session - * target vaadin session - * @return session route registry for session if exists or new. - */ - private SessionRouteRegistry getRegistry(VaadinSession session) { - try { - session.lock(); - return (SessionRouteRegistry) SessionRouteRegistry - .getSessionRegistry(session); - } finally { - session.unlock(); - } - } - - @Test - public void routeConfigurationUpdateLock_configurationIsUpdatedOnlyAfterUnlock() { - CountDownLatch waitReaderThread = new CountDownLatch(1); - CountDownLatch waitUpdaterThread = new CountDownLatch(2); - - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(getRegistry(session)); - - Thread readerThread = new Thread() { - @Override - public void run() { - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - routeConfiguration.getAvailableRoutes().isEmpty()); - - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - routeConfiguration.getAvailableRoutes().isEmpty()); - - waitReaderThread.countDown(); - } - }; - - readerThread.start(); - - routeConfiguration.update(() -> { - routeConfiguration.setRoute("", MyRoute.class, - Collections.emptyList()); - - waitUpdaterThread.countDown(); - - routeConfiguration.setRoute("path", Secondary.class, - Collections.emptyList()); - - waitUpdaterThread.countDown(); - try { - waitReaderThread.await(); - } catch (InterruptedException e) { - Assert.fail(); - } - }); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 2, routeConfiguration.getAvailableRoutes().size()); - } - - @Test - public void isRouteRegistered_returnsCorrectly() { - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(getRegistry(session)); - - routeConfiguration.update(() -> { - routeConfiguration.setRoute("", MyRoute.class, - Collections.emptyList()); - routeConfiguration.setRoute("path", Secondary.class, - Collections.emptyList()); - }); - - Assert.assertTrue("Registered 'MyRoute.class' should return true", - routeConfiguration.isRouteRegistered(MyRoute.class)); - Assert.assertTrue("Registered 'Secondary.class' should return true", - routeConfiguration.isRouteRegistered(Secondary.class)); - Assert.assertFalse("Unregistered 'Url.class' should return false", - routeConfiguration.isRouteRegistered(Url.class)); - } - - @Test - public void routeConfiguration_getMethodsReturnCorrectly() { - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(getRegistry(session)); - - routeConfiguration.update(() -> { - routeConfiguration.setRoute("", MyRoute.class); - routeConfiguration.setRoute("path", Secondary.class); - routeConfiguration.setRoute("parents", MiddleLayout.class, - MainLayout.class); - routeConfiguration.setAnnotatedRoute(ParameterView.class); - }); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 4, routeConfiguration.getAvailableRoutes().size()); - Assert.assertTrue("Expected path '' to be registered", - routeConfiguration.isPathAvailable("")); - Assert.assertTrue("Expected path 'path' to be registered", - routeConfiguration.isPathAvailable("path")); - Assert.assertTrue("Expected path 'parents' to be registered", - routeConfiguration.isPathAvailable("parents")); - - Assert.assertEquals("Url should have only been 'parents'", "parents", - routeConfiguration.getUrl(MiddleLayout.class)); - - Optional template; - - template = routeConfiguration.getTemplate(MiddleLayout.class); - Assert.assertTrue("Missing template", template.isPresent()); - Assert.assertEquals("Url should have only been 'parents'", "parents", - template.get()); - - Optional> pathRoute = routeConfiguration - .getRoute("path"); - Assert.assertTrue("'path' should have returned target class", - pathRoute.isPresent()); - Assert.assertEquals("'path' registration should be Secondary", - Secondary.class, pathRoute.get()); - - template = routeConfiguration.getTemplate(ParameterView.class); - Assert.assertTrue("Missing template for ParameterView", - template.isPresent()); - Assert.assertEquals( - "ParameterView template is not correctly generated from Route and RoutePrefix", - "category/:int(" + RouteParameterRegex.INTEGER + ")/item/:long(" - + RouteParameterRegex.LONG + ")", - template.get()); - - Assert.assertTrue("ParameterView template not registered.", - routeConfiguration.isPathAvailable("category/:int(" - + RouteParameterRegex.INTEGER + ")/item/:long(" - + RouteParameterRegex.LONG + ")")); - - Assert.assertEquals( - "ParameterView url with RouteParameters not generated correctly.", - "category/1234567890/item/12345678900", - routeConfiguration.getUrl(ParameterView.class, - new RouteParameters(new RouteParam("int", "1234567890"), - new RouteParam("long", "12345678900")))); - - routeConfiguration.update(() -> { - routeConfiguration.removeRoute("path"); - routeConfiguration.setRoute("url", Url.class); - }); - - Assert.assertFalse( - "Removing the path 'path' should have cleared it from the registry", - routeConfiguration.isPathAvailable("path")); - - Assert.assertTrue("Expected path 'url' to be registered", - routeConfiguration.isPathAvailable( - HasUrlParameterFormat.getTemplate("url", Url.class))); - - Optional> urlRoute = routeConfiguration - .getRoute("url"); - - Assert.assertFalse( - "'url' with no parameters should not have returned a class", - urlRoute.isPresent()); - - urlRoute = routeConfiguration.getRoute("url", - Collections.singletonList("param")); - Assert.assertTrue("'url' with parameters should have returned a class", - urlRoute.isPresent()); - Assert.assertEquals("'url' registration should be Url", Url.class, - urlRoute.get()); - } - - @Test - public void routeConfiguration_routeTemplatesWorkCorrectly() { - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(getRegistry(session)); - - routeConfiguration.update(() -> { - routeConfiguration.setAnnotatedRoute(ComponentView.class); - }); - - // Main template for target. - final Optional template = routeConfiguration - .getTemplate(ComponentView.class); - Assert.assertTrue("Missing template", template.isPresent()); - Assert.assertEquals("component/:identifier/:path*", template.get()); - - // url produced by @RouteAlias(value = ":tab(api)/:path*") - Assert.assertEquals("component/button/api/com/vaadin/flow/button", - routeConfiguration.getUrl(ComponentView.class, - new RouteParameters( - new RouteParam("identifier", "button"), - new RouteParam("tab", "api"), new RouteParam( - "path", "com/vaadin/flow/button")))); - - // url produced by @Route(value = ":path*") - Assert.assertEquals("component/button/com/vaadin/flow/button", - routeConfiguration.getUrl(ComponentView.class, - new RouteParameters( - new RouteParam("identifier", "button"), - new RouteParam("path", - "com/vaadin/flow/button")))); - - // url produced by @RouteAlias(value = - // ":tab(overview|samples|links|reviews|discussions)") - Assert.assertEquals("component/button/reviews", - routeConfiguration.getUrl(ComponentView.class, - new RouteParameters( - new RouteParam("identifier", "button"), - new RouteParam("tab", "reviews")))); - - // url produced by @RouteAlias(value = - // ":tab(overview|samples|links|reviews|discussions)") - Assert.assertEquals("component/button/overview", - routeConfiguration.getUrl(ComponentView.class, - new RouteParameters( - new RouteParam("identifier", "button"), - new RouteParam("tab", "overview")))); - - try { - // Asking the url of target with invalid parameter values. - routeConfiguration.getUrl(ComponentView.class, - new RouteParameters(new RouteParam("identifier", "button"), - new RouteParam("tab", "examples"))); - Assert.fail("`tab` parameter doesn't accept `examples` as value."); - } catch (NotFoundException e) { - } - } - - @Test - public void addListenerToApplicationScoped_noEventForSessionChange() { - VaadinServlet servlet = Mockito.mock(VaadinServlet.class); - Mockito.when(servlet.getServletContext()).thenReturn(servletContext); - Mockito.when(vaadinService.getServlet()).thenReturn(servlet); - - try { - CurrentInstance.set(VaadinService.class, vaadinService); - VaadinSession.setCurrent(session); - session.lock(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forApplicationScope(); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - routeConfiguration.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - routeConfiguration.setRoute("old", MyRoute.class); - - Assert.assertEquals(1, added.size()); - Assert.assertEquals(0, removed.size()); - - added.clear(); - removed.clear(); - - routeConfiguration = RouteConfiguration.forSessionScope(); - - routeConfiguration.setRoute("new", MyRoute.class); - - Assert.assertEquals(0, added.size()); - Assert.assertEquals(0, removed.size()); - } finally { - session.unlock(); - CurrentInstance.clearAll(); - } - } - - @Test - public void addListenerToSessionScoped_alsoEventsForApplicationScope() { - VaadinServlet servlet = Mockito.mock(VaadinServlet.class); - Mockito.when(servlet.getServletContext()).thenReturn(servletContext); - Mockito.when(vaadinService.getServlet()).thenReturn(servlet); - - try { - CurrentInstance.set(VaadinService.class, vaadinService); - VaadinSession.setCurrent(session); - session.lock(); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - RouteConfiguration routeConfiguration = RouteConfiguration - .forSessionScope(); - - routeConfiguration.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - routeConfiguration.setRoute("old", MyRoute.class); - - Assert.assertEquals(1, added.size()); - Assert.assertEquals(0, removed.size()); - - added.clear(); - removed.clear(); - - routeConfiguration = RouteConfiguration.forApplicationScope(); - - routeConfiguration.setRoute("new", MyRoute.class); - - Assert.assertEquals(1, added.size()); - Assert.assertEquals(0, removed.size()); - } finally { - session.unlock(); - CurrentInstance.clearAll(); - } - } - - @Test - public void configurationForSessionRegistry_buildsWithCorrectRegistry() { - SessionRouteRegistry registry = getRegistry(session); - registry.update(() -> { - registry.setRoute("", MyRoute.class, Collections.emptyList()); - registry.setRoute("path", Secondary.class, Collections.emptyList()); - }); - - try { - VaadinSession.setCurrent(session); - session.lock(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forSessionScope(); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 2, routeConfiguration.getAvailableRoutes().size()); - } finally { - session.unlock(); - CurrentInstance.clearAll(); - } - } - - @Test - public void configurationForApplicationScope_buildsWithCorrectRegistry() { - registry.update(() -> { - registry.setRoute("", MyRoute.class, Collections.emptyList()); - registry.setRoute("path", Secondary.class, Collections.emptyList()); - }); - - VaadinServlet servlet = Mockito.mock(VaadinServlet.class); - Mockito.when(servlet.getServletContext()).thenReturn(servletContext); - Mockito.when(vaadinService.getServlet()).thenReturn(servlet); - - try { - CurrentInstance.set(VaadinService.class, vaadinService); - session.lock(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forApplicationScope(); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 2, routeConfiguration.getAvailableRoutes().size()); - } finally { - session.unlock(); - CurrentInstance.clearAll(); - } - } - - @Test - public void setRoutes_allExpectedRoutesAreSet() { - RouteRegistry registry = mockRegistry(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(registry); - - Mockito.doAnswer(invocation -> { - Object[] args = invocation.getArguments(); - ((Command) args[0]).execute(); - return null; - }).when(registry).update(Mockito.any(Command.class)); - - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - Arrays.asList(MyRoute.class, MyInfo.class, MyPalace.class, - MyModular.class) - .forEach(routeConfiguration::setAnnotatedRoute); - }); - - Mockito.verify(registry).update(Mockito.any()); - - Mockito.verify(registry).setRoute("home", MyRoute.class, - Collections.emptyList()); - - Mockito.verify(registry).setRoute("info", MyInfo.class, - Collections.emptyList()); - - Mockito.verify(registry).setRoute("palace", MyPalace.class, - Collections.emptyList()); - - Mockito.verify(registry).setRoute("modular", MyModular.class, - Collections.emptyList()); - } - - @Test - public void registeredRouteWithAlias_allPathsAreRegistered() { - RouteRegistry registry = mockRegistry(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(registry); - - routeConfiguration.setAnnotatedRoute(MyRouteWithAliases.class); - - Mockito.verify(registry).setRoute("withAliases", - MyRouteWithAliases.class, Collections.emptyList()); - Mockito.verify(registry).setRoute("version", MyRouteWithAliases.class, - Collections.emptyList()); - Mockito.verify(registry).setRoute("person", MyRouteWithAliases.class, - Collections.emptyList()); - - } - - @Test - public void routeWithParent_parentsAreCollectedCorrectly() { - RouteRegistry registry = mockRegistry(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(registry); - - routeConfiguration.setAnnotatedRoute(SingleLayout.class); - - Mockito.verify(registry).setRoute("single", SingleLayout.class, - Collections.singletonList(MainLayout.class)); - - routeConfiguration.setAnnotatedRoute(DoubleLayout.class); - - Mockito.verify(registry).setRoute("double", DoubleLayout.class, - Arrays.asList(MiddleLayout.class, MainLayout.class)); - } - - @Test - public void parentLayoutAnnotatedClass_parentsCorrecltCollected() { - RouteRegistry registry = Mockito.mock(RouteRegistry.class); - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(registry); - - routeConfiguration.setParentAnnotatedRoute("middle", - MiddleLayout.class); - - Mockito.verify(registry).setRoute("middle", MiddleLayout.class, - Collections.singletonList(MainLayout.class)); - } - - private void awaitCountDown(CountDownLatch countDownLatch) { - try { - countDownLatch.await(); - } catch (InterruptedException e) { - Assert.fail(); - } - } - - private RouteRegistry mockRegistry() { - RouteRegistry registry = Mockito.mock(RouteRegistry.class); - VaadinContext context = new MockVaadinContext(); - Mockito.when(registry.getContext()).thenReturn(context); - return registry; - } - - @Tag("div") - @Route("home") - private static class MyRoute extends Component { - } - - @Tag("div") - @Route("info") - private static class MyInfo extends Component { - } - - @Tag("div") - @Route("palace") - private static class MyPalace extends Component { - } - - @Tag("div") - @Route("modular") - private static class MyModular extends Component { - } - - @Tag("div") - @Route("withAliases") - @RouteAlias("version") - @RouteAlias("person") - private static class MyRouteWithAliases extends Component { - } - - @Tag("div") - @Route(value = "single", layout = MainLayout.class) - private static class SingleLayout extends Component { - } - - @Tag("div") - @Route(value = "double", layout = MiddleLayout.class) - private static class DoubleLayout extends Component { - } - - @Tag("div") - private static class MainLayout extends Component implements RouterLayout { - } - - @Tag("div") - @ParentLayout(MainLayout.class) - private static class MiddleLayout extends Component - implements RouterLayout { - } - - @Tag("div") - private static class Secondary extends Component { - } - - @Tag("div") - private static class Url extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @RoutePrefix("category/:int(" + RouteParameterRegex.INTEGER + ")") - @Tag("div") - private static class MainView extends Component implements RouterLayout { - } - - @Route(value = "item/:long(" + RouteParameterRegex.LONG - + ")", layout = MainView.class) - @Tag("div") - private static class ParameterView extends Component { - } - - @Route(value = ":path*") - @RouteAlias(value = ":tab(api)/:path*") - @RouteAlias(value = ":tab(overview|samples|links|reviews|discussions)") - @RoutePrefix("component/:identifier") - @Tag("div") - public static class ComponentView extends Component { - } - - /** - * Extending class to let us mock the getRouteRegistry method for testing. - */ - private static class MockService extends VaadinServletService { - - @Override - public RouteRegistry getRouteRegistry() { - return super.getRouteRegistry(); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouteNotFoundErrorTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouteNotFoundErrorTest.java deleted file mode 100644 index 68ea447f6b0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouteNotFoundErrorTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.Collections; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.RouteRegistry; -import com.vaadin.flow.server.VaadinSession; - -public class RouteNotFoundErrorTest { - - @Tag(Tag.A) - private static class RouteTarget extends Component { - - } - - @Test - public void setErrorParameter_productionMode_pathContainRoutesTemplate_renderedElementHasNoRoutes() { - - RouteNotFoundError page = new RouteNotFoundError(); - - BeforeEnterEvent event = Mockito.mock(BeforeEnterEvent.class); - Location location = Mockito.mock(Location.class); - Mockito.when(location.getPath()).thenReturn("{{routes}}"); - Mockito.when(event.getLocation()).thenReturn(location); - - UI ui = Mockito.mock(UI.class); - VaadinSession session = Mockito.mock(VaadinSession.class); - Mockito.when(ui.getSession()).thenReturn(session); - DeploymentConfiguration config = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(session.getConfiguration()).thenReturn(config); - Mockito.when(config.isProductionMode()).thenReturn(true); - - Mockito.when(event.getUI()).thenReturn(ui); - - ErrorParameter param = new ErrorParameter( - NotFoundException.class, new NotFoundException()); - - Router router = Mockito.mock(Router.class); - Mockito.when(event.getSource()).thenReturn(router); - RouteRegistry registry = Mockito.mock(RouteRegistry.class); - Mockito.when(router.getRegistry()).thenReturn(registry); - RouteData data = new RouteData(Collections.emptyList(), "bar", - Collections.emptyList(), RouteTarget.class, - Collections.emptyList()); - Mockito.when(registry.getRegisteredRoutes()) - .thenReturn(Collections.singletonList(data)); - - event.getSource().getRegistry().getRegisteredRoutes(); - - page.setErrorParameter(event, param); - - MatcherAssert.assertThat(page.getElement().toString(), - CoreMatchers.not(CoreMatchers.containsString("bar"))); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouteParametersTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouteParametersTest.java deleted file mode 100644 index dbe953df9ce..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouteParametersTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.Arrays; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class RouteParametersTest { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Test - public void getters_provide_correct_values() { - RouteParameters parameters = getParameters(); - - // String getter - Assert.assertEquals("Wrong value", "foo", - parameters.get("string").get()); - Assert.assertEquals("Wrong value", "123", - parameters.get("integer").get()); - Assert.assertEquals("Wrong value", "12345678900", - parameters.get("long").get()); - Assert.assertEquals("Wrong value", "path/to/foo/bar", - parameters.get("varargs").get()); - - // Integer getter - Assert.assertEquals("Wrong value", Integer.valueOf(123), - parameters.getInteger("integer").get()); - - // Long getter - Assert.assertEquals("Wrong value", Long.valueOf(123), - parameters.getLong("integer").get()); - Assert.assertEquals("Wrong value", Long.valueOf(12345678900L), - parameters.getLong("long").get()); - - // Wildcard getter - Assert.assertEquals("Wrong value", Arrays.asList("foo"), - parameters.getWildcard("string")); - Assert.assertEquals("Wrong value", Arrays.asList("123"), - parameters.getWildcard("integer")); - Assert.assertEquals("Wrong value", Arrays.asList("12345678900"), - parameters.getWildcard("long")); - Assert.assertEquals("Wrong value", - Arrays.asList("path", "to", "foo", "bar"), - parameters.getWildcard("varargs")); - } - - @Test - public void getters_provide_empty_values() { - RouteParameters parameters = getParameters(); - - Assert.assertFalse( - "Getting the String value of a non-existing parameter should return empty Optional", - parameters.get("foo").isPresent()); - Assert.assertFalse( - "Getting the Integer value of a non-existing parameter should return empty Optional", - parameters.getInteger("foo").isPresent()); - Assert.assertFalse( - "Getting the Long value of a non-existing parameter should return empty Optional", - parameters.getLong("foo").isPresent()); - - Assert.assertTrue( - "Getting the Wildcard value of a non-existing parameter should return empty List", - parameters.getWildcard("foo").isEmpty()); - } - - @Test - public void integer_getter_stringParameter_throws() { - RouteParameters parameters = getParameters(); - - exception.expect(IllegalArgumentException.class); - exception.expectMessage( - "Couldn't parse 'string' parameter value 'foo' as integer"); - - parameters.getInteger("string"); - } - - @Test - public void integer_getter_longParameter_throws() { - RouteParameters parameters = getParameters(); - - exception.expect(IllegalArgumentException.class); - exception.expectMessage( - "Couldn't parse 'long' parameter value '12345678900' as integer"); - - parameters.getInteger("long"); - } - - @Test - public void integer_getter_varaargsParameter_throws() { - RouteParameters parameters = getParameters(); - - exception.expect(IllegalArgumentException.class); - exception.expectMessage( - "Couldn't parse 'varargs' parameter value 'path/to/foo/bar' as integer"); - - parameters.getInteger("varargs"); - } - - @Test - public void long_getter_varaargsParameter_throws() { - RouteParameters parameters = getParameters(); - - exception.expect(IllegalArgumentException.class); - exception.expectMessage( - "Couldn't parse 'varargs' parameter value 'path/to/foo/bar' as long"); - - parameters.getLong("varargs"); - } - - @Test - public void long_getter_stringParameter_throws() { - RouteParameters parameters = getParameters(); - - exception.expect(IllegalArgumentException.class); - exception.expectMessage( - "Couldn't parse 'string' parameter value 'foo' as long"); - - parameters.getLong("string"); - } - - @Test - public void varargs_initializer_throws_exception() { - try { - new RouteParameters(new RouteParam("int", "123"), - new RouteParam("int", "123")); - - Assert.fail( - "RouteParameters initializer should have failed with same parameter defined more than once."); - } catch (IllegalArgumentException e) { - } - } - - private RouteParameters getParameters() { - return new RouteParameters(new RouteParam("string", "foo"), - new RouteParam("integer", "123"), - new RouteParam("long", "12345678900"), - new RouteParam("varargs", "path/to/foo/bar")); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouterConfigurationUrlResolvingTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouterConfigurationUrlResolvingTest.java deleted file mode 100644 index 092329b3aef..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouterConfigurationUrlResolvingTest.java +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.router; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EventObject; -import java.util.List; - -import com.vaadin.flow.router.internal.HasUrlParameterFormat; -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.VaadinService; - -@NotThreadSafe -public class RouterConfigurationUrlResolvingTest extends RoutingTestBase { - private RouteConfiguration routeConfiguration; - private UI ui; - private VaadinService service = Mockito.mock(VaadinService.class); - private DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - - @Before - public void init() throws NoSuchFieldException, IllegalAccessException { - super.init(); - ui = new RouterTestMockUI(router); - ui.getSession().lock(); - ui.getSession().setConfiguration(configuration); - - VaadinService.setCurrent(service); - - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - Mockito.when(service.getRouter()).thenReturn(router); - - Mockito.when(configuration.isProductionMode()).thenReturn(true); - routeConfiguration = RouteConfiguration - .forRegistry(router.getRegistry()); - } - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - private void setNavigationTargets( - Class... navigationTargets) - throws InvalidRouteConfigurationException { - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - Arrays.asList(navigationTargets) - .forEach(routeConfiguration::setAnnotatedRoute); - }); - } - - @Test - public void basic_url_resolving() - throws InvalidRouteConfigurationException { - setNavigationTargets(RootNavigationTarget.class, - FooNavigationTarget.class, FooBarNavigationTarget.class); - - Assert.assertEquals("", - routeConfiguration.getUrl(RootNavigationTarget.class)); - Assert.assertEquals("foo", - routeConfiguration.getUrl(FooNavigationTarget.class)); - Assert.assertEquals("foo/bar", - routeConfiguration.getUrl(FooBarNavigationTarget.class)); - } - - @Test - public void nested_layouts_url_resolving() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteChild.class, LoneRoute.class); - - Assert.assertEquals("parent/child", - routeConfiguration.getUrl(RouteChild.class)); - Assert.assertEquals("single", - routeConfiguration.getUrl(LoneRoute.class)); - } - - @Test - public void layout_with_url_parameter_url_resolving() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - OtherGreetingNavigationTarget.class); - - Assert.assertEquals("greeting/my_param", routeConfiguration - .getUrl(GreetingNavigationTarget.class, "my_param")); - Assert.assertEquals("greeting/true", routeConfiguration - .getUrl(GreetingNavigationTarget.class, "true")); - - Assert.assertEquals("greeting/other", routeConfiguration - .getUrl(GreetingNavigationTarget.class, "other")); - } - - @Test - public void url_resolves_correctly_for_optional_and_wild_parameters() - throws InvalidRouteConfigurationException, NotFoundException { - setNavigationTargets(OptionalParameter.class, WildParameter.class); - - Assert.assertEquals( - "Optional value should be able to return even without any parameters", - "optional", routeConfiguration.getUrl(OptionalParameter.class)); - - Assert.assertEquals( - "Wildcard value should be able to return even without any parameters", - "wild", routeConfiguration.getUrl(WildParameter.class)); - - Assert.assertEquals("optional/my_param", - routeConfiguration.getUrl(OptionalParameter.class, "my_param")); - - Assert.assertEquals("wild/true", - routeConfiguration.getUrl(WildParameter.class, "true")); - - Assert.assertEquals("wild/there/are/many/of/us", routeConfiguration - .getUrl(WildParameter.class, "there/are/many/of/us")); - } - - @Test - public void wildcardPathWithEmptyParameter_emptyParameterIsAvailable() { - WildParameter.events.clear(); - WildParameter.param = null; - setNavigationTargets(WildParameter.class); - - router.navigate(ui, new Location("wild//two/three"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("/two/three", WildParameter.param); - - router.navigate(ui, new Location("wild////four/five"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("///four/five", WildParameter.param); - - router.navigate(ui, new Location("wild//two//four"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("/two//four", WildParameter.param); - } - - @Test - public void root_navigation_target_with_wildcard_parameter() - throws InvalidRouteConfigurationException { - WildRootParameter.events.clear(); - WildRootParameter.param = null; - setNavigationTargets(WildRootParameter.class); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - WildRootParameter.events.size()); - Assert.assertEquals("Parameter should be empty", "", - WildRootParameter.param); - - router.navigate(ui, new Location("my/wild"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - WildRootParameter.events.size()); - Assert.assertEquals("Parameter should be empty", "my/wild", - WildRootParameter.param); - - Assert.assertEquals("", - routeConfiguration.getUrl(WildRootParameter.class)); - Assert.assertEquals("wild", - routeConfiguration.getUrl(WildRootParameter.class, "wild")); - - List params = Arrays.asList("", null); - Assert.assertEquals("", routeConfiguration - .getUrl(WildRootParameter.class, params.get(1))); - } - - @Test - public void root_navigation_target_with_optional_parameter() - throws InvalidRouteConfigurationException { - OptionalRootParameter.events.clear(); - OptionalRootParameter.param = null; - setNavigationTargets(OptionalRootParameter.class); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - OptionalRootParameter.events.size()); - Assert.assertNull("Parameter should be empty", - OptionalRootParameter.param); - - router.navigate(ui, new Location("optional"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - OptionalRootParameter.events.size()); - Assert.assertEquals("Parameter should be empty", "optional", - OptionalRootParameter.param); - - Assert.assertEquals("", - routeConfiguration.getUrl(OptionalRootParameter.class)); - Assert.assertEquals("optional", routeConfiguration - .getUrl(OptionalRootParameter.class, "optional")); - - List params = Arrays.asList("", null); - Assert.assertEquals("", routeConfiguration - .getUrl(OptionalRootParameter.class, params.get(1))); - } - - @Test - public void getUrl_for_has_url_with_supported_parameters() - throws InvalidRouteConfigurationException { - setNavigationTargets(IntegerParameter.class, LongParameter.class, - BooleanParameter.class); - - Assert.assertEquals("integer/5", - routeConfiguration.getUrl(IntegerParameter.class, 5)); - - Assert.assertEquals("long/5", - routeConfiguration.getUrl(LongParameter.class, 5l)); - - Assert.assertEquals("boolean/false", - routeConfiguration.getUrl(BooleanParameter.class, false)); - } - - @Test // 3519 - public void getUrl_throws_for_required_parameter() { - expectedEx.expect(IllegalArgumentException.class); - expectedEx.expectMessage( - String.format("Navigation target '%s' requires a parameter.", - RouteWithParameter.class.getName())); - setNavigationTargets(RouteWithParameter.class); - - routeConfiguration.getUrl(RouteWithParameter.class); - } - - @Test // 3519 - public void getUrl_returns_url_if_parameter_is_wildcard_or_optional() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteWithMultipleParameters.class, - OptionalParameter.class); - - String url = routeConfiguration - .getUrl(RouteWithMultipleParameters.class); - - Assert.assertEquals("Returned url didn't match Wildcard parameter", - RouteWithMultipleParameters.class.getAnnotation(Route.class) - .value(), - url); - url = routeConfiguration.getUrl(OptionalParameter.class); - - Assert.assertEquals("Returned url didn't match Optional parameter", - OptionalParameter.class.getAnnotation(Route.class).value(), - url); - } - - @Test // 3519 - public void getUrlBase_returns_url_without_parameter_even_for_required_parameters() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteWithParameter.class, - RouteWithMultipleParameters.class, OptionalParameter.class, - FooNavigationTarget.class); - - Assert.assertEquals("Required parameter didn't match url base.", - RouteWithParameter.class.getAnnotation(Route.class).value(), - routeConfiguration.getUrlBase(RouteWithParameter.class) - .orElse(null)); - Assert.assertEquals("Wildcard parameter didn't match url base.", - RouteWithMultipleParameters.class.getAnnotation(Route.class) - .value(), - routeConfiguration.getUrlBase(RouteWithMultipleParameters.class) - .orElse(null)); - Assert.assertEquals("Optional parameter didn't match url base.", - OptionalParameter.class.getAnnotation(Route.class).value(), - routeConfiguration.getUrlBase(OptionalParameter.class) - .orElse(null)); - Assert.assertEquals("Non parameterized url didn't match url base.", - FooNavigationTarget.class.getAnnotation(Route.class).value(), - routeConfiguration.getUrlBase(FooNavigationTarget.class) - .orElse(null)); - } - - @Test // #2740 - public void getTemplate_returns_url_template() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteWithParameter.class, - RouteWithMultipleParameters.class, OptionalParameter.class, - FooNavigationTarget.class); - - Assert.assertEquals("Required parameter didn't match route template.", - "param/" + HasUrlParameterFormat.PARAMETER, routeConfiguration - .getTemplate(RouteWithParameter.class).orElse(null)); - Assert.assertEquals("Wildcard parameter didn't match route template.", - "param/" + HasUrlParameterFormat.PARAMETER + "*", - routeConfiguration - .getTemplate(RouteWithMultipleParameters.class) - .orElse(null)); - Assert.assertEquals("Optional parameter didn't match route template.", - "optional/" + HasUrlParameterFormat.PARAMETER + "?", - routeConfiguration.getTemplate(OptionalParameter.class) - .orElse(null)); - Assert.assertEquals( - "Non parameterized url didn't match route template.", "foo", - routeConfiguration.getTemplate(FooNavigationTarget.class) - .orElse(null)); - } - - @Test - public void routerLinkInParent_updatesWhenNavigating() - throws InvalidRouteConfigurationException { - setNavigationTargets(LoneRoute.class, RouteChild.class); - - ui.navigate(routeConfiguration.getUrl(LoneRoute.class)); - - RouteParent routeParent = (RouteParent) ui.getInternals() - .getActiveRouterTargetsChain().get(1); - RouterLink loneLink = routeParent.loneLink; - - Assert.assertTrue("Link should be attached", - loneLink.getUI().isPresent()); - Assert.assertTrue( - "Link should be highlighted when navigated to link target", - loneLink.getElement().hasAttribute("highlight")); - - ui.navigate(routeConfiguration.getUrl(RouteChild.class)); - - Assert.assertTrue("Link should be attached", - loneLink.getUI().isPresent()); - Assert.assertFalse( - "Link should not be highlighted when navigated to other target", - loneLink.getElement().hasAttribute("highlight")); - } - - @Test // #2740 - public void navigation_targets_remove_route_with_same_path() - throws InvalidRouteConfigurationException { - setNavigationTargets(MyPage.class, MyPageWithParam.class); - - assertMyPageAndWithParamAvailable(); - - routeConfiguration.update(() -> routeConfiguration.removeRoute("my")); - - final List availableRoutes = routeConfiguration - .getAvailableRoutes(); - Assert.assertEquals(1, availableRoutes.size()); - Assert.assertEquals("my/" + HasUrlParameterFormat.PARAMETER, - availableRoutes.get(0).getTemplate()); - Assert.assertEquals(MyPageWithParam.class, - availableRoutes.get(0).getNavigationTarget()); - } - - @Test // #2740 - public void navigation_targets_remove_route_with_same_path_and_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(MyPage.class, MyPageWithParam.class); - - assertMyPageAndWithParamAvailable(); - - routeConfiguration.update(() -> routeConfiguration - .removeRoute("my/" + HasUrlParameterFormat.PARAMETER)); - - assertMyPageAvailable(); - } - - @Test // #2740 - public void navigation_targets_remove_route_target_with_same_path_and_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(MyPage.class, MyPageWithParam.class); - - assertMyPageAndWithParamAvailable(); - - routeConfiguration.update(() -> routeConfiguration.removeRoute("my", - MyPageWithParam.class)); - - assertMyPageAvailable(); - } - - private void assertMyPageAvailable() { - final List availableRoutes = routeConfiguration - .getAvailableRoutes(); - - Assert.assertEquals(1, availableRoutes.size()); - Assert.assertEquals("my", availableRoutes.get(0).getTemplate()); - Assert.assertEquals(MyPage.class, - availableRoutes.get(0).getNavigationTarget()); - } - - private void assertMyPageAndWithParamAvailable() { - Assert.assertEquals(MyPage.class, - routeConfiguration.getRoute("my").get()); - Assert.assertEquals(MyPageWithParam.class, routeConfiguration - .getRoute("my/" + HasUrlParameterFormat.PARAMETER).get()); - Assert.assertEquals(MyPageWithParam.class, - routeConfiguration - .getRoute("my", - Arrays.asList(HasUrlParameterFormat.PARAMETER)) - .get()); - } - - @Test // #2740 - public void navigation_targets_with_same_route_and_one_with_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(MyPage.class, MyPageWithParam.class); - - assertSameRouteWithParams(); - } - - @Test // #2740 - public void navigation_targets_with_same_route_and_two_with_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(MyPage.class, MyPageWithParam.class, - MyPageWithWildcardParam.class); - - assertSameRouteWithParams(); - - Assert.assertEquals("my/:" + HasUrlParameterFormat.PARAMETER_NAME + "*", - routeConfiguration.getTemplate(MyPageWithWildcardParam.class) - .get()); - - Assert.assertEquals("my/wild/value", routeConfiguration - .getUrl(MyPageWithWildcardParam.class, "wild/value")); - Assert.assertEquals("my/wild/value", - routeConfiguration.getUrl(MyPageWithWildcardParam.class, - new RouteParameters( - HasUrlParameterFormat.PARAMETER_NAME, - "wild/value"))); - - Assert.assertEquals(MyPageWithWildcardParam.class, - routeConfiguration.getRoute("my/wild/param").get()); - } - - private void assertSameRouteWithParams() { - Assert.assertEquals("my", - routeConfiguration.getTemplate(MyPage.class).get()); - Assert.assertEquals("my/:" + HasUrlParameterFormat.PARAMETER_NAME, - routeConfiguration.getTemplate(MyPageWithParam.class).get()); - - Assert.assertEquals("my", routeConfiguration.getUrl(MyPage.class)); - Assert.assertEquals("my/value", - routeConfiguration.getUrl(MyPageWithParam.class, "value")); - Assert.assertEquals("my/value", - routeConfiguration.getUrl(MyPageWithParam.class, - new RouteParameters( - HasUrlParameterFormat.PARAMETER_NAME, - "value"))); - - Assert.assertEquals(MyPage.class, - routeConfiguration.getRoute("my").get()); - Assert.assertEquals(MyPageWithParam.class, - routeConfiguration.getRoute("my/param").get()); - } - - @RoutePrefix("parent") - @Tag(Tag.DIV) - public static class RouteParent extends Component implements RouterLayout { - private final RouterLink loneLink = new RouterLink("lone", - LoneRoute.class); - - public RouteParent() { - getElement().appendChild(loneLink.getElement()); - } - } - - @Route(value = "single", layout = RouteParent.class, absolute = true) - @Tag(Tag.DIV) - public static class LoneRoute extends Component - implements BeforeEnterObserver { - - static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - } - - @Route(value = "child", layout = RouteParent.class) - @Tag(Tag.DIV) - public static class RouteChild extends Component - implements BeforeLeaveObserver, BeforeEnterObserver { - - static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - @Route("wild") - @Tag(Tag.DIV) - public static class WildParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("optional") - @Tag(Tag.DIV) - public static class OptionalParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @com.vaadin.flow.router.OptionalParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("") - @Tag(Tag.DIV) - public static class WildRootParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("") - @Tag(Tag.DIV) - public static class OptionalRootParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @com.vaadin.flow.router.OptionalParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("integer") - @Tag(Tag.DIV) - public static class IntegerParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static Integer param; - - @Override - public void setParameter(BeforeEvent event, Integer parameter) { - events.add(event); - param = parameter; - } - } - - @Route("long") - @Tag(Tag.DIV) - public static class LongParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static Long param; - - @Override - public void setParameter(BeforeEvent event, Long parameter) { - events.add(event); - param = parameter; - } - } - - @Route("boolean") - @Tag(Tag.DIV) - public static class BooleanParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static Boolean param; - - @Override - public void setParameter(BeforeEvent event, Boolean parameter) { - events.add(event); - param = parameter; - } - } - - @Route("param") - @Tag(Tag.DIV) - public static class RouteWithParameter extends Component - implements BeforeEnterObserver, HasUrlParameter { - - private static String param; - - private static List events = new ArrayList<>(); - - @Override - public void setParameter(BeforeEvent event, String parameter) { - events.add(event); - param = parameter; - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - } - - @Route("param") - @Tag(Tag.DIV) - public static class RouteWithMultipleParameters extends Component - implements BeforeEnterObserver, HasUrlParameter { - - private static String param; - - private static List events = new ArrayList<>(); - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - events.add(event); - param = parameter; - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - } - - @Route("my") - @Tag(Tag.DIV) - public class MyPage extends Component { - } - - @Route("my") - @Tag(Tag.DIV) - public class MyPageWithParam extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Route("my") - @Tag(Tag.DIV) - public class MyPageWithWildcardParam extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, - @com.vaadin.flow.router.WildcardParameter String parameter) { - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouterLayoutTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouterLayoutTest.java deleted file mode 100644 index b062d1e2af8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouterLayoutTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.vaadin.flow.router; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.ComponentTest; -import com.vaadin.flow.dom.Element; - -public class RouterLayoutTest { - - private static final String NEW_ID = "newId"; - private TestRouterLayout testRouterLayout; - - @Before - public void setup() { - testRouterLayout = new TestRouterLayout(); - } - - @Test - public void show_nonNull_childrenUpdated() { - Assert.assertEquals(0, testRouterLayout.getElement().getChildCount()); - - ComponentTest.TestDiv content = new ComponentTest.TestDiv(); - testRouterLayout.showRouterLayoutContent(content); - - Assert.assertEquals(1, testRouterLayout.getElement().getChildCount()); - - ComponentTest.TestDiv newContent = new ComponentTest.TestDiv(); - newContent.setId(NEW_ID); - content.getElement().removeFromParent(); - testRouterLayout.showRouterLayoutContent(newContent); - - Assert.assertEquals(1, testRouterLayout.getElement().getChildCount()); - Assert.assertSame(NEW_ID, - testRouterLayout.getElement().getChild(0).getAttribute("id")); - } - - @Test - public void show_null_noChildren() { - testRouterLayout.showRouterLayoutContent(null); - Assert.assertEquals(0, testRouterLayout.getElement().getChildCount()); - } - - @Test - public void remove_removesContent() { - ComponentTest.TestDiv content = new ComponentTest.TestDiv(); - testRouterLayout.element.appendChild(content.getElement()); - - testRouterLayout.removeRouterLayoutContent(content); - - Assert.assertEquals(0, testRouterLayout.getElement().getChildCount()); - } - - private static class TestRouterLayout implements RouterLayout { - private final Element element = new Element("span"); - - @Override - public Element getElement() { - return element; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouterLinkTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouterLinkTest.java deleted file mode 100644 index 5bfe6137b48..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouterLinkTest.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.HasCurrentService; -import com.vaadin.flow.router.internal.HasUrlParameterFormat; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; -import com.vaadin.flow.shared.ApplicationConstants; - -@NotThreadSafe -public class RouterLinkTest extends HasCurrentService { - - private ApplicationRouteRegistry registry; - - private Router router; - - private UI ui; - - @Tag(Tag.DIV) - @Route("bar") - public static class TestView extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - - } - - @Before - public void setUp() throws NoSuchFieldException, IllegalAccessException, - InvalidRouteConfigurationException { - registry = new TestRouteRegistry(); - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(registry); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - Arrays.asList(TestView.class, FooNavigationTarget.class, - ParameterNavigationTarget.class, - GreetingNavigationTarget.class) - .forEach(routeConfiguration::setAnnotatedRoute); - }); - router = new Router(registry); - - ui = new RoutingTestBase.RouterTestUI(router); - VaadinService service = VaadinService.getCurrent(); - Mockito.when(service.getRouter()).thenReturn(router); - } - - @Test - public void createRouterLink_implicitCurrentVaadinServiceRouter() { - // This method sets mock VaadinService instance which returns - // Router from the UI. - RouterLink link = new RouterLink("Show something", TestView.class, - "something"); - Assert.assertEquals("Show something", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/something", - link.getElement().getAttribute("href")); - } - - @Test - public void setRoute_attachedLink() { - UI ui = new UI(); - - RouterLink link = new RouterLink(); - - ui.add(link); - link.setRoute(router, TestView.class, "foo"); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/foo", link.getElement().getAttribute("href")); - } - - @Test - public void setRoute_withoutRouter() { - RouterLink link = new RouterLink(); - - ui.add(link); - link.setRoute(FooNavigationTarget.class); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("foo", link.getElement().getAttribute("href")); - } - - @Test - public void setRoute_withoutRouterWithParameter() { - RouterLink link = new RouterLink(); - - ui.add(link); - link.setRoute(GreetingNavigationTarget.class, "foo"); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("greeting/foo", - link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_explicitRouter() { - RouterLink link = new RouterLink(router, "Show something", - TestView.class, "something"); - Assert.assertEquals("Show something", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/something", - link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_withTargetViewNoText() { - RouterLink link = new RouterLink(FooNavigationTarget.class); - Assert.assertEquals("", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("foo", link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_withTargetViewWithParameterNoText() { - RouterLink link = new RouterLink(TestView.class, "something"); - Assert.assertEquals("", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/something", - link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_withTargetViewWithRouteParametersNoText() { - RouteParameters routeParameters = HasUrlParameterFormat - .getParameters("something"); - RouterLink link = new RouterLink(TestView.class, routeParameters); - Assert.assertEquals("", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/something", - link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_explicitRouterWithTargetViewNoText() { - RouterLink link = new RouterLink(router, FooNavigationTarget.class); - Assert.assertEquals("", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("foo", link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_explicitRouterWithTargetViewWithParameterNoText() { - RouterLink link = new RouterLink(router, TestView.class, "something"); - Assert.assertEquals("", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/something", - link.getElement().getAttribute("href")); - } - - @Test - public void createRouterLink_explicitRouterWithTargetViewWithRouteParametersNoText() { - RouteParameters routeParameters = HasUrlParameterFormat - .getParameters("something"); - RouterLink link = new RouterLink(router, TestView.class, - routeParameters); - Assert.assertEquals("", link.getText()); - Assert.assertTrue(link.getElement() - .hasAttribute(ApplicationConstants.ROUTER_LINK_ATTRIBUTE)); - - Assert.assertTrue(link.getElement().hasAttribute("href")); - - Assert.assertEquals("bar/something", - link.getElement().getAttribute("href")); - } - - @Test - public void createReconfigureRouterLink_implicitCurrentVaadinServiceRouter() { - RouterLink link = new RouterLink("Show something", TestView.class, - "something"); - - link.setRoute(router, TestView.class, "other"); - - Assert.assertEquals("bar/other", - link.getElement().getAttribute("href")); - - link.setRoute(router, TestView.class, "changed"); - - Assert.assertEquals("bar/changed", - link.getElement().getAttribute("href")); - } - - @Test - public void createReconfigureRouterLink_explicitRouter() { - RouterLink link = new RouterLink(router, "Show something", - TestView.class, "something"); - - link.setRoute(router, TestView.class, "other"); - - Assert.assertEquals("bar/other", - link.getElement().getAttribute("href")); - - link.setRoute(router, TestView.class, "changed"); - - Assert.assertEquals("bar/changed", - link.getElement().getAttribute("href")); - } - - @Test - public void reconfigureRouterLink_attachedLink() { - RouterLink link = new RouterLink(); - ui.add(link); - - link.setRoute(router, TestView.class, "other"); - - Assert.assertEquals("bar/other", - link.getElement().getAttribute("href")); - - link.setRoute(router, TestView.class, "changed"); - - Assert.assertEquals("bar/changed", - link.getElement().getAttribute("href")); - } - - @Test(expected = IllegalStateException.class) - public void noImplicitRouter() { - VaadinService service = VaadinService.getCurrent(); - Mockito.when(service.getRouter()).thenReturn(null); - new RouterLink("Show something", TestView.class); - } - - @Test - public void routerLink_withoutRouter_WithRouteParameters() { - assertRouterLinkRouteParameters(false); - } - - @Test - public void routerLink_WithRouteParameters() { - assertRouterLinkRouteParameters(true); - } - - private void assertRouterLinkRouteParameters(boolean useUI) { - RouterLink link = new RouterLink("Foo", ParameterNavigationTarget.class, - new RouteParameters("barId", "barValue")); - - if (useUI) { - ui.add(link); - } - - Assert.assertEquals("foo/barValue/bar", - link.getElement().getAttribute("href")); - - assertRouterLinkSetRoute(link, ParameterNavigationTarget.class, - new RouteParameters("fooId", "123"), "foo/123/foo"); - - assertRouterLinkSetRoute(link, ParameterNavigationTarget.class, - new RouteParameters("foos", "123/qwe"), "foo/123/qwe"); - - try { - link.setRoute(ParameterNavigationTarget.class, - new RouteParameters("fooId", "qwe")); - Assert.fail("Route is not registered."); - } catch (IllegalArgumentException e) { - } - } - - private void assertRouterLinkSetRoute(RouterLink link, - Class target, RouteParameters parameters, - String url) { - link.setRoute(target, parameters); - Assert.assertEquals(url, link.getElement().getAttribute("href")); - } - - private void triggerNavigationEvent(com.vaadin.flow.router.Router router, - RouterLink link, String location) { - AfterNavigationEvent event = new AfterNavigationEvent( - new LocationChangeEvent(router, new UI(), - NavigationTrigger.ROUTER_LINK, new Location(location), - Collections.emptyList())); - link.afterNavigation(event); - } - - @Override - protected VaadinService createService() { - return Mockito.mock(VaadinService.class); - } - - @Test - public void routerLinkCreationForNormalRouteTarget() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - Assert.assertEquals("foo", link.getHref()); - } - - @Test - public void routerLinkCreationForUrlParameterRouteTarget() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Greeting", - GreetingNavigationTarget.class, "hello"); - Assert.assertEquals("greeting/hello", link.getHref()); - } - - @Test - public void routerLinkDefaultHighlightCondition() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - - triggerNavigationEvent(router, link, "foo/bar"); - Assert.assertTrue(link.getElement().hasAttribute("highlight")); - - triggerNavigationEvent(router, link, "baz"); - Assert.assertFalse(link.getElement().hasAttribute("highlight")); - } - - @Test - public void routerLinkSameLocationHighlightCondition() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - link.setHighlightCondition(HighlightConditions.sameLocation()); - - triggerNavigationEvent(router, link, "foo/bar"); - Assert.assertFalse(link.getElement().hasAttribute("highlight")); - - triggerNavigationEvent(router, link, "foo"); - Assert.assertTrue(link.getElement().hasAttribute("highlight")); - } - - @Test - public void routerLinkLocationPrefixHighlightCondition() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - link.setHighlightCondition( - HighlightConditions.locationPrefix("foo/ba")); - - triggerNavigationEvent(router, link, "foo/bar"); - Assert.assertTrue(link.getElement().hasAttribute("highlight")); - - triggerNavigationEvent(router, link, "foo/baz"); - Assert.assertTrue(link.getElement().hasAttribute("highlight")); - - triggerNavigationEvent(router, link, "foo/qux"); - Assert.assertFalse(link.getElement().hasAttribute("highlight")); - } - - @Test - public void routerLinkClearOldHighlightAction() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - triggerNavigationEvent(router, link, "foo/bar"); - - link.setHighlightAction(HighlightActions.toggleClassName("highlight")); - triggerNavigationEvent(router, link, "foo/bar/baz"); - - Assert.assertFalse(link.getElement().hasAttribute("highlight")); - } - - @Test - public void routerLinkClassNameHightlightAction() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - link.setHighlightAction(HighlightActions.toggleClassName("highlight")); - - triggerNavigationEvent(router, link, "foo/bar"); - Assert.assertTrue(link.hasClassName("highlight")); - - triggerNavigationEvent(router, link, "bar"); - Assert.assertFalse(link.hasClassName("highlight")); - } - - @Test - public void routerLinkThemeHightlightAction() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - link.setHighlightAction(HighlightActions.toggleTheme("highlight")); - - triggerNavigationEvent(router, link, "foo/bar"); - Assert.assertTrue( - link.getElement().getThemeList().contains("highlight")); - - triggerNavigationEvent(router, link, "bar"); - Assert.assertFalse( - link.getElement().getThemeList().contains("highlight")); - } - - @Test - public void routerLinkQueryParameters() - throws InvalidRouteConfigurationException { - RouterLink link = new RouterLink(router, "Foo", - FooNavigationTarget.class); - - Map paramMap = new HashMap<>(); - paramMap.put("foo", "bar"); - QueryParameters params = QueryParameters.simple(paramMap); - link.setQueryParameters(params); - String href = link.getHref(); - Assert.assertEquals("foo?foo=bar", href); - - link.setQueryParameters(null); - href = link.getHref(); - Assert.assertEquals("foo", href); - } - - @Test - public void routerLinkToNotRouterTarget_throwsIAE() { - expectedEx.expect(IllegalArgumentException.class); - new RouterLink("", Foo.class); - } - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Route("foo") - @Tag(Tag.DIV) - public static class FooNavigationTarget extends Component { - } - - @Route("foo/:barId?/bar") - @RouteAlias("foo/:fooId(" + RouteParameterRegex.INTEGER + ")/foo") - @RouteAlias("foo/:foos*") - @Tag(Tag.DIV) - public static class ParameterNavigationTarget extends Component { - } - - @Route("greeting") - @PageTitle("Custom Title") - @Tag(Tag.DIV) - public static class GreetingNavigationTarget extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Tag(Tag.DIV) - public static class Foo extends Component { - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RouterTest.java b/flow-server/src/test/java/com/vaadin/flow/router/RouterTest.java deleted file mode 100644 index 014ddfabdc5..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RouterTest.java +++ /dev/null @@ -1,4165 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EventObject; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.jcip.annotations.NotThreadSafe; - -import org.hamcrest.MatcherAssert; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.ComponentUtil; -import com.vaadin.flow.component.HasComponents; -import com.vaadin.flow.component.HasElement; -import com.vaadin.flow.component.Html; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.ExtendedClientDetails; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.i18n.LocaleChangeEvent; -import com.vaadin.flow.i18n.LocaleChangeObserver; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.router.BeforeLeaveEvent.ContinueNavigationAction; -import com.vaadin.flow.router.RouterTest.CombinedObserverTarget.Enter; -import com.vaadin.flow.router.RouterTest.CombinedObserverTarget.Leave; -import com.vaadin.flow.router.internal.DefaultErrorHandler; -import com.vaadin.flow.router.internal.HasUrlParameterFormat; -import com.vaadin.flow.router.internal.RouteUtil; -import com.vaadin.flow.server.HttpStatusCode; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; -import com.vaadin.flow.shared.Registration; - -import elemental.json.Json; -import elemental.json.JsonObject; - -import static com.vaadin.flow.router.internal.RouteModelTest.parameters; -import static com.vaadin.flow.router.internal.RouteModelTest.varargs; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.junit.Assert.assertEquals; - -@NotThreadSafe -public class RouterTest extends RoutingTestBase { - - private static final String DYNAMIC_TITLE = "I am dynamic!"; - public static final String EXCEPTION_WRAPPER_MESSAGE = "There was an exception while trying to navigate to '%s' with the exception message '%s'"; - - private UI ui; - - private VaadinService service = Mockito.mock(VaadinService.class); - - private DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - - @Route("") - @Tag(Tag.DIV) - public static class RootNavigationTarget extends Component - implements AfterNavigationObserver { - - static List events = new ArrayList<>(); - - @Override - public void afterNavigation(AfterNavigationEvent event) { - events.add(event); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class AfterNavigationTarget extends Component - implements AfterNavigationObserver { - - static List events = new ArrayList<>(); - - @Override - public void afterNavigation(AfterNavigationEvent event) { - events.add("AfterNavigation Observer"); - } - } - - @Route("foo") - @Tag(Tag.DIV) - public static class FooNavigationTarget extends Component { - - } - - @Route("foo/bar") - @Tag(Tag.DIV) - public static class FooBarNavigationTarget extends Component - implements BeforeEnterObserver, BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - @Route("manual") - @Tag(Tag.DIV) - public static class ManualNavigationTarget extends Component - implements BeforeEnterObserver, BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add("Before enter"); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add("Before leave"); - } - } - - @Route("enteringTarget") - @Tag(Tag.DIV) - public static class EnteringNavigationTarget extends Component - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - } - - @Route("leavingTarget") - @Tag(Tag.DIV) - public static class LeavingNavigationTarget extends Component - implements BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - @Route("combined") - @Tag(Tag.DIV) - public static class CombinedObserverTarget extends Component { - @Tag(Tag.DIV) - public static class Enter extends Component - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - } - - @Tag(Tag.DIV) - public static class Leave extends Component - implements BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - @Tag(Tag.DIV) - public static class Before extends Component - implements BeforeEnterObserver, BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - public CombinedObserverTarget() { - getElement().appendChild(new Enter().getElement(), - new Leave().getElement(), new Before().getElement()); - } - } - - @Route("reroute") - @Tag(Tag.DIV) - public static class ReroutingNavigationTarget extends Component - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - event.rerouteTo(new NavigationStateBuilder(event.getSource()) - .withTarget(FooBarNavigationTarget.class).build()); - } - } - - @Route("reroute") - @Tag(Tag.DIV) - public static class ReroutingOnLeaveNavigationTarget extends Component - implements BeforeLeaveObserver { - private static List events = new ArrayList<>(); - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - // Note possible loop problem with redirecting on beforeLeave! - if (events.isEmpty()) { - events.add(event); - event.rerouteTo(new NavigationStateBuilder(event.getSource()) - .withTarget(FooBarNavigationTarget.class).build()); - } - } - } - - @Route("param") - @Tag(Tag.DIV) - public static class ParameterRouteNoParameter extends Component { - } - - @Route("param") - @Tag(Tag.DIV) - public static class RouteWithParameter extends Component - implements BeforeEnterObserver, HasUrlParameter { - - private static String param; - - private static List events = new ArrayList<>(); - - @Override - public void setParameter(BeforeEvent event, String parameter) { - events.add(event); - param = parameter; - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - } - - @Route("param") - @Tag(Tag.DIV) - public static class RouteWithMultipleParameters extends Component - implements BeforeEnterObserver, HasUrlParameter { - - private static String param; - - private static List events = new ArrayList<>(); - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - events.add(event); - param = parameter; - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - } - - @Route("param/static") - @Tag(Tag.DIV) - public static class StaticParameter extends Component { - } - - @Route("optional") - @Tag(Tag.DIV) - public static class OptionalNoParameter extends Component { - } - - @Route("optional") - @Tag(Tag.DIV) - public static class OptionalParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @com.vaadin.flow.router.OptionalParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("optional") - @Tag(Tag.DIV) - public static class WithoutOptionalParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("usupported/wildcard") - @Tag(Tag.DIV) - public static class UnsupportedWildParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static Integer param; - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter Integer parameter) { - events.add(event); - param = parameter; - } - } - - @Route("wild") - @Tag(Tag.DIV) - public static class WildParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("wild") - @Tag(Tag.DIV) - public static class WildHasParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("integer") - @Tag(Tag.DIV) - public static class IntegerParameter extends Component - implements HasUrlParameter { - - protected static List events = new ArrayList<>(); - - private static Integer param; - - @Override - public void setParameter(BeforeEvent event, Integer parameter) { - events.add(event); - param = parameter; - } - } - - @Route("long") - @Tag(Tag.DIV) - public static class LongParameter extends Component - implements HasUrlParameter { - - protected static List events = new ArrayList<>(); - - private static Long param; - - @Override - public void setParameter(BeforeEvent event, Long parameter) { - events.add(event); - param = parameter; - } - } - - @Route("boolean") - @Tag(Tag.DIV) - public static class BooleanParameter extends Component - implements HasUrlParameter { - - protected static List events = new ArrayList<>(); - - private static Boolean param; - - @Override - public void setParameter(BeforeEvent event, Boolean parameter) { - events.add(event); - param = parameter; - } - } - - @Route("wild") - @Tag(Tag.DIV) - public static class WildNormal extends Component { - } - - @Route("redirect/to/param") - @Tag(Tag.DIV) - public static class RerouteToRouteWithParam extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteTo("param", "hello"); - } - } - - @Route("fail/param") - @Tag(Tag.DIV) - public static class FailRerouteWithParam extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteTo("param", Boolean.TRUE); - } - } - - @Route("redirect/to/params") - @Tag(Tag.DIV) - public static class RerouteToRouteWithMultipleParams extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteTo("param", Arrays.asList("this", "must", "work")); - } - } - - @Route("fail/params") - @Tag(Tag.DIV) - public static class FailRerouteWithParams extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteTo("param", Arrays.asList(1L, 2L)); - } - } - - @Route("navigation-target-with-title") - @PageTitle("Custom Title") - @Tag(Tag.DIV) - public static class NavigationTargetWithTitle extends Component { - } - - @RoutePrefix("parent-with-title") - @PageTitle("Parent Title") - @Tag(Tag.DIV) - public static class ParentWithTitle extends Component - implements RouterLayout { - } - - @Route(value = "child", layout = ParentWithTitle.class) - @Tag(Tag.DIV) - public static class ChildWithoutTitle extends Component { - } - - @Route("navigation-target-with-dynamic-title") - @Tag(Tag.DIV) - public static class NavigationTargetWithDynamicTitle extends Component - implements HasDynamicTitle { - - public NavigationTargetWithDynamicTitle() { - } - - @Override - public String getPageTitle() { - return DYNAMIC_TITLE; - } - } - - @Route("url") - @Tag(Tag.DIV) - public static class NavigationTargetWithDynamicTitleFromUrl extends - Component implements HasDynamicTitle, HasUrlParameter { - - private String title = DYNAMIC_TITLE; - - public NavigationTargetWithDynamicTitleFromUrl() { - } - - @Override - public String getPageTitle() { - return title; - } - - @Override - public void setParameter(BeforeEvent event, - @com.vaadin.flow.router.OptionalParameter String parameter) { - title = parameter; - } - } - - @Route("url") - @Tag(Tag.DIV) - public static class NavigationTargetWithDynamicTitleFromNavigation - extends Component implements HasDynamicTitle, BeforeEnterObserver { - - private String title = DYNAMIC_TITLE; - - public NavigationTargetWithDynamicTitleFromNavigation() { - } - - @Override - public String getPageTitle() { - return title; - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - title = "ACTIVATING"; - } - } - - @Route("navigationEvents") - @Tag(Tag.DIV) - public static class NavigationEvents extends Component { - - private static List events = new ArrayList<>(); - - public NavigationEvents() { - getElement().appendChild(new AfterNavigation().getElement()); - getElement().appendChild(new BeforeNavigation().getElement()); - } - } - - @Tag(Tag.DIV) - private static class AfterNavigation extends Component - implements AfterNavigationObserver { - - @Override - public void afterNavigation(AfterNavigationEvent event) { - NavigationEvents.events.add(event); - } - } - - @Tag(Tag.DIV) - private static class BeforeNavigation extends Component - implements BeforeEnterObserver, BeforeLeaveObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - NavigationEvents.events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - NavigationEvents.events.add(event); - } - } - - @RoutePrefix("parent") - @Tag(Tag.DIV) - public static class RouteParent extends Component implements RouterLayout { - private final RouterLink loneLink = new RouterLink("lone", - LoneRoute.class); - - public RouteParent() { - getElement().appendChild(loneLink.getElement()); - } - } - - @Route(value = "after-navigation-child", layout = RouteParent.class) - @Tag(Tag.DIV) - public static class AfterNavigationChild extends Component - implements AfterNavigationObserver { - - static List events = new ArrayList<>(); - - @Override - public void afterNavigation(AfterNavigationEvent event) { - events.add(event); - } - } - - @Route(value = "after-navigation-within-same-parent", layout = RouteParent.class) - @Tag(Tag.DIV) - public static class AfterNavigationWithinSameParent extends Component - implements AfterNavigationObserver { - - static List events = new ArrayList<>(); - - @Override - public void afterNavigation(AfterNavigationEvent event) { - events.add(event); - } - } - - @Route(value = "child", layout = RouteParent.class) - @Tag(Tag.DIV) - public static class RouteChild extends Component - implements BeforeLeaveObserver, BeforeEnterObserver { - - static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - - } - - @Route(value = "childWithParameter", layout = RouteParent.class) - @Tag(Tag.DIV) - public static class RouteChildWithParameter extends Component implements - BeforeLeaveObserver, BeforeEnterObserver, HasUrlParameter { - - static List events = new ArrayList<>(); - static List parameters = new ArrayList<>(); - - @Override - public void setParameter(BeforeEvent event, String parameter) { - parameters.add(parameter); - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - @Route(value = "single", layout = RouteParent.class, absolute = true) - @Tag(Tag.DIV) - public static class LoneRoute extends Component - implements BeforeEnterObserver { - - static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - } - - @Route("") - @Tag(Tag.DIV) - public static class WildRootParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("") - @Tag(Tag.DIV) - public static class OptionalRootParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, - @com.vaadin.flow.router.OptionalParameter String parameter) { - events.add(event); - param = parameter; - } - } - - @Route("") - @Tag(Tag.DIV) - public static class RootParameter extends Component - implements HasUrlParameter { - - private static List events = new ArrayList<>(); - - private static String param; - - @Override - public void setParameter(BeforeEvent event, String parameter) { - events.add(event); - param = parameter; - } - } - - public static class ErrorTarget extends RouteNotFoundError - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - private static String message; - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - message = ((Html) getChildren().findFirst().get()).getInnerHtml(); - } - } - - public static final String EXCEPTION_TEXT = "My custom not found class!"; - - public static class CustomNotFoundTarget extends RouteNotFoundError { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - getElement().setText(EXCEPTION_TEXT); - return HttpStatusCode.NOT_FOUND.getCode(); - } - } - - @Tag(Tag.DIV) - public static class NonExtendingNotFoundTarget extends Component - implements HasErrorParameter { - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - getElement().setText(EXCEPTION_TEXT); - return HttpStatusCode.NOT_FOUND.getCode(); - } - } - - @Tag(Tag.DIV) - @ParentLayout(RouteParent.class) - public static class ErrorTargetWithParent extends Component - implements HasErrorParameter { - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - getElement().setText(EXCEPTION_TEXT); - return HttpStatusCode.NOT_FOUND.getCode(); - } - } - - @Tag(Tag.DIV) - public static class DuplicateNotFoundTarget extends Component - implements HasErrorParameter { - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - getElement().setText(EXCEPTION_TEXT); - return HttpStatusCode.NOT_FOUND.getCode(); - } - } - - @Tag(Tag.DIV) - public static class FileNotFound extends Component - implements HasErrorParameter { - private static NavigationTrigger trigger; - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - trigger = event.getTrigger(); - return HttpStatusCode.NOT_FOUND.getCode(); - } - } - - @Tag(Tag.DIV) - public static class FailingErrorHandler extends Component - implements HasErrorParameter { - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - throw new RuntimeException(parameter.getException()); - } - } - - @Route("exception") - @Tag(Tag.DIV) - public static class FailOnException extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - throw new RuntimeException("Failed on an exception"); - } - } - - @Tag(Tag.DIV) - public static class FaultyErrorView extends Component - implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - // Return faulty status code. - return 0; - } - } - - @Route("forwardAndReroute/exception") - @Tag(Tag.DIV) - public static class ForwardingAndReroutingNavigationTarget extends Component - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - event.forwardTo(new NavigationStateBuilder(event.getSource()) - .withTarget(FooBarNavigationTarget.class).build()); - - event.rerouteTo(new NavigationStateBuilder(event.getSource()) - .withTarget(FooBarNavigationTarget.class).build()); - } - } - - @Route("beforeToError/exception") - @Tag(Tag.DIV) - public static class RerouteToError extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteToError(IllegalArgumentException.class); - } - } - - @Route("beforeToError/message") - @Tag(Tag.DIV) - public static class RerouteToErrorWithMessage extends Component - implements BeforeEnterObserver, HasUrlParameter { - - private String message; - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteToError(IllegalArgumentException.class, message); - } - - @Override - public void setParameter(BeforeEvent event, String parameter) { - message = parameter; - } - } - - @Tag(Tag.DIV) - public static class IllegalTarget extends Component - implements HasErrorParameter { - - private static List events = new ArrayList<>(); - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - events.add(event); - if (parameter.hasCustomMessage()) { - getElement().setText(parameter.getCustomMessage()); - } else { - getElement().setText("Illegal argument exception."); - } - return HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(); - } - } - - @Route("loop") - @Tag(Tag.DIV) - public static class LoopByUINavigate extends Component - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - UI.getCurrent().navigate("loop"); - } - } - - @Route("loop") - @Tag(Tag.DIV) - public static class LoopOnRouterNavigate extends Component - implements BeforeEnterObserver { - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - UI ui = UI.getCurrent(); - ui.getInternals().getRouter().navigate(ui, new Location("loop"), - NavigationTrigger.PROGRAMMATIC); - } - } - - @Route("redirect/loop") - @Tag(Tag.DIV) - public static class RedirectToLoopByReroute extends Component - implements BeforeEnterObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - UI.getCurrent().navigate("loop"); - } - } - - @Route("postpone") - @Tag(Tag.DIV) - public static class PostponingForeverNavigationTarget extends Component - implements BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - event.postpone(); - events.add(event); - } - } - - @Route("postpone") - @Tag(Tag.DIV) - public static class PostponingAndResumingNavigationTarget extends Component - implements BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - ContinueNavigationAction action = event.postpone(); - events.add(event); - action.proceed(); - } - - } - - @Route("postpone") - @Tag(Tag.DIV) - public static class PostponingFirstTimeNavigationTarget extends Component - implements BeforeLeaveObserver { - - private int counter = 0; - - private static List events = new ArrayList<>(); - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - counter++; - if (counter < 2) { - event.postpone(); - } - events.add(event); - } - } - - @Tag(Tag.DIV) - public static class ChildListener extends Component - implements BeforeEnterObserver, BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - - @Override - public void beforeEnter(BeforeEnterEvent event) { - events.add(event); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - events.add(event); - } - } - - @Route("postpone") - @Tag(Tag.DIV) - public static class PostponingAndResumingCompoundNavigationTarget - extends Component implements BeforeLeaveObserver { - - private static List events = new ArrayList<>(); - private static ContinueNavigationAction postpone; - - public PostponingAndResumingCompoundNavigationTarget() { - getElement().appendChild(new ChildListener().getElement()); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - postpone = event.postpone(); - events.add(event); - } - } - - @Route("foo") - @Tag(Tag.DIV) - public static class ProceedRightAfterPospone extends Component - implements BeforeLeaveObserver { - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - event.postpone().proceed(); - } - - } - - @Route("toNotFound") - @Tag(Tag.DIV) - public static class RedirectToNotFoundInHasParam extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - event.rerouteToError(NotFoundException.class); - } - } - - @Route("param/reroute") - @Tag(Tag.DIV) - public static class RedirectOnSetParam extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - // NOTE! Expects RootParameter.class to be registered! - event.rerouteTo("", parameter); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class Translations extends Component - implements LocaleChangeObserver { - - private static List events = new ArrayList<>(); - - @Override - public void localeChange(LocaleChangeEvent event) { - events.add(event); - } - } - - @Tag(Tag.DIV) - public static class MainLayout extends Component implements RouterLayout { - } - - @Route(value = "base", layout = MainLayout.class) - @ParentLayout(MainLayout.class) - @Tag(Tag.DIV) - public static class BaseLayout extends Component implements RouterLayout { - } - - @Route(value = "sub", layout = BaseLayout.class) - @Tag(Tag.DIV) - public static class SubLayout extends Component { - } - - @Tag(Tag.DIV) - public static abstract class AbstractMain extends Component { - } - - @Route("") - @Tag(Tag.DIV) - public static class ExtendingView extends AbstractMain { - } - - @Route - @Tag(Tag.DIV) - public static class Main extends Component { - } - - @Route - @Tag(Tag.DIV) - public static class MainView extends Component { - } - - @Route - @Tag(Tag.DIV) - public static class NamingConvention extends Component { - } - - @Route - @Tag(Tag.DIV) - public static class NamingConventionView extends Component { - } - - @Route - @Tag(Tag.DIV) - public static class View extends Component { - } - - @Route(value = "1", layout = NoRemoveLayout.class) - @Tag(Tag.DIV) - public static class NoRemoveContent1 extends Component { - - } - - @Route(value = "2", layout = NoRemoveLayout.class) - @Tag(Tag.DIV) - public static class NoRemoveContent2 extends Component { - - } - - @Tag(Tag.DIV) - public static class NoRemoveLayout extends Component - implements RouterLayout { - @Override - public void removeRouterLayoutContent(HasElement oldContent) { - // Do nothing - } - } - - /** - * This class is used as a based for some navigation chains. It will log - * into the static lists init, beforeLeave, - * beforeEnter and afterNavigation the respective - * events in the order they are triggered, where init is the - * constructor. The value logged is the id field of the class - * which by default is the class name. - */ - @Tag(Tag.DIV) - public static class ProcessEventsBase extends Component - implements BeforeLeaveObserver, BeforeEnterObserver, - AfterNavigationObserver, HasComponents { - - static List init = new ArrayList<>(); - - static List beforeLeave = new ArrayList<>(); - - static List beforeEnter = new ArrayList<>(); - - static List afterNavigation = new ArrayList<>(); - - static void clear() { - init.clear(); - beforeLeave.clear(); - beforeEnter.clear(); - afterNavigation.clear(); - } - - private String id; - - public ProcessEventsBase() { - this(null); - } - - public ProcessEventsBase(String id) { - this.id = id != null ? id : getClass().getSimpleName(); - init.add(this.id); - } - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - beforeLeave.add(id); - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - beforeEnter.add(id); - } - - public void setParameter(BeforeEvent event, String parameter) { - beforeEnter.add(parameter); - } - - @Override - public void afterNavigation(AfterNavigationEvent event) { - afterNavigation.add(id); - } - - } - - /** - * This is the root layout of the navigation chain. It also adds some - * children components used in the assertion of the event order, as being - * children of the layout in the chain instead of being part of the layout - * chain itself. - * - * So any children of an instance of this class should receive the - * navigation events right after the instance of this class receives them - * and in the order they are added. - */ - public static class ProcessEventsRoot extends ProcessEventsBase - implements RouterLayout { - - public ProcessEventsRoot() { - ProcessEventsBase child1 = new ProcessEventsBase("rootChild1"); - child1.add(new ProcessEventsBase("rootChild11")); - - add(child1); - add(new ProcessEventsBase("rootChild2")); - - } - } - - /** - * Just a navigation chain layout. - */ - @ParentLayout(ProcessEventsRoot.class) - public static class ProcessEventsTrunk extends ProcessEventsBase - implements RouterLayout { - - } - - /** - * Just another layout in the navigation chain. See - * {@link ProcessEventsRoot} for more details. - */ - @ParentLayout(ProcessEventsTrunk.class) - public static class ProcessEventsBranch extends ProcessEventsBase - implements RouterLayout { - - public ProcessEventsBranch() { - add(new ProcessEventsBase("branchChild1")); - - ProcessEventsBase child1 = new ProcessEventsBase("branchChild2"); - add(child1); - - child1.add(new ProcessEventsBase("branchChild21")); - } - } - - /** - * Simple navigation target. - */ - @Route(value = "event/flower", layout = ProcessEventsBranch.class) - public static class ProcessEventsFlower extends ProcessEventsBase { - - } - - /** - * Simple navigation target with preserve on refresh. - */ - @Route(value = "event/fruit", layout = ProcessEventsBranch.class) - @PreserveOnRefresh - public static class ProcessEventsFruit extends ProcessEventsBase { - - } - - /** - * Navigation target using one parameter. We want to assert whether the - * setParameter is triggered right before - * beforeEvent does. - */ - @Route(value = "event/leaf", layout = ProcessEventsBranch.class) - public static class ProcessEventsLeaf extends ProcessEventsBase - implements HasUrlParameter { - - public ProcessEventsLeaf() { - // This child should get the last beforeEvent, after setParameter - // and this instance's beforeEvent. - add(new ProcessEventsBase("leafChild")); - } - - @Override - public void setParameter(BeforeEvent event, String parameter) { - super.setParameter(event, parameter); - } - } - - /** - * Navigation target using one parameter. We want to assert whether - * setParameter is triggered before this component's child, - * considering it doesn't observe the event. - */ - @Route(value = "event/needle", layout = ProcessEventsBranch.class) - @Tag(Tag.DIV) - public static class ProcessEventsNeedle extends Component - implements HasComponents, HasUrlParameter { - - public ProcessEventsNeedle() { - ProcessEventsBase.init.add(getClass().getSimpleName()); - - // This child should get the last beforeEvent, after setParameter - // and this instance's beforeEvent. - add(new ProcessEventsBase("needleChild")); - } - - @Override - public void setParameter(BeforeEvent event, String parameter) { - ProcessEventsBase.beforeEnter.add(parameter); - } - } - - /** - * A navigation layout used to redirect. This is used to assert that any - * following layouts and the navigation target won't be created when a - * redirect happens. - */ - @ParentLayout(ProcessEventsTrunk.class) - public static class ProcessEventsRotten extends ProcessEventsBase - implements RouterLayout { - - public ProcessEventsRotten() { - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - super.beforeEnter(event); - - event.rerouteTo("event/flower"); - } - } - - /** - * Just a navigation chain layout. - */ - @ParentLayout(ProcessEventsRotten.class) - public static class ProcessEventsStick extends ProcessEventsBase - implements RouterLayout { - - public ProcessEventsStick() { - } - } - - /** - * Navigating to this target will reroute from - * ProcessEventsRotten which is a class on the parent layout - * chain. So this class shouldn't even be initialized when navigating to it. - */ - @Route(value = "event/twig", layout = ProcessEventsStick.class) - public static class ProcessEventsTwig extends ProcessEventsBase { - - } - - /** - * Parent layout used to reroute to login when not logged in. - */ - public static class SecurityParent extends ProcessEventsBase - implements RouterLayout { - - @Override - public void beforeLeave(BeforeLeaveEvent event) { - super.beforeLeave(event); - - // Only testing beforeLeave that same target redirect is not - // processed. - event.forwardTo("security/login"); - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - super.beforeEnter(event); - - event.rerouteTo("security/login"); - } - - } - - @Route(value = "security/login", layout = SecurityParent.class) - public static class SecurityLogin extends ProcessEventsBase { - - } - - @Route(value = "security/document", layout = SecurityParent.class) - public static class SecurityDocument extends ProcessEventsBase { - - } - - @Tag(Tag.DIV) - public static class RouteParametersBase extends Component - implements BeforeEnterObserver { - - static RouteParameters parameters; - - static Class target; - - static void clear() { - parameters = null; - target = null; - } - - @Override - public void beforeEnter(BeforeEnterEvent event) { - parameters = event.getRouteParameters(); - target = getClass(); - } - } - - @RoutePrefix(":parentID") - public static class ParentWithParameter extends RouteParametersBase - implements RouterLayout { - } - - @Route(value = "", layout = ParentWithParameter.class) - @RoutePrefix("link/:chainLinkID") - @ParentLayout(ParentWithParameter.class) - public static class ChainLinkWithParameter extends RouteParametersBase - implements RouterLayout { - } - - @Route(value = "target/:targetChainLinkID/bar", layout = ChainLinkWithParameter.class) - public static class TargetWithParameter extends RouteParametersBase { - } - - @Route(value = ":optional?/:anotherOptional?", layout = ChainLinkWithParameter.class) - public static class TargetWithOptionalParameters - extends RouteParametersBase { - } - - @Route(value = ":targetChainLinkID", layout = ParentWithParameter.class) - @RoutePrefix("targetLink/:chainLinkID?/chainLink") - @ParentLayout(ParentWithParameter.class) - public static class ChainLinkWithParameterAndTarget - extends RouteParametersBase implements RouterLayout { - } - - @Route(value = ":anotherTargetID/:yetAnotherID/foo/:varargsFoo*", layout = ChainLinkWithParameterAndTarget.class) - public static class AnotherTargetWithParameter extends RouteParametersBase { - } - - @Route(":intType(" + RouteParameterRegex.INTEGER + ")") - @RouteAlias(":stringType") - @RouteAlias(":intType?(" + RouteParameterRegex.INTEGER + ")" - + "/:stringType?/:varargs*(thinking|of|U|and|I)") - @RoutePrefix("param/types") - public static class ParameterTypesView extends RouteParametersBase - implements RouterLayout { - } - - @Route(":something?") - @RouteAlias(":messageID(" + RouteParameterRegex.INTEGER + ")") - @RouteAlias("last") - @RoutePrefix("forum/thread/:threadID(" + RouteParameterRegex.INTEGER + ")") - public static class ParametersForumThreadView extends RouteParametersBase - implements RouterLayout { - } - - @Route(":alias(framework|platform|vaadin-spring|vaadin-spring-boot)/:version?(v?\\d.*)/:path*") - @RouteAlias(":groupId(\\w[\\w\\d]+\\.[\\w\\d\\-\\.]+)/:artifactId/:version?(v?\\d.*)/:path*") - @RouteAlias(":path*") - @RoutePrefix("api") - public static class ParametersApiView extends RouteParametersBase - implements RouterLayout { - } - - @Route(":tabIdentifier?(api)/:apiPath*") - @RouteAlias(":tabIdentifier?(overview|samples|links|reviews|discussions)") - @RoutePrefix("directory/component/:urlIdentifier/:versionIdentifier?(v?\\d.*)") - public static class DetailsView extends RouteParametersBase - implements RouterLayout { - } - - @Route("") - @RouteAlias("param/:regex?([0-9]*)") - @RouteAlias("param/:regex?([0-9]*)/edit") - public static class ParametersRegexView extends RouteParametersBase { - } - - @Route("") - @RouteAlias(":search?") - @RoutePrefix("search") - public static class SearchView extends RouteParametersBase { - } - - @Route("show") - public static class ShowAllView extends RouteParametersBase { - } - - @Route("show/:filter?") - public static class RedirectRouteParametersView - extends RouteParametersBase { - - static boolean doForward = false; - - @Override - public void beforeEnter(BeforeEnterEvent event) { - super.beforeEnter(event); - - event.getRouteParameters().get("filter").ifPresent(value -> { - - if (!value.equals("original")) { - RouteParametersBase.clear(); - - if (value.equals("wrong")) { - redirect(event, RedirectWithRouteParametersView.class, - new RouteParameters("noParameter", value)); - } else if (value.equals("all")) { - redirect(event, RedirectToView.class); - } else { - redirect(event, RedirectWithRouteParametersView.class, - new RouteParameters("text", value)); - } - } - }); - } - - private void redirect(BeforeEnterEvent event, - Class target) { - if (doForward) { - // These methods without parameters should be tested. - event.forwardTo(target); - } else { - event.rerouteTo(target); - } - } - - private void redirect(BeforeEnterEvent event, - Class target, RouteParameters parameters) { - if (doForward) { - event.forwardTo(target, parameters); - } else { - event.rerouteTo(target, parameters); - } - } - } - - @Route("filter") - public static class RedirectToView extends RouteParametersBase { - } - - @Route("filter/:text") - public static class RedirectWithRouteParametersView - extends RouteParametersBase { - } - - @Route("forward/setParameter/back") - @Tag(Tag.DIV) - public static class ForwardSetParameterBackView extends Component - implements BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - ForwardSetParameterView.backBeforeEnterInvoked = true; - } - } - - @Route("forward/setParameter") - @Tag(Tag.DIV) - public static class ForwardSetParameterView extends Component - implements HasUrlParameter, AfterNavigationObserver { - - static boolean afterNavigationInvoked = false; - static boolean backBeforeEnterInvoked = false; - - private static void clear() { - afterNavigationInvoked = false; - backBeforeEnterInvoked = false; - } - - @Override - public void setParameter(BeforeEvent event, String parameter) { - afterNavigationInvoked = false; - - event.forwardTo(ForwardSetParameterBackView.class); - } - - @Override - public void afterNavigation(AfterNavigationEvent event) { - afterNavigationInvoked = true; - } - } - - @Route("forwardtourl") - @Tag(Tag.DIV) - public static class RedirectToExternalUrl extends Component { - static AtomicInteger instancesCreated = new AtomicInteger(0); - - public RedirectToExternalUrl() { - instancesCreated.incrementAndGet(); - } - - } - - @Override - @Before - public void init() throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - super.init(); - ui = new RouterTestMockUI(router); - ui.getSession().lock(); - ui.getSession().setConfiguration(configuration); - - VaadinService.setCurrent(service); - - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - Mockito.when(service.getRouter()).thenReturn(router); - - Mockito.when(configuration.isProductionMode()).thenReturn(true); - } - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Test - public void basic_navigation() throws InvalidRouteConfigurationException { - setNavigationTargets(RootNavigationTarget.class, - FooNavigationTarget.class, FooBarNavigationTarget.class); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals(RootNavigationTarget.class, getUIComponentClass()); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals(FooNavigationTarget.class, getUIComponentClass()); - - router.navigate(ui, new Location("foo/bar"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals(FooBarNavigationTarget.class, - getUIComponentClass()); - } - - @Test - public void resolveNavigation_pathContainsDots_dotSegmentIsNotParentReference_noException() { - router.resolveNavigationTarget("/.../dsfsdfsdf", - Collections.emptyMap()); - // doesn't throw - } - - @Test(expected = InvalidLocationException.class) - public void resolveNavigation_pathContainsDots_pathIsRelative_noException() { - router.resolveNavigationTarget("/../dsfsdfsdf", Collections.emptyMap()); - // Location explicitly disallows ".." segments - } - - @Test - public void page_title_set_from_annotation() - throws InvalidRouteConfigurationException { - setNavigationTargets(NavigationTargetWithTitle.class); - router.navigate(ui, new Location("navigation-target-with-title"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Custom Title", ui.getInternals().getTitle()); - } - - @Test - public void page_title_not_set_from_annotation_in_parent() - throws InvalidRouteConfigurationException { - setNavigationTargets(ChildWithoutTitle.class); - - router.navigate(ui, new Location("parent-with-title/child"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("", ui.getInternals().getTitle()); - } - - @Test - public void page_title_set_dynamically() - throws InvalidRouteConfigurationException { - setNavigationTargets(NavigationTargetWithDynamicTitle.class); - - router.navigate(ui, - new Location("navigation-target-with-dynamic-title"), - NavigationTrigger.PROGRAMMATIC); - - MatcherAssert.assertThat("Dynamic title is wrong", - ui.getInternals().getTitle(), is(DYNAMIC_TITLE)); - } - - @Test - public void page_title_set_dynamically_from_url_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(NavigationTargetWithDynamicTitleFromUrl.class); - - router.navigate(ui, new Location("url/hello"), - NavigationTrigger.PROGRAMMATIC); - - MatcherAssert.assertThat("Dynamic title is wrong", - ui.getInternals().getTitle(), is("hello")); - } - - @Test - public void page_title_set_dynamically_from_event_handler() - throws InvalidRouteConfigurationException { - setNavigationTargets( - NavigationTargetWithDynamicTitleFromNavigation.class); - - router.navigate(ui, new Location("url"), - NavigationTrigger.PROGRAMMATIC); - - MatcherAssert.assertThat("Dynamic title is wrong", - ui.getInternals().getTitle(), is("ACTIVATING")); - } - - @Test - public void before_navigation_event_is_triggered() - throws InvalidRouteConfigurationException { - FooBarNavigationTarget.events.clear(); - setNavigationTargets(RootNavigationTarget.class, - FooNavigationTarget.class, FooBarNavigationTarget.class); - - router.navigate(ui, new Location("foo/bar"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 1, - FooBarNavigationTarget.events.size()); - Assert.assertEquals("Unexpected event type", BeforeEnterEvent.class, - FooBarNavigationTarget.events.get(0).getClass()); - } - - @Test - public void leave_and_enter_listeners_only_receive_correct_state() - throws InvalidRouteConfigurationException { - setNavigationTargets(LeavingNavigationTarget.class, - EnteringNavigationTarget.class, RootNavigationTarget.class); - - router.navigate(ui, new Location("enteringTarget"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("BeforeEnterObserver should have fired.", 1, - EnteringNavigationTarget.events.size()); - - router.navigate(ui, new Location("leavingTarget"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("No leave or enter target should have fired.", 1, - EnteringNavigationTarget.events.size()); - - Assert.assertEquals("No leave or enter target should have fired.", 0, - LeavingNavigationTarget.events.size()); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("BeforeLeaveObserver should have fired", 1, - LeavingNavigationTarget.events.size()); - } - - @Test - public void leave_navigate_and_enter_listeners_execute_in_correct_order() - throws InvalidRouteConfigurationException { - setNavigationTargets(CombinedObserverTarget.class, - RootNavigationTarget.class); - - // Observer execution order should be BeforeNavigation before - // EnterListener, but BeforeLeave before BeforeNavigation - router.navigate(ui, new Location("combined"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("BeforeEnterObserver should have fired.", 1, - Enter.events.size()); - - Assert.assertEquals("BeforeNavigationObserver should have fired.", 1, - CombinedObserverTarget.Before.events.size()); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("BeforeLeaveObserver target should have fired.", 1, - Leave.events.size()); - - Assert.assertEquals( - "BeforeNavigationObserver target should have fired.", 2, - CombinedObserverTarget.Before.events.size()); - - Assert.assertEquals("LeaveListener got event", BeforeLeaveEvent.class, - CombinedObserverTarget.Before.events.get(1).getClass()); - } - - @Test - public void before_navigation_event_is_triggered_for_attach_and_detach() - throws InvalidRouteConfigurationException { - FooBarNavigationTarget.events.clear(); - setNavigationTargets(RootNavigationTarget.class, - FooNavigationTarget.class, FooBarNavigationTarget.class); - - router.navigate(ui, new Location("foo/bar"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 1, - FooBarNavigationTarget.events.size()); - Assert.assertEquals(BeforeEnterEvent.class, - FooBarNavigationTarget.events.get(0).getClass()); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 2, - FooBarNavigationTarget.events.size()); - Assert.assertEquals(BeforeLeaveEvent.class, - FooBarNavigationTarget.events.get(1).getClass()); - } - - @Test - public void reroute_on_before_navigation_event() - throws InvalidRouteConfigurationException { - FooBarNavigationTarget.events.clear(); - ReroutingNavigationTarget.events.clear(); - RootNavigationTarget.events.clear(); - setNavigationTargets(RootNavigationTarget.class, - ReroutingNavigationTarget.class, FooBarNavigationTarget.class); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Map params = new HashMap<>(); - params.put("foo", "bar"); - QueryParameters queryParameters = QueryParameters.simple(params); - - router.navigate(ui, new Location("reroute", queryParameters), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - ReroutingNavigationTarget.events.size()); - - Assert.assertEquals("Expected event amount was wrong", 1, - FooBarNavigationTarget.events.size()); - - Assert.assertEquals(FooBarNavigationTarget.class, - getUIComponentClass()); - - Assert.assertEquals(BeforeEnterEvent.class, - ReroutingNavigationTarget.events.get(0).getClass()); - Assert.assertEquals(BeforeEnterEvent.class, - FooBarNavigationTarget.events.get(0).getClass()); - - QueryParameters rerouteQueryParameters = FooBarNavigationTarget.events - .get(0).getLocation().getQueryParameters(); - Assert.assertNotNull(rerouteQueryParameters); - - List foo = rerouteQueryParameters.getParameters().get("foo"); - Assert.assertNotNull(foo); - Assert.assertFalse(foo.isEmpty()); - Assert.assertEquals(foo.get(0), "bar"); - } - - @Test - public void before_and_after_event_fired_in_correct_order() - throws InvalidRouteConfigurationException { - NavigationEvents.events.clear(); - setNavigationTargets(NavigationEvents.class); - - router.navigate(ui, new Location("navigationEvents"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - NavigationEvents.events.size()); - - Assert.assertEquals("Before navigation event was wrong.", - BeforeEnterEvent.class, - NavigationEvents.events.get(0).getClass()); - - Assert.assertEquals("After navigation event was wrong.", - AfterNavigationEvent.class, - NavigationEvents.events.get(1).getClass()); - } - - @Test - public void after_event_not_fired_on_detach() - throws InvalidRouteConfigurationException { - NavigationEvents.events.clear(); - setNavigationTargets(NavigationEvents.class, FooNavigationTarget.class); - - router.navigate(ui, new Location("navigationEvents"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - NavigationEvents.events.size()); - Assert.assertEquals("Before navigation event was wrong.", - BeforeEnterEvent.class, - NavigationEvents.events.get(0).getClass()); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 3, - NavigationEvents.events.size()); - Assert.assertEquals("After navigation event was wrong.", - BeforeLeaveEvent.class, - NavigationEvents.events.get(2).getClass()); - } - - @Test - public void reroute_with_url_parameter() - throws InvalidRouteConfigurationException { - RouteWithParameter.events.clear(); - setNavigationTargets(GreetingNavigationTarget.class, - RouteWithParameter.class, RerouteToRouteWithParam.class); - - router.navigate(ui, new Location("redirect/to/param"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - RouteWithParameter.events.size()); - Assert.assertEquals("Before navigation event was wrong.", "hello", - RouteWithParameter.param); - } - - @Test - public void reroute_fails_with_no_url_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - ParameterRouteNoParameter.class, RerouteToRouteWithParam.class); - String locationString = "redirect/to/param"; - - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "Routing with mismatching parameters should have failed -", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - String message = "No route 'param' accepting the parameters [hello] was found."; - String exceptionText = String.format(EXCEPTION_WRAPPER_MESSAGE, - locationString, message); - assertExceptionComponent(exceptionText); - } - - @Test - public void reroute_fails_with_faulty_url_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - RouteWithParameter.class, FailRerouteWithParam.class); - - String locationString = "fail/param"; - router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - String message = "Given route parameter 'class java.lang.Boolean' is of the wrong type. Required 'class java.lang.String'."; - String exceptionText = String.format(EXCEPTION_WRAPPER_MESSAGE, - locationString, message); - - assertExceptionComponent(exceptionText); - } - - @Test - public void reroute_with_multiple_route_parameters() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - RouteWithMultipleParameters.class, - RerouteToRouteWithMultipleParams.class); - - router.navigate(ui, new Location("redirect/to/params"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - RouteWithMultipleParameters.events.size()); - Assert.assertEquals("Before navigation event was wrong.", - "this/must/work", RouteWithMultipleParameters.param); - } - - @Test - public void reroute_fails_with_faulty_route_parameters() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - RouteWithMultipleParameters.class, FailRerouteWithParams.class); - String locationString = "fail/params"; - - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "Routing with mismatching parameters should have failed -", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - String message = "Given route parameter 'class java.lang.Long' is of the wrong type. Required 'class java.lang.String'."; - String exceptionText = String.format(EXCEPTION_WRAPPER_MESSAGE, - locationString, message); - assertExceptionComponent(exceptionText); - } - - @Test - public void reroute_with_multiple_route_parameters_fails_to_parameterless_target() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - ParameterRouteNoParameter.class, - RerouteToRouteWithMultipleParams.class); - String locationString = "redirect/to/params"; - - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "Routing with mismatching parameters should have failed -", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - String message = "No route 'param' accepting the parameters [this, must, work] was found."; - String exceptionText = String.format(EXCEPTION_WRAPPER_MESSAGE, - locationString, message); - assertExceptionComponent(exceptionText); - } - - @Test - public void reroute_with_multiple_route_parameters_fails_to_single_parameter_target() - throws InvalidRouteConfigurationException { - setNavigationTargets(GreetingNavigationTarget.class, - RouteWithParameter.class, - RerouteToRouteWithMultipleParams.class); - String locationString = "redirect/to/params"; - - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "Routing with mismatching parameters should have failed -", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - String message = "No route 'param' accepting the parameters [this, must, work] was found."; - String exceptionText = String.format(EXCEPTION_WRAPPER_MESSAGE, - locationString, message); - assertExceptionComponent(exceptionText); - } - - @Test - public void route_precedence_when_one_has_parameter() - throws InvalidRouteConfigurationException { - RouteWithParameter.events.clear(); - setNavigationTargets(RouteWithParameter.class, StaticParameter.class); - - router.navigate(ui, new Location("param/param"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals(RouteWithParameter.class, getUIComponentClass()); - - // Expectation of 2 events is due to parameter and BeforeNavigation - Assert.assertEquals("Expected event amount was wrong", 2, - RouteWithParameter.events.size()); - Assert.assertEquals("Before navigation event was wrong.", "param", - RouteWithParameter.param); - - router.navigate(ui, new Location("param/static"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals( - "Did not get correct class even though StaticParameter should have precedence over RouteWithParameter due to exact url match.", - StaticParameter.class, getUIComponentClass()); - } - - @Test - public void optional_parameter_gets_parameter() - throws InvalidRouteConfigurationException { - OptionalParameter.events.clear(); - setNavigationTargets(OptionalParameter.class); - - router.navigate(ui, new Location("optional/parameter"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - OptionalParameter.events.size()); - Assert.assertEquals("Before navigation event was wrong.", "parameter", - OptionalParameter.param); - } - - @Test - public void optional_parameter_matches_no_parameter() - throws InvalidRouteConfigurationException { - OptionalParameter.events.clear(); - OptionalParameter.param = null; - setNavigationTargets(OptionalParameter.class); - - router.navigate(ui, new Location("optional"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - OptionalParameter.events.size()); - Assert.assertNull("Before navigation event was wrong.", - OptionalParameter.param); - } - - @Test - public void correctly_return_route_with_one_base_route_with_optionals() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteWithParameter.class, - ParameterRouteNoParameter.class); - - router.navigate(ui, new Location("param/parameter"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Failed", RouteWithParameter.class, - getUIComponentClass()); - } - - @Test - public void base_route_and_optional_parameter_throws_configuration_error() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets '%s' and '%s' have the same path and '%s' has an OptionalParameter that will never be used as optional.", - OptionalNoParameter.class.getName(), - OptionalParameter.class.getName(), - OptionalParameter.class.getName())); - - setNavigationTargets(OptionalParameter.class, - OptionalNoParameter.class); - - } - - @Test - public void navigateToRoot_errorCode_dontRedirect() - throws InvalidRouteConfigurationException { - - setNavigationTargets(FooNavigationTarget.class); - - Assert.assertEquals(HttpStatusCode.NOT_FOUND.getCode(), router.navigate( - ui, new Location(""), NavigationTrigger.PROGRAMMATIC)); - } - - @Test - public void navigating_to_route_with_wildcard_parameter() - throws InvalidRouteConfigurationException { - WildParameter.events.clear(); - WildParameter.param = null; - setNavigationTargets(WildParameter.class); - - router.navigate(ui, new Location("wild"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - WildParameter.events.size()); - Assert.assertEquals("Parameter should be empty", "", - WildParameter.param); - - router.navigate(ui, new Location("wild/single"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 2, - WildParameter.events.size()); - Assert.assertEquals("Parameter should be empty", "single", - WildParameter.param); - - router.navigate(ui, new Location("wild/multi/part/parameter"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 3, - WildParameter.events.size()); - Assert.assertEquals("Parameter should be empty", "multi/part/parameter", - WildParameter.param); - } - - @Test - public void route_with_wildcard_parameter_should_be_last_hit() - throws InvalidRouteConfigurationException { - WildParameter.events.clear(); - WildParameter.param = null; - setNavigationTargets(WildParameter.class, WildHasParameter.class, - WildNormal.class); - - router.navigate(ui, new Location("wild"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 0, - WildHasParameter.events.size()); - - router.navigate(ui, new Location("wild/parameter"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - WildHasParameter.events.size()); - Assert.assertEquals("Parameter didn't match expected value", - "parameter", WildHasParameter.param); - - router.navigate(ui, new Location("wild/multi/part/parameter"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - WildParameter.events.size()); - Assert.assertEquals("Parameter didn't match expected value", - "multi/part/parameter", WildParameter.param); - - } - - @Test - public void root_navigation_target_with_required_parameter() - throws InvalidRouteConfigurationException { - RootParameter.events.clear(); - setNavigationTargets(RootParameter.class); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "Has url with required parameter should not match to \"\"", 0, - RootParameter.events.size()); - } - - @Test - public void reroute_on_hasParameter_step() - throws InvalidRouteConfigurationException { - RootParameter.events.clear(); - setNavigationTargets(RootParameter.class, RedirectOnSetParam.class); - - router.navigate(ui, new Location("param/reroute/hello"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - RootParameter.events.size()); - Assert.assertEquals("Parameter should match the one in url", "hello", - RootParameter.param); - } - - @Test - public void has_url_with_supported_parameters_navigation() - throws InvalidRouteConfigurationException { - IntegerParameter.events.clear(); - LongParameter.events.clear(); - BooleanParameter.events.clear(); - setNavigationTargets(IntegerParameter.class, LongParameter.class, - BooleanParameter.class); - - router.navigate(ui, new Location("integer/5"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 1, - IntegerParameter.events.size()); - Assert.assertEquals("Parameter should match the one in url", 5, - IntegerParameter.param.intValue()); - - router.navigate(ui, new Location("long/5"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 1, - LongParameter.events.size()); - Assert.assertEquals("Parameter should match the one in url", 5, - LongParameter.param.longValue()); - - router.navigate(ui, new Location("boolean/true"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 1, - BooleanParameter.events.size()); - Assert.assertEquals("Parameter should match the one in url", true, - BooleanParameter.param); - } - - @Test - public void longParameter_deserialization() - throws InvalidRouteConfigurationException { - LongParameter.events.clear(); - setNavigationTargets(LongParameter.class); - - router.navigate(ui, new Location("long/+" + Long.MAX_VALUE), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected event amount was wrong", 1, - LongParameter.events.size()); - Assert.assertEquals("Parameter should accept long max with +", - Long.MAX_VALUE, LongParameter.param.longValue()); - - router.navigate(ui, new Location("long/" + Long.MIN_VALUE), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Expected negative and positive event", 2, - LongParameter.events.size()); - Assert.assertEquals("Parameter should accept long max with +", - Long.MIN_VALUE, LongParameter.param.longValue()); - - // Navigation will give a 404 not found if the deserialization fails. - Assert.assertEquals(404, - router.navigate(ui, new Location("long/9223372036854775817"), - NavigationTrigger.PROGRAMMATIC)); - Assert.assertEquals("No faulty event recorded", 2, - LongParameter.events.size()); - } - - @Test - public void default_wildcard_support_only_for_string() - throws InvalidRouteConfigurationException { - setNavigationTargets(UnsupportedWildParameter.class); - - String locationString = "usupported/wildcard/3/4/1"; - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - String message = String.format( - "Invalid wildcard parameter in class %s. Only String is supported for wildcard parameters.", - UnsupportedWildParameter.class.getName()); - String exceptionText1 = String.format("Could not navigate to '%s'", - locationString); - String exceptionText2 = String.format( - "Reason: Failed to parse url parameter, exception: %s", - new UnsupportedOperationException(message)); - - assertExceptionComponent(RouteNotFoundError.class, exceptionText1, - exceptionText2); - } - - @Test - public void unparsable_url_parameter() - throws InvalidRouteConfigurationException { - setNavigationTargets(LongParameter.class); - - String locationString = "long/unsupportedParam"; - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - String exceptionText1 = String.format("Could not navigate to '%s'", - locationString); - String exceptionText2 = String - .format("Reason: Couldn't find route for '%s'", locationString); - - assertExceptionComponent(RouteNotFoundError.class, exceptionText1, - exceptionText2); - } - - @Test - public void redirect_to_routeNotFound_error_view_when_no_route_found() - throws InvalidRouteConfigurationException { - ErrorTarget.events.clear(); - setNavigationTargets(FooNavigationTarget.class); - setErrorNavigationTargets(ErrorTarget.class); - - String locationString = "error"; - int result = router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - Assert.assertEquals("Expected event amount was wrong", 1, - ErrorTarget.events.size()); - - String errorMessage = ErrorTarget.message; - Assert.assertTrue(errorMessage.contains( - String.format("Could not navigate to '%s'", locationString))); - Assert.assertTrue(errorMessage.contains( - String.format("Couldn't find route for '%s'", locationString))); - } - - @Test - public void exception_during_navigation_is_caught_and_show_in_internalServerError() - throws InvalidRouteConfigurationException { - setNavigationTargets(FailOnException.class); - - int result = router.navigate(ui, new Location("exception"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - } - - @Test - public void fail_for_multiple_classes_extending_the_same_exception_class() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - setErrorNavigationTargets(ErrorTarget.class, - CustomNotFoundTarget.class); - } - - @Route("npe") - @Tag(Tag.DIV) - public static class NpeNavigationTarget extends Component { - public NpeNavigationTarget() { - throw new NullPointerException("Null was found"); - } - } - - @Tag(Tag.DIV) - @DefaultErrorHandler - public static class DefaultNullPointerException extends Component - implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return HttpStatusCode.UNAUTHORIZED.getCode(); - } - } - - @Tag(Tag.DIV) - public static class NullPointerExceptionHandler extends Component - implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(); - } - } - - @Test // spring #661 - public void pick_custom_from_multiple_error_targets_when_other_is_default_annotated() { - setNavigationTargets(NpeNavigationTarget.class); - setErrorNavigationTargets(DefaultNullPointerException.class, - NullPointerExceptionHandler.class); - - int result = router.navigate(ui, new Location("npe"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals( - "Null pointer should return the server error of the custom implementation.", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - - Assert.assertEquals( - "Expected the extending class to be used instead of the super class", - NullPointerExceptionHandler.class, getUIComponentClass()); - } - - @Test - public void do_not_accept_same_exception_targets() { - - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(startsWith( - "Only one target for an exception should be defined. Found ")); - - setErrorNavigationTargets(NonExtendingNotFoundTarget.class, - DuplicateNotFoundTarget.class); - } - - @Test - public void custom_exception_target_should_override_default_ones() { - setErrorNavigationTargets(NonExtendingNotFoundTarget.class, - RouteNotFoundError.class); - - int result = router.navigate(ui, new Location("exception"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - Assert.assertEquals( - "Expected the extending class to be used instead of the super class", - NonExtendingNotFoundTarget.class, getUIComponentClass()); - - assertExceptionComponent(NonExtendingNotFoundTarget.class, - EXCEPTION_TEXT); - } - - @Test - public void custom_exception_target_is_used() { - setErrorNavigationTargets(CustomNotFoundTarget.class, - RouteNotFoundError.class); - - int result = router.navigate(ui, new Location("exception"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - Assert.assertEquals( - "Expected the extending class to be used instead of the super class", - CustomNotFoundTarget.class, getUIComponentClass()); - - assertExceptionComponent(CustomNotFoundTarget.class, EXCEPTION_TEXT); - } - - @Test - public void error_target_has_parent_layout() - throws InvalidRouteConfigurationException { - // Needed for the router link in the parent used by the error views - setNavigationTargets(LoneRoute.class); - setErrorNavigationTargets(ErrorTargetWithParent.class, - RouteNotFoundError.class); - - int result = router.navigate(ui, new Location("exception"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - Component parenComponent = ComponentUtil - .findParentComponent(ui.getElement().getChild(0)).get(); - - Assert.assertEquals(RouteParent.class, parenComponent.getClass()); - - List> childClasses = parenComponent.getChildren() - .map(Object::getClass).collect(Collectors.toList()); - Assert.assertEquals( - Arrays.asList(RouterLink.class, ErrorTargetWithParent.class), - childClasses); - } - - @Test - public void reroute_to_error_opens_expected_error_target() - throws InvalidRouteConfigurationException { - setNavigationTargets(RerouteToError.class); - setErrorNavigationTargets(IllegalTarget.class); - - int result = router.navigate(ui, - new Location("beforeToError/exception"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Target should have rerouted to exception target.", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - - Assert.assertEquals(IllegalTarget.class, getUIComponentClass()); - - Optional visibleComponent = ui.getElement().getChild(0) - .getComponent(); - Assert.assertEquals("Illegal argument exception.", - visibleComponent.get().getElement().getText()); - } - - @Test - public void reroute_to_error_with_custom_message_message_is_used() - throws InvalidRouteConfigurationException { - IllegalTarget.events.clear(); - setNavigationTargets(RerouteToErrorWithMessage.class); - setErrorNavigationTargets(IllegalTarget.class); - - int result = router.navigate(ui, - new Location("beforeToError/message/CustomMessage"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Target should have rerouted to exception target.", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - - Assert.assertEquals(IllegalTarget.class, getUIComponentClass()); - - Optional visibleComponent = ui.getElement().getChild(0) - .getComponent(); - Assert.assertEquals("CustomMessage", - visibleComponent.get().getElement().getText()); - - Assert.assertEquals("Expected only one event message from error view", - 1, IllegalTarget.events.size()); - BeforeEnterEvent event = (BeforeEnterEvent) IllegalTarget.events.get(0); - Assert.assertEquals("Parameter should be empty", - "beforeToError/message/CustomMessage", - event.getLocation().getPath()); - - } - - @Test - public void reroute_to_error_from_has_param() - throws InvalidRouteConfigurationException { - setNavigationTargets(RedirectToNotFoundInHasParam.class); - - int result = router.navigate(ui, new Location("toNotFound/error"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Target should have rerouted to exception target.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - Assert.assertEquals(RouteNotFoundError.class, getUIComponentClass()); - } - - @Test - public void forward_and_reroute_at_the_same_time_exception() - throws InvalidRouteConfigurationException { - String location = "forwardAndReroute/exception"; - - FooBarNavigationTarget.events.clear(); - ForwardingAndReroutingNavigationTarget.events.clear(); - RootNavigationTarget.events.clear(); - setNavigationTargets(RootNavigationTarget.class, - ForwardingAndReroutingNavigationTarget.class, - FooBarNavigationTarget.class); - - router.navigate(ui, new Location(location), - NavigationTrigger.PROGRAMMATIC); - - String validationMessage = "Error forward & reroute can not be set at the same time"; - - String errorMessage = String.format( - "There was an exception while trying to navigate to '%s' with the exception message '%s'", - location, validationMessage); - - assertExceptionComponent(InternalServerError.class, errorMessage); - } - - @Test - public void faulty_error_response_code_should_throw_exception() - throws InvalidRouteConfigurationException { - setNavigationTargets(RerouteToError.class); - setErrorNavigationTargets(FaultyErrorView.class); - - String location = "beforeToError/exception"; - int result = router.navigate(ui, new Location(location), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "Target should have failed on an internal exception.", - HttpStatusCode.INTERNAL_SERVER_ERROR.getCode(), result); - - String validationMessage = String.format( - "Error state code must be a valid HttpStatusCode value. Received invalid value of '%s' for '%s'", - 0, FaultyErrorView.class.getName()); - - String errorMessage = String.format( - "There was an exception while trying to navigate to '%s' with the exception message '%s'", - location, validationMessage); - - assertExceptionComponent(InternalServerError.class, errorMessage); - } - - @Test - public void repeatedly_navigating_to_same_ur_through_ui_navigate_should_not_loop() - throws InvalidRouteConfigurationException { - LoopByUINavigate.events.clear(); - setNavigationTargets(LoopByUINavigate.class); - - ui.navigate("loop"); - - Assert.assertEquals("Expected only one request to loop", 1, - LoopByUINavigate.events.size()); - Assert.assertNull("Last handled location should have been cleared", - ui.getInternals().getLastHandledLocation()); - } - - @Test - public void ui_navigate_should_not_loop() - throws InvalidRouteConfigurationException { - LoopByUINavigate.events.clear(); - RedirectToLoopByReroute.events.clear(); - setNavigationTargets(LoopByUINavigate.class, - RedirectToLoopByReroute.class); - - ui.navigate("redirect/loop"); - - Assert.assertEquals("Expected one events", 1, - LoopByUINavigate.events.size()); - Assert.assertEquals("Expected onve events", 1, - RedirectToLoopByReroute.events.size()); - } - - @Test - public void ui_navigate_should_only_have_one_history_marking_on_loop() - throws InvalidRouteConfigurationException { - setNavigationTargets(LoopByUINavigate.class); - - ui.navigate("loop"); - - long historyInvocations = ui.getInternals() - .dumpPendingJavaScriptInvocations().stream() - .filter(js -> js.getInvocation().getExpression() - .contains("history.pushState")) - .count(); - assertEquals(1, historyInvocations); - - Assert.assertNull("Last handled location should have been cleared", - ui.getInternals().getLastHandledLocation()); - } - - @Test - public void router_navigate_should_not_loop() - throws InvalidRouteConfigurationException { - setNavigationTargets(LoopOnRouterNavigate.class); - - ui.navigate("loop"); - - Assert.assertEquals("Expected only one request", 1, - LoopOnRouterNavigate.events.size()); - Assert.assertNull("Last handled location should have been cleared", - ui.getInternals().getLastHandledLocation()); - } - - @Test - public void exception_while_navigating_should_succeed_and_clear_last_handled() - throws InvalidRouteConfigurationException { - setNavigationTargets(FailOnException.class); - - ui.navigate("exception"); - - Assert.assertNull("Last handled location should have been cleared", - ui.getInternals().getLastHandledLocation()); - } - - @Test - public void exception_in_exception_handler_while_navigating_should_clear_last_handled() - throws InvalidRouteConfigurationException { - setNavigationTargets(FailOnException.class); - setErrorNavigationTargets(FailingErrorHandler.class); - - try { - ui.navigate("exception"); - Assert.fail("No runtime exception was thrown from navigation"); - } catch (Exception re) { - Assert.assertNull( - "Last handled location should have been cleared even though navigation failed", - ui.getInternals().getLastHandledLocation()); - } - } - - @Test - public void postpone_then_resume_on_before_navigation_event() - throws InvalidRouteConfigurationException, InterruptedException { - RootNavigationTarget.events.clear(); - PostponingAndResumingNavigationTarget.events.clear(); - setNavigationTargets(RootNavigationTarget.class, - PostponingAndResumingNavigationTarget.class); - - int status1 = router.navigate(ui, new Location("postpone"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("First transition failed", - HttpStatusCode.OK.getCode(), status1); - Assert.assertEquals(PostponingAndResumingNavigationTarget.class, - getUIComponentClass()); - - Assert.assertEquals("Expected event amount was wrong", 0, - PostponingAndResumingNavigationTarget.events.size()); - - int status2 = router.navigate(ui, new Location(""), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Second transition failed", - HttpStatusCode.OK.getCode(), status2); - - Assert.assertEquals(RootNavigationTarget.class, getUIComponentClass()); - Assert.assertEquals( - "Expected event in the first target amount was wrong", 1, - PostponingAndResumingNavigationTarget.events.size()); - Assert.assertEquals( - "Expected event amount in the last target was wrong", 1, - RootNavigationTarget.events.size()); - } - - @Test - public void postpone_forever_on_before_navigation_event() - throws InvalidRouteConfigurationException { - RootNavigationTarget.events.clear(); - PostponingAndResumingNavigationTarget.events.clear(); - setNavigationTargets(RootNavigationTarget.class, - PostponingForeverNavigationTarget.class); - - int status1 = router.navigate(ui, new Location("postpone"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("First transition failed", - HttpStatusCode.OK.getCode(), status1); - Assert.assertEquals(PostponingForeverNavigationTarget.class, - getUIComponentClass()); - - int status2 = router.navigate(ui, new Location(""), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Second transition failed", - HttpStatusCode.OK.getCode(), status2); - - Assert.assertEquals(PostponingForeverNavigationTarget.class, - getUIComponentClass()); - Assert.assertEquals("Expected event amount in the target was wrong", 1, - PostponingForeverNavigationTarget.events.size()); - - Assert.assertEquals("Expected event amount in the root was wrong", 0, - RootNavigationTarget.events.size()); - } - - @Test - public void postpone_obsoleted_by_new_navigation_transition() - throws InvalidRouteConfigurationException, InterruptedException { - FooBarNavigationTarget.events.clear(); - FooBarNavigationTarget.events.clear(); - setNavigationTargets(FooNavigationTarget.class, - FooBarNavigationTarget.class, - PostponingFirstTimeNavigationTarget.class); - - int status1 = router.navigate(ui, new Location("postpone"), - NavigationTrigger.PROGRAMMATIC); - int status2 = router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("Expected event amount was wrong", 1, - PostponingFirstTimeNavigationTarget.events.size()); - BeforeLeaveEvent event = PostponingFirstTimeNavigationTarget.events - .get(0); - - int status3 = router.navigate(ui, new Location("foo/bar"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("First transition failed", - HttpStatusCode.OK.getCode(), status1); - Assert.assertEquals(FooBarNavigationTarget.class, - getUIComponentClass()); - - event.postpone().proceed(); - - Assert.assertEquals("Second transition failed", - HttpStatusCode.OK.getCode(), status2); - Assert.assertEquals("Third transition failed", - HttpStatusCode.OK.getCode(), status3); - - Assert.assertEquals(FooBarNavigationTarget.class, - getUIComponentClass()); - Assert.assertEquals("Expected event amount was wrong", 2, - PostponingFirstTimeNavigationTarget.events.size()); - - Assert.assertEquals("Expected event amount was wrong", 1, - FooBarNavigationTarget.events.size()); - } - - @Test - public void postpone_then_resume_with_multiple_listeners() - throws InvalidRouteConfigurationException, InterruptedException { - setNavigationTargets(RootNavigationTarget.class, - PostponingAndResumingCompoundNavigationTarget.class); - - int status1 = router.navigate(ui, new Location("postpone"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("First transition failed", - HttpStatusCode.OK.getCode(), status1); - Assert.assertEquals(PostponingAndResumingCompoundNavigationTarget.class, - getUIComponentClass()); - - int status2 = router.navigate(ui, new Location(""), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Second transition failed", - HttpStatusCode.OK.getCode(), status2); - - Assert.assertNotNull( - PostponingAndResumingCompoundNavigationTarget.postpone); - - PostponingAndResumingCompoundNavigationTarget.postpone.proceed(); - - Assert.assertEquals(RootNavigationTarget.class, getUIComponentClass()); - Assert.assertEquals(1, - PostponingAndResumingCompoundNavigationTarget.events.size()); - Assert.assertEquals(2, ChildListener.events.size()); - Assert.assertEquals(BeforeEnterEvent.class, - ChildListener.events.get(0).getClass()); - Assert.assertEquals(BeforeLeaveEvent.class, - ChildListener.events.get(1).getClass()); - } - - @Test - public void navigation_should_fire_locale_change_observer() - throws InvalidRouteConfigurationException { - Translations.events.clear(); - setNavigationTargets(Translations.class); - - ui.navigate(""); - - Assert.assertEquals("Expected event amount was wrong", 1, - Translations.events.size()); - Assert.assertEquals(Locale.getDefault(), - Translations.events.get(0).getLocale()); - } - - @Test - public void away_navigation_should_not_inform_observer() - throws InvalidRouteConfigurationException, InterruptedException { - Translations.events.clear(); - setNavigationTargets(FooNavigationTarget.class, Translations.class); - - ui.navigate(""); - - Assert.assertEquals("Expected event amount was wrong", 1, - Translations.events.size()); - Assert.assertEquals(Locale.getDefault(), - Translations.events.get(0).getLocale()); - - ui.navigate("foo"); - - Assert.assertEquals("Recorded event amount should have stayed the same", - 1, Translations.events.size()); - } - - @Test // 3424 - public void route_as_parent_layout_handles_as_expected() - throws InvalidRouteConfigurationException { - setNavigationTargets(BaseLayout.class, SubLayout.class); - - ui.navigate("base"); - Assert.assertEquals(MainLayout.class, getUIComponentClass()); - - List children = ui.getChildren() - .collect(Collectors.toList()); - Assert.assertEquals(1, children.size()); - Assert.assertEquals(MainLayout.class, children.get(0).getClass()); - children = children.get(0).getChildren().collect(Collectors.toList()); - Assert.assertEquals(1, children.size()); - Assert.assertEquals(BaseLayout.class, children.get(0).getClass()); - children = children.get(0).getChildren().collect(Collectors.toList()); - Assert.assertTrue(children.isEmpty()); - - ui.navigate("sub"); - Assert.assertEquals(MainLayout.class, getUIComponentClass()); - - children = ui.getChildren().collect(Collectors.toList()); - Assert.assertEquals(1, children.size()); - Assert.assertEquals(MainLayout.class, children.get(0).getClass()); - children = children.get(0).getChildren().collect(Collectors.toList()); - Assert.assertEquals(1, children.size()); - Assert.assertEquals(BaseLayout.class, children.get(0).getClass()); - children = children.get(0).getChildren().collect(Collectors.toList()); - Assert.assertEquals(1, children.size()); - Assert.assertEquals(SubLayout.class, children.get(0).getClass()); - children = children.get(0).getChildren().collect(Collectors.toList()); - Assert.assertTrue(children.isEmpty()); - - } - - @Test - public void proceedRightAfterPostpone_navigationIsDone() - throws InvalidRouteConfigurationException { - setNavigationTargets(ProceedRightAfterPospone.class, - RootNavigationTarget.class); - - RootNavigationTarget.events.clear(); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - // View ProceedRightAfterPospone postpones the navigation and - // immediately proceed, it means that RootNavigationTarget should be - // informed about AfterNavigationEvent - Assert.assertEquals(1, RootNavigationTarget.events.size()); - Assert.assertEquals(AfterNavigationEvent.class, - RootNavigationTarget.events.get(0).getClass()); - } - - @Test - public void navigateWithinOneParent_oneLeaveEventOneEnterEvent() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteChild.class, LoneRoute.class); - - router.navigate(ui, new Location("parent/child"), - NavigationTrigger.PROGRAMMATIC); - RouteChild.events.clear(); - router.navigate(ui, new Location("single"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals(1, RouteChild.events.size()); - Assert.assertEquals(BeforeLeaveEvent.class, - RouteChild.events.get(0).getClass()); - - Assert.assertEquals(1, LoneRoute.events.size()); - Assert.assertEquals(BeforeEnterEvent.class, - LoneRoute.events.get(0).getClass()); - } - - @Test - public void navigateWithinOneParent_oneAfterNavigationEventOneEventOnly() - throws InvalidRouteConfigurationException { - setNavigationTargets(AfterNavigationChild.class, - AfterNavigationWithinSameParent.class, LoneRoute.class); - - router.navigate(ui, new Location("parent/after-navigation-child"), - NavigationTrigger.PROGRAMMATIC); - AfterNavigationChild.events.clear(); - router.navigate(ui, - new Location("parent/after-navigation-within-same-parent"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "After navigation event should not be fired for " - + AfterNavigationChild.class.getSimpleName(), - 0, AfterNavigationChild.events.size()); - - Assert.assertEquals( - "Only one navigation event should be fired for " - + AfterNavigationWithinSameParent.class.getSimpleName(), - 1, AfterNavigationWithinSameParent.events.size()); - Assert.assertEquals( - "The fired event type should be " - + AfterNavigationEvent.class.getSimpleName(), - AfterNavigationEvent.class, - AfterNavigationWithinSameParent.events.get(0).getClass()); - } - - @Test // #2754 - public void manually_registered_listeners_should_fire_for_every_navigation() - throws InvalidRouteConfigurationException { - setNavigationTargets(RootNavigationTarget.class, - FooNavigationTarget.class, FooBarNavigationTarget.class); - - AtomicInteger leaveCount = new AtomicInteger(0); - AtomicInteger enterCount = new AtomicInteger(0); - AtomicInteger afterCount = new AtomicInteger(0); - - ui.addBeforeLeaveListener(event -> leaveCount.incrementAndGet()); - ui.addBeforeEnterListener(event -> enterCount.incrementAndGet()); - ui.addAfterNavigationListener(event -> afterCount.incrementAndGet()); - - Assert.assertEquals( - "No event should have happened due to adding listener.", 0, - leaveCount.get()); - Assert.assertEquals( - "No event should have happened due to adding listener.", 0, - enterCount.get()); - Assert.assertEquals( - "No event should have happened due to adding listener.", 0, - afterCount.get()); - - router.navigate(ui, new Location("foo/bar"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("BeforeLeaveListener should have been invoked.", 1, - leaveCount.get()); - Assert.assertEquals("BeforeEnterListener should have been invoked.", 1, - enterCount.get()); - Assert.assertEquals("AfterNavigationListener should have been invoked.", - 1, afterCount.get()); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("BeforeLeaveListener should have been invoked.", 2, - leaveCount.get()); - Assert.assertEquals("BeforeEnterListener should have been invoked.", 2, - enterCount.get()); - Assert.assertEquals("AfterNavigationListener should have been invoked.", - 2, afterCount.get()); - } - - @Test // #2754 - public void after_navigation_listener_is_only_invoked_once_for_redirect() - throws InvalidRouteConfigurationException { - setNavigationTargets(ReroutingNavigationTarget.class, - FooBarNavigationTarget.class); - - AtomicInteger afterCount = new AtomicInteger(0); - - ui.addAfterNavigationListener(event -> afterCount.incrementAndGet()); - - router.navigate(ui, new Location("reroute"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "AfterNavigationListener should have been invoked only after redirect.", - 1, afterCount.get()); - } - - @Test // #2754 - public void before_leave_listener_is_invoked_for_each_redirect() - throws InvalidRouteConfigurationException { - setNavigationTargets(ReroutingNavigationTarget.class, - FooBarNavigationTarget.class); - - AtomicInteger leaveCount = new AtomicInteger(0); - ui.addBeforeLeaveListener(event -> leaveCount.incrementAndGet()); - - router.navigate(ui, new Location("reroute"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "BeforeLeaveListener should have been invoked for initial navigation and redirect.", - 2, leaveCount.get()); - } - - @Test // #2754 - public void before_enter_listener_is_invoked_for_each_redirect_when_redirecting_on_before_enter() - throws InvalidRouteConfigurationException { - setNavigationTargets(ReroutingNavigationTarget.class, - FooBarNavigationTarget.class); - - AtomicInteger enterCount = new AtomicInteger(0); - ui.addBeforeEnterListener(event -> enterCount.incrementAndGet()); - - router.navigate(ui, new Location("reroute"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "BeforeEnterListener should have been invoked for initial navigation and redirect.", - 2, enterCount.get()); - } - - @Test // #2754 - public void before_enter_listener_is_invoked_once_and_before_leave_twice_when_redirecting_on_before_leave() - throws InvalidRouteConfigurationException { - ReroutingOnLeaveNavigationTarget.events.clear(); - - setNavigationTargets(ReroutingOnLeaveNavigationTarget.class, - FooBarNavigationTarget.class, FooNavigationTarget.class); - - router.navigate(ui, new Location("reroute"), - NavigationTrigger.PROGRAMMATIC); - - AtomicInteger leaveCount = new AtomicInteger(0); - AtomicInteger enterCount = new AtomicInteger(0); - ui.addBeforeLeaveListener(event -> leaveCount.incrementAndGet()); - ui.addBeforeEnterListener(event -> enterCount.incrementAndGet()); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "BeforeLeaveListener should have been invoked for initial navigation and redirect.", - 2, leaveCount.get()); - Assert.assertEquals( - "BeforeEnterListener should have been invoked for initial navigation and redirect.", - 1, enterCount.get()); - } - - @Test // #2754 - public void manual_before_listeners_are_fired_before_observers() - throws InvalidRouteConfigurationException { - ManualNavigationTarget.events.clear(); - setNavigationTargets(ManualNavigationTarget.class, - FooNavigationTarget.class); - - Registration beforeEnter = ui.addBeforeEnterListener( - event -> ManualNavigationTarget.events.add("Manual event")); - - router.navigate(ui, new Location("manual"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("not enough events", 2, - ManualNavigationTarget.events.size()); - - Assert.assertEquals("Manual event", - ManualNavigationTarget.events.get(0)); - Assert.assertEquals("Before enter", - ManualNavigationTarget.events.get(1)); - - // Deactivate before enter and add beforeLeave listener - beforeEnter.remove(); - ui.addBeforeLeaveListener( - event -> ManualNavigationTarget.events.add("Manual event")); - - router.navigate(ui, new Location("foo"), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("not enough events", 4, - ManualNavigationTarget.events.size()); - - Assert.assertEquals("Manual event", - ManualNavigationTarget.events.get(2)); - Assert.assertEquals("Before leave", - ManualNavigationTarget.events.get(3)); - } - - @Test // #2754 - public void manual_after_listener_is_fired_before_observer() - throws InvalidRouteConfigurationException { - AfterNavigationTarget.events.clear(); - setNavigationTargets(AfterNavigationTarget.class); - - ui.addAfterNavigationListener( - event -> AfterNavigationTarget.events.add("Manual event")); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals("not enough events", 2, - AfterNavigationTarget.events.size()); - - Assert.assertEquals("Manual event", - AfterNavigationTarget.events.get(0)); - Assert.assertEquals("AfterNavigation Observer", - AfterNavigationTarget.events.get(1)); - } - - @Test // #3616 - public void navigating_with_class_gets_correct_component() - throws InvalidRouteConfigurationException { - setNavigationTargets(RootNavigationTarget.class, - FooNavigationTarget.class, FooBarNavigationTarget.class); - - Optional target = ui - .navigate(RootNavigationTarget.class); - Assert.assertEquals(getUIComponent(), target.get()); - Assert.assertEquals(RootNavigationTarget.class, getUIComponentClass()); - - ui.navigate(FooNavigationTarget.class); - Assert.assertEquals(FooNavigationTarget.class, getUIComponentClass()); - - ui.navigate(FooBarNavigationTarget.class); - Assert.assertEquals(FooBarNavigationTarget.class, - getUIComponentClass()); - } - - @Test // #3616 - public void navigating_with_class_and_parameter_gets_correct_component() - throws InvalidRouteConfigurationException { - setNavigationTargets(RouteWithParameter.class, BooleanParameter.class, - WildParameter.class, OptionalParameter.class); - - Optional newView = ui - .navigate(RouteWithParameter.class, "Parameter"); - Assert.assertEquals(ComponentUtil - .findParentComponent(ui.getElement().getChild(0)).get(), - newView.get()); - - Assert.assertEquals(RouteWithParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", "Parameter", - RouteWithParameter.param); - - ui.navigate(OptionalParameter.class, "optional"); - Assert.assertEquals(OptionalParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", "optional", - OptionalParameter.param); - Optional target = ui - .navigate(OptionalParameter.class); - Assert.assertEquals(getUIComponent(), target.get()); - Assert.assertEquals(OptionalParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", null, - OptionalParameter.param); - ui.navigate(OptionalParameter.class, (String) null); - Assert.assertEquals(OptionalParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", null, - OptionalParameter.param); - - ui.navigate(BooleanParameter.class, false); - Assert.assertEquals(BooleanParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", false, - BooleanParameter.param); - - ui.navigate(WildParameter.class); - Assert.assertEquals(WildParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", "", - WildParameter.param); - ui.navigate(WildParameter.class, (String) null); - Assert.assertEquals(WildParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", "", - WildParameter.param); - ui.navigate(WildParameter.class, ""); - Assert.assertEquals(WildParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", "", - WildParameter.param); - ui.navigate(WildParameter.class, "my/wild/param"); - Assert.assertEquals(WildParameter.class, getUIComponentClass()); - Assert.assertEquals("Before navigation event was wrong.", - "my/wild/param", WildParameter.param); - - } - - @Test // #3988 - public void exception_event_should_keep_original_trigger() { - setErrorNavigationTargets(FileNotFound.class); - - int result = router.navigate(ui, new Location("programmatic"), - NavigationTrigger.PROGRAMMATIC); - Assert.assertEquals("Non existent route should have returned.", - HttpStatusCode.NOT_FOUND.getCode(), result); - - Assert.assertEquals(NavigationTrigger.PROGRAMMATIC, - FileNotFound.trigger); - - JsonObject state = Json.createObject(); - state.put("href", "router_link"); - state.put("scrollPositionX", 0d); - state.put("scrollPositionY", 0d); - router.navigate(ui, new Location("router_link"), - NavigationTrigger.ROUTER_LINK, state); - - Assert.assertEquals(NavigationTrigger.ROUTER_LINK, - FileNotFound.trigger); - - router.navigate(ui, new Location("history"), NavigationTrigger.HISTORY); - - Assert.assertEquals(NavigationTrigger.HISTORY, FileNotFound.trigger); - - router.navigate(ui, new Location("page_load"), - NavigationTrigger.PAGE_LOAD); - - Assert.assertEquals(NavigationTrigger.PAGE_LOAD, FileNotFound.trigger); - } - - private String resolve(Class clazz) { - Route annotation = clazz.getAnnotation(Route.class); - return RouteUtil.resolve(clazz, annotation); - } - - @Test - public void test_router_resolve() { - Assert.assertEquals("", resolve(Main.class)); - Assert.assertEquals("", resolve(MainView.class)); - Assert.assertEquals("", resolve(View.class)); - Assert.assertEquals("namingconvention", - resolve(NamingConvention.class)); - Assert.assertEquals("namingconvention", - resolve(NamingConventionView.class)); - } - - @Test - public void basic_naming_based_routes() - throws InvalidRouteConfigurationException { - setNavigationTargets(NamingConvention.class, Main.class); - - Assert.assertEquals(Main.class, - router.resolveNavigationTarget("/", Collections.emptyMap()) - .get().getNavigationTarget()); - - Assert.assertEquals( - NamingConvention.class, router - .resolveNavigationTarget("/namingconvention", - Collections.emptyMap()) - .get().getNavigationTarget()); - } - - @Test - public void customRoutePathProvider_naming_based_routes() - throws InvalidRouteConfigurationException { - router = new Router(new TestRouteRegistry(new RoutePathProvider() { - - @Override - public String getRoutePath(Class navigationTarget) { - if (navigationTarget.equals(NamingConvention.class)) { - return "bar"; - } - if (navigationTarget.equals(Main.class)) { - return "foo"; - } - return null; - } - })); - setNavigationTargets(NamingConvention.class, Main.class); - - Assert.assertEquals(Main.class, - router.resolveNavigationTarget("/foo", Collections.emptyMap()) - .get().getNavigationTarget()); - - Assert.assertEquals(NamingConvention.class, - router.resolveNavigationTarget("/bar", Collections.emptyMap()) - .get().getNavigationTarget()); - } - - @Test - public void basic_naming_based_routes_with_trailing_view() - throws InvalidRouteConfigurationException { - setNavigationTargets(NamingConventionView.class, MainView.class); - - Assert.assertEquals(MainView.class, - router.resolveNavigationTarget("/", Collections.emptyMap()) - .get().getNavigationTarget()); - - Assert.assertEquals( - NamingConventionView.class, router - .resolveNavigationTarget("/namingconvention", - Collections.emptyMap()) - .get().getNavigationTarget()); - } - - @Test - public void test_naming_based_routes_with_name_view() - throws InvalidRouteConfigurationException { - setNavigationTargets(View.class); - - Assert.assertEquals(View.class, - router.resolveNavigationTarget("/", Collections.emptyMap()) - .get().getNavigationTarget()); - } - - @Test - public void customRoutePathProvider_name_view() - throws InvalidRouteConfigurationException { - router = new Router(new TestRouteRegistry(new RoutePathProvider() { - - @Override - public String getRoutePath(Class navigationTarget) { - if (navigationTarget.equals(View.class)) { - return "foo"; - } - return null; - } - })); - - setNavigationTargets(View.class); - - Assert.assertEquals(View.class, - router.resolveNavigationTarget("/foo", Collections.emptyMap()) - .get().getNavigationTarget()); - } - - @Tag("div") - @Route("noParent") - @RouteAlias(value = "twoParents", layout = BaseLayout.class) - public static class AliasLayout extends Component { - - } - - @Test - public void alias_has_two_parents_even_if_route_doesnt() { - RouteConfiguration.forRegistry(router.getRegistry()) - .setAnnotatedRoute(AliasLayout.class); - - List> parents = router.getRegistry() - .getRouteLayouts("noParent", AliasLayout.class); - - Assert.assertTrue("Main route should have no parents.", - parents.isEmpty()); - - parents = router.getRegistry().getRouteLayouts("twoParents", - AliasLayout.class); - - Assert.assertEquals("Route alias should have two parents", 2, - parents.size()); - } - - @Test - public void verify_collisions_not_allowed_with_naming_convention() { - InvalidRouteConfigurationException exception = null; - try { - setNavigationTargets(NamingConvention.class, - NamingConventionView.class); - } catch (InvalidRouteConfigurationException e) { - exception = e; - } - Assert.assertNotNull( - "Routes with same navigation target should not be allowed", - exception); - } - - @Test - public void preserve_initial_ui_contents() - throws InvalidRouteConfigurationException { - setNavigationTargets(View.class); - - Element specialChild = new Element("div"); - ui.getElement().appendChild(specialChild); - - router.navigate(ui, new Location(""), NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals(ui.getElement(), specialChild.getParent()); - } - - @Test - public void noRemoveLayout_oldContentRetained() { - setNavigationTargets(NoRemoveContent1.class, NoRemoveContent2.class); - - ui.navigate(NoRemoveContent1.class); - NoRemoveLayout layout = (NoRemoveLayout) ui.getChildren().findFirst() - .get(); - - Assert.assertEquals(Arrays.asList(NoRemoveContent1.class), - layout.getChildren().map(Component::getClass) - .collect(Collectors.toList())); - - ui.navigate(NoRemoveContent2.class); - - Assert.assertEquals( - Arrays.asList(NoRemoveContent1.class, NoRemoveContent2.class), - layout.getChildren().map(Component::getClass) - .collect(Collectors.toList())); - } - - @Test // 5388 - public void layout_chain_is_included_in_before_events() { - setNavigationTargets(LoneRoute.class, RouteChildWithParameter.class); - - RouteChildWithParameter.events.clear(); - ui.navigate(RouteChildWithParameter.class, "foobar"); - - BeforeEnterEvent beforeEnterEvent = (BeforeEnterEvent) RouteChildWithParameter.events - .get(0); - Assert.assertEquals( - "There is not exactly one layout in the layout chain", 1, - beforeEnterEvent.getLayouts().size()); - Assert.assertTrue("RouteParent was not included in the layout chain", - beforeEnterEvent.getLayouts().contains(RouteParent.class)); - - RouteChildWithParameter.events.clear(); - ui.navigate(LoneRoute.class); - - BeforeLeaveEvent beforeLeaveEvent = (BeforeLeaveEvent) RouteChildWithParameter.events - .get(0); - Assert.assertEquals( - "There is not exactly one layout in the layout chain", 1, - beforeLeaveEvent.getLayouts().size()); - Assert.assertTrue("RouteParent was not included in the layout chain", - beforeLeaveEvent.getLayouts().contains(RouteParent.class)); - } - - @Test - public void optional_parameter_non_existing_route() - throws InvalidRouteConfigurationException { - OptionalParameter.events.clear(); - Mockito.when(configuration.isProductionMode()).thenReturn(false); - setNavigationTargets(OptionalParameter.class); - - String locationString = "optional/doesnotExist/parameter"; - router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - String exceptionText1 = String.format("Could not navigate to '%s'", - locationString); - - String exceptionText2 = String.format("Couldn't find route for '%s'", - locationString); - - String optionalTemplate = HasUrlParameterFormat.getTemplate("optional", - OptionalParameter.class); - - String exceptionText3 = "
  • " + optionalTemplate - + " (supports optional parameter)
  • "; - - assertExceptionComponent(RouteNotFoundError.class, exceptionText1, - exceptionText2, exceptionText3); - } - - @Test - public void without_optional_parameter() - throws InvalidRouteConfigurationException { - OptionalParameter.events.clear(); - Mockito.when(configuration.isProductionMode()).thenReturn(false); - setNavigationTargets(WithoutOptionalParameter.class); - - String locationString = "optional"; - router.navigate(ui, new Location(locationString), - NavigationTrigger.PROGRAMMATIC); - - String exceptionText1 = String.format("Could not navigate to '%s'", - locationString); - - String exceptionText2 = String - .format("Reason: Couldn't find route for '%s'", locationString); - - String template = HasUrlParameterFormat.getTemplate("optional", - WithoutOptionalParameter.class); - - String exceptionText3 = "
  • " + template - + " (requires parameter)
  • "; - - assertExceptionComponent(RouteNotFoundError.class, exceptionText1, - exceptionText2, exceptionText3); - } - - @Test // #4595 - public void reroute_and_forward_from_parent_layout() { - ProcessEventsBase.clear(); - - setNavigationTargets(SecurityDocument.class, SecurityLogin.class); - - // On init and beforeEnter, SecurityParent is invoked twice, since on - // the initial request it reroutes. - final List expectedInitially = Arrays.asList("SecurityParent", - "SecurityParent", "SecurityLogin"); - final List expected = Arrays.asList("SecurityParent", - "SecurityLogin"); - - // beforeEnter is going to reroute to login. - router.navigate(ui, new Location("security/document"), - NavigationTrigger.PROGRAMMATIC); - - assertEventOrder(expectedInitially, null, expectedInitially, expected); - - ProcessEventsBase.clear(); - - // beforeLeave is going to forward to same url. - router.navigate(ui, new Location("security/login"), - NavigationTrigger.PROGRAMMATIC); - - // Instances already exists from previous navigation, so expectedInit is - // null. - assertExistingChainEventOrder(expected); - } - - @Test // #4595 - public void event_listeners_are_invoked_starting_with_parent_component() - throws InvalidRouteConfigurationException { - ProcessEventsBase.clear(); - - setNavigationTargets(ProcessEventsFlower.class); - - router.navigate(ui, new Location("event/flower"), - NavigationTrigger.PROGRAMMATIC); - - assertInitialChainEventOrder( - getProcessEventsBranchChainNames("ProcessEventsFlower")); - } - - @Test // #4595 - public void event_listeners_are_invoked_starting_with_parent_component_when_preserved_on_refresh() - throws InvalidRouteConfigurationException { - ProcessEventsBase.clear(); - - // This is null by default. - ExtendedClientDetails previousClientDetails = ui.getInternals() - .getExtendedClientDetails(); - - // Used with PreserveOnRefresh. - ExtendedClientDetails clientDetails = Mockito - .mock(ExtendedClientDetails.class); - ui.getInternals().setExtendedClientDetails(clientDetails); - - Mockito.when(clientDetails.getWindowName()).thenReturn("mock"); - - setNavigationTargets(ProcessEventsFruit.class); - - router.navigate(ui, new Location("event/fruit"), - NavigationTrigger.PROGRAMMATIC); - - ProcessEventsBase.clear(); - - router.navigate(ui, new Location("event/fruit"), - NavigationTrigger.PROGRAMMATIC); - - assertExistingChainEventOrder( - getProcessEventsBranchChainNames("ProcessEventsFruit")); - - // Set back the previous client details. - ui.getInternals().setExtendedClientDetails(previousClientDetails); - } - - @Test // #4595 - public void parent_layouts_are_reused_when_change_url() - throws InvalidRouteConfigurationException { - ProcessEventsBase.clear(); - - setNavigationTargets(ProcessEventsFlower.class, - ProcessEventsLeaf.class); - - router.navigate(ui, new Location("event/flower"), - NavigationTrigger.PROGRAMMATIC); - - ProcessEventsBase.clear(); - - final String parameter = "green"; - router.navigate(ui, new Location("event/leaf/" + parameter), - NavigationTrigger.PROGRAMMATIC); - - assertEventOrder(Arrays.asList("ProcessEventsLeaf", "leafChild"), - getProcessEventsBranchChainNames("ProcessEventsFlower"), - getProcessEventsBranchChainNames(parameter, "ProcessEventsLeaf", - "leafChild"), - getProcessEventsBranchChainNames("ProcessEventsLeaf", - "leafChild")); - } - - @Test // #4595 - public void components_are_not_created_when_parent_layout_redirects() - throws InvalidRouteConfigurationException { - ProcessEventsBase.clear(); - - setNavigationTargets(ProcessEventsFlower.class, - ProcessEventsTwig.class); - - router.navigate(ui, new Location("event/twig"), - NavigationTrigger.PROGRAMMATIC); - - // This is expected after reroute. - final List expectedOnReroute = getProcessEventsBranchChainNames( - "ProcessEventsFlower"); - - // This is expected on init and BeforeEnter since the - // ProcessEventsRotten - // parent of ProcessEventsTwig will reroute, so ProcessEventsTwig and - // ProcessEventsStick won't be created. - final List expected = Stream - .concat(getProcessEventsTrunkChainNames("ProcessEventsRotten") - .stream(), expectedOnReroute.stream()) - .collect(Collectors.toList()); - assertEventOrder(expected, null, expected, expectedOnReroute); - } - - @Test // #4595 - public void url_parameter_is_invoked_right_before_enter_events() - throws InvalidRouteConfigurationException { - ProcessEventsBase.clear(); - - setNavigationTargets(ProcessEventsLeaf.class); - - final String parameter = "red"; - router.navigate(ui, new Location("event/leaf/" + parameter), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "BeforeEnter events aren't triggered in correct order", - getProcessEventsBranchChainNames(parameter, "ProcessEventsLeaf", - "leafChild"), - ProcessEventsBase.beforeEnter); - } - - @Test // #4595 - public void url_parameter_is_invoked_where_before_enter_is_not_observed() - throws InvalidRouteConfigurationException { - ProcessEventsBase.clear(); - - setNavigationTargets(ProcessEventsNeedle.class); - - final String parameter = "green"; - router.navigate(ui, new Location("event/needle/" + parameter), - NavigationTrigger.PROGRAMMATIC); - - Assert.assertEquals( - "BeforeEnter events aren't triggered in correct order", - getProcessEventsBranchChainNames(parameter, "needleChild"), - ProcessEventsBase.beforeEnter); - } - - @Test // #2740 #4213 - public void navigate_incorrectParameter_shouldNotBeResolved() { - setNavigationTargets(ChainLinkWithParameter.class, - TargetWithOptionalParameters.class, TargetWithParameter.class, - AnotherTargetWithParameter.class, - ChainLinkWithParameterAndTarget.class); - - assertRouteParameters("qwe/123/link", null); - - assertRouteParameters("link/qwe/123/456", null); - - assertRouteParameters("123/link/456/789/target/bar", null); - - assertRouteParameters( - "123/targetLink/456/789/chainLink/987/foo/a/b/c/d/e/f", null); - - assertRouteParameters("987/765/targetLink/chainLink/543", null); - } - - @Test // #2740 #4213 - public void navigateToChainLinkWithParameter_routeParametersAreExtractedCorrectly() { - setNavigationTargets(ChainLinkWithParameter.class); - - assertRouteParameters("qwe/link/123", - parameters("parentID", "qwe", "chainLinkID", "123")); - } - - @Test // #2740 #4213 - public void navigateToTargetWithOptionalParameters_routeParametersAreExtractedCorrectly() { - setNavigationTargets(TargetWithOptionalParameters.class); - - assertRouteParameters("qwe/link/123/456", parameters("parentID", "qwe", - "chainLinkID", "123", "optional", "456")); - assertRouteParameters("qwe/link/123/456/789", - parameters("parentID", "qwe", "chainLinkID", "123", "optional", - "456", "anotherOptional", "789")); - } - - @Test // #2740 #4213 - public void navigateToTargetWithParameter_routeParametersAreExtractedCorrectly() { - setNavigationTargets(TargetWithParameter.class); - - assertRouteParameters("123/link/456/target/789/bar", - parameters("parentID", "123", "chainLinkID", "456", - "targetChainLinkID", "789")); - } - - @Test // #2740 #4213 - public void navigateToAnotherTargetWithParameter_routeParametersAreExtractedCorrectly() { - setNavigationTargets(AnotherTargetWithParameter.class); - - assertRouteParameters( - "123/targetLink/456/chainLink/789/987/foo/a/b/c/d/e/f", - parameters("parentID", "123", "chainLinkID", "456", - "anotherTargetID", "789", "yetAnotherID", "987", - "varargsFoo", varargs("a", "b", "c", "d", "e", "f"))); - assertRouteParameters("abc/targetLink/def/chainLink/ghi/jkl/foo", - parameters("parentID", "abc", "chainLinkID", "def", - "anotherTargetID", "ghi", "yetAnotherID", "jkl")); - - assertRouteParameters("012/targetLink/chainLink/345/678/foo/1/2/3/4", - parameters("parentID", "012", "anotherTargetID", "345", - "yetAnotherID", "678", "varargsFoo", - varargs("1", "2", "3", "4"))); - assertRouteParameters("012/targetLink/chainLink/345/678/foo", - parameters("parentID", "012", "anotherTargetID", "345", - "yetAnotherID", "678")); - } - - @Test // #2740 #4213 - public void navigateToChainLinkWithParameterAndTarget_routeParametersAreExtractedCorrectly() { - setNavigationTargets(ChainLinkWithParameterAndTarget.class); - - assertRouteParameters("987/targetLink/765/chainLink/543", - parameters("parentID", "987", "chainLinkID", "765", - "targetChainLinkID", "543")); - assertRouteParameters("987/targetLink/chainLink/543", - parameters("parentID", "987", "targetChainLinkID", "543")); - } - - @Test // #2740 #4213 - public void navigateToParameterTypesView_routeParametersAreExtractedCorrectly() { - setNavigationTargets(ParameterTypesView.class); - - assertRouteParameters("param/types/123", parameters("intType", "123")); - - assertRouteParameters("param/types/thinking", - parameters("stringType", "thinking")); - - assertRouteParameters("param/types/1/am/thinking/of/U/and/I", - parameters("intType", "1", "stringType", "am", "varargs", - "thinking/of/U/and/I")); - Assert.assertEquals("Invalid varargs", - Arrays.asList("thinking", "of", "U", "and", "I"), - RouteParametersBase.parameters.getWildcard("varargs")); - - assertRouteParameters("param/types/12345678900/long", - parameters("intType", "12345678900", "stringType", "long")); - - assertRouteParameters("param/types/long/12345678900", null); - - assertRouteParameters("param/types/thinking/of/U/and/I", - parameters("stringType", "thinking", "varargs", "of/U/and/I")); - - assertRouteParameters("param/types/I/am/thinking", null); - } - - @Test // #2740 #4213 - public void navigateToParametersForumThreadView_routeParametersAreExtractedCorrectly() { - setNavigationTargets(ParametersForumThreadView.class); - - assertRouteParameters("forum/thread/123/456", - parameters("threadID", "123", "messageID", "456")); - assertRouteParameters("forum/thread/123/last", - parameters("threadID", "123")); - assertRouteParameters("forum/thread/123", - parameters("threadID", "123")); - assertRouteParameters("forum/thread/123/thread-name", - parameters("threadID", "123", "something", "thread-name")); - } - - @Test // #2740 #4213 - public void navigateToParametersApiView_routeParametersAreExtractedCorrectly() { - setNavigationTargets(ParametersApiView.class); - - // path is empty - assertRouteParameters("api", parameters()); - - // with path - assertRouteParameters("api/com/vaadin/client/package-summary.html", - parameters("path", varargs("com", "vaadin", "client", - "package-summary.html"))); - - // alias=framework, version is empty - assertRouteParameters( - "api/framework/com/vaadin/client/package-summary.html", - parameters("alias", "framework", "path", varargs("com", - "vaadin", "client", "package-summary.html"))); - - // alias=framework, version=8.9.4 - assertRouteParameters( - "api/framework/8.9.4/com/vaadin/client/package-summary.html", - parameters("alias", "framework", "version", "8.9.4", "path", - varargs("com", "vaadin", "client", - "package-summary.html"))); - - // groupId=com.vaadin, artifactId=vaadin-all, version is empty - assertRouteParameters( - "api/com.vaadin/vaadin-all/com/vaadin/client/package-summary.html", - parameters("groupId", "com.vaadin", "artifactId", "vaadin-all", - "path", varargs("com", "vaadin", "client", - "package-summary.html"))); - - // groupId=com.vaadin, artifactId=vaadin-all, version=8.9.4 - assertRouteParameters( - "api/com.vaadin/vaadin-all/8.9.4/com/vaadin/client/package-summary.html", - parameters("groupId", "com.vaadin", "version", "8.9.4", - "artifactId", "vaadin-all", "path", varargs("com", - "vaadin", "client", "package-summary.html"))); - } - - @Test // #2740 #4213 - public void navigateToDetailsView_routeParametersAreExtractedCorrectly() { - setNavigationTargets(DetailsView.class); - - assertRouteParameters("directory/component/url-parameter-mapping", - parameters("urlIdentifier", "url-parameter-mapping")); - assertRouteParameters( - "directory/component/url-parameter-mapping/discussions", - parameters("urlIdentifier", "url-parameter-mapping", - "tabIdentifier", "discussions")); - assertRouteParameters( - "directory/component/url-parameter-mapping/api/org/vaadin/flow/helper/HasAbsoluteUrlParameterMapping.html", - parameters("urlIdentifier", "url-parameter-mapping", - "tabIdentifier", "api", "apiPath", - varargs("org", "vaadin", "flow", "helper", - "HasAbsoluteUrlParameterMapping.html"))); - - assertRouteParameters( - "directory/component/url-parameter-mapping/1.0.0-alpha7/api/org/vaadin/flow/helper/HasAbsoluteUrlParameterMapping.html", - parameters("urlIdentifier", "url-parameter-mapping", - "versionIdentifier", "1.0.0-alpha7", "tabIdentifier", - "api", "apiPath", - varargs("org", "vaadin", "flow", "helper", - "HasAbsoluteUrlParameterMapping.html"))); - assertRouteParameters( - "directory/component/url-parameter-mapping/1.0.0-alpha7/discussions", - parameters("urlIdentifier", "url-parameter-mapping", - "versionIdentifier", "1.0.0-alpha7", "tabIdentifier", - "discussions")); - assertRouteParameters( - "directory/component/url-parameter-mapping/1.0.0-alpha7", - parameters("urlIdentifier", "url-parameter-mapping", - "versionIdentifier", "1.0.0-alpha7")); - - // Assert url failure - assertRouteParameters("directory/component", null); - } - - @Test // #2740 #4213 - public void navigateToParametersRegexView_routeParametersAreExtractedCorrectly() { - setNavigationTargets(ParametersRegexView.class); - - assertRouteParameters("param/123", parameters("regex", "123")); - assertRouteParameters("param/abc", null); - assertRouteParameters("param/-123", null); - - assertRouteParameters("param/123/edit", parameters("regex", "123")); - assertRouteParameters("param/abc/edit", null); - assertRouteParameters("param/-123/edit", null); - - assertRouteParameters("param", parameters()); - assertRouteParameters("param/edit", parameters()); - } - - @Test // #2740 #4213 - public void routes_withAlternateOptionalParameter_failToRegister() { - assertFailingRouteConfiguration(SearchView.class); - assertFailingRouteConfiguration(ShowAllView.class, - RedirectRouteParametersView.class); - assertFailingRouteConfiguration(RedirectRouteParametersView.class, - ShowAllView.class); - } - - @Test // #2740 #4213 - public void reroute_withRouteParameters_succeed() { - setNavigationTargets(RedirectRouteParametersView.class, - RedirectToView.class, RedirectWithRouteParametersView.class); - - assertRouteParametersRedirect(); - } - - @Test // #2740 #4213 - public void forward_withRouteParameters_succeed() { - RedirectRouteParametersView.doForward = true; - - setNavigationTargets(RedirectRouteParametersView.class, - RedirectToView.class, RedirectWithRouteParametersView.class); - - assertRouteParametersRedirect(); - } - - @Test // #2740 #4213 - public void reroute_withWrongRouteParameters_fails() { - setNavigationTargets(RedirectRouteParametersView.class, - RedirectToView.class, RedirectWithRouteParametersView.class); - - assertWrongRouteParametersRedirect(); - } - - @Test // #2740 #4213 - public void forward_withWrongRouteParameters_fails() { - RedirectRouteParametersView.doForward = true; - - setNavigationTargets(RedirectRouteParametersView.class, - RedirectToView.class, RedirectWithRouteParametersView.class); - - assertWrongRouteParametersRedirect(); - } - - @Test // #5173 - public void forward_fromSetParameters_withoutBeforeEnterObserver() { - ForwardSetParameterView.clear(); - - setNavigationTargets(ForwardSetParameterView.class, - ForwardSetParameterBackView.class); - - navigate("forward/setParameter/test"); - - Assert.assertFalse( - "afterNavigation must not be invoked after forwardTo in setParameter", - ForwardSetParameterView.afterNavigationInvoked); - Assert.assertTrue("forwardTo ForwardSetParameterBackView failed", - ForwardSetParameterView.backBeforeEnterInvoked); - } - - @Test - public void forwardToExternalUrl_preventsViewFromBeingCreated() { - setNavigationTargets(RedirectToExternalUrl.class); - ui.addBeforeEnterListener( - e -> e.forwardToUrl("https://external/enter")); - - navigate("forwardtourl"); - - Assert.assertEquals(0, RedirectToExternalUrl.instancesCreated.get()); - } - - @Test - public void forwardToExternalUrl_forwardsToUrl() { - String externalForwardUrl = "https://external/enter"; - setNavigationTargets(RedirectToExternalUrl.class); - ui.addBeforeEnterListener(e -> { - e.forwardToUrl(externalForwardUrl); - }); - - navigate("forwardtourl"); - long historyInvocations = ui.getInternals() - .dumpPendingJavaScriptInvocations().stream() - .filter(js -> js.getInvocation().getExpression() - .contains("window.open") - && ((String) js.getInvocation().getParameters().get(0)) - .contains(externalForwardUrl)) - .count(); - assertEquals(1, historyInvocations); - - } - - private void assertWrongRouteParametersRedirect() { - assertRouteParameters("show/wrong", null, null); - } - - private void assertRouteParametersRedirect() { - assertRouteParameters("show/all", parameters(), RedirectToView.class); - assertRouteParameters("show/some", parameters("text", "some"), - RedirectWithRouteParametersView.class); - assertRouteParameters("show", parameters(), - RedirectRouteParametersView.class); - assertRouteParameters("show/original", parameters("filter", "original"), - RedirectRouteParametersView.class); - } - - private void assertFailingRouteConfiguration( - Class... navigationTargets) { - try { - setNavigationTargets(navigationTargets); - Assert.fail("Route configuration should fail"); - } catch (InvalidRouteConfigurationException e) { - } - } - - private void assertRouteParameters(String url, RouteParameters parameters) { - assertRouteParameters(url, parameters, null); - } - - private void assertRouteParameters(String url, RouteParameters parameters, - Class target) { - RouteParametersBase.clear(); - - navigate(url); - - Assert.assertEquals("Incorrect parameters", parameters, - RouteParametersBase.parameters); - - if (target != null) { - Assert.assertEquals("Incorrect target", target, - RouteParametersBase.target); - } - } - - private List getProcessEventsTrunkChainNames(String... leaf) { - final List chainNames = new ArrayList<>( - Arrays.asList("ProcessEventsRoot", "rootChild1", "rootChild11", - "rootChild2", "ProcessEventsTrunk")); - - chainNames.addAll(Arrays.asList(leaf)); - - return chainNames; - } - - private List getProcessEventsBranchChainNames(String... leaf) { - final List chainNames = getProcessEventsTrunkChainNames( - "ProcessEventsBranch", "branchChild1", "branchChild2", - "branchChild21"); - - chainNames.addAll(Arrays.asList(leaf)); - - return chainNames; - } - - private void assertInitialChainEventOrder(List expected) { - assertEventOrder(expected, null, expected, expected); - } - - private void assertExistingChainEventOrder(List expected) { - assertEventOrder(null, expected, expected, expected); - } - - private void assertEventOrder(List expectedInit, - List expectedBeforeLeave, List expectedBeforeEnter, - List expectedAfterNavigation) { - - if (expectedInit == null) { - Assert.assertTrue("There should be no component initialization", - ProcessEventsBase.init.isEmpty()); - } else { - Assert.assertEquals( - "Component initialization is done in incorrect order", - expectedInit, ProcessEventsBase.init); - } - - if (expectedBeforeLeave == null) { - Assert.assertTrue("There should be no BeforeLeave events triggered", - ProcessEventsBase.beforeLeave.isEmpty()); - } else { - Assert.assertEquals( - "BeforeLeave events aren't triggered in correct order", - expectedBeforeLeave, ProcessEventsBase.beforeLeave); - } - - Assert.assertEquals( - "BeforeEnter events aren't triggered in correct order", - expectedBeforeEnter, ProcessEventsBase.beforeEnter); - - Assert.assertEquals( - "AfterNavigation events aren't triggered in correct order", - expectedAfterNavigation, ProcessEventsBase.afterNavigation); - } - - private void setNavigationTargets( - Class... navigationTargets) - throws InvalidRouteConfigurationException { - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(router.getRegistry()); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - Arrays.asList(navigationTargets) - .forEach(routeConfiguration::setAnnotatedRoute); - }); - } - - private void setErrorNavigationTargets( - Class... errorNavigationTargets) { - ((ApplicationRouteRegistry) router.getRegistry()) - .setErrorNavigationTargets( - new HashSet<>(Arrays.asList(errorNavigationTargets))); - } - - private Class getUIComponentClass() { - return getUIComponent().getClass(); - } - - private Component getUIComponent() { - return ComponentUtil.findParentComponent(ui.getElement().getChild(0)) - .get(); - } - - private void assertExceptionComponent(String exceptionText) { - assertExceptionComponent(InternalServerError.class, exceptionText); - } - - private void assertExceptionComponent(Class errorClass, - String... exceptionTexts) { - Optional visibleComponent = ui.getElement().getChild(0) - .getComponent(); - - Assert.assertTrue("No navigation component visible", - visibleComponent.isPresent()); - - Component routeNotFoundError = visibleComponent.get(); - Assert.assertEquals(errorClass, routeNotFoundError.getClass()); - String errorText = getErrorText(routeNotFoundError); - for (String exceptionText : exceptionTexts) { - Assert.assertTrue( - "Expected the error text to contain '" + exceptionText - + "', but it is '" + errorText + "'", - errorText.contains(exceptionText)); - } - } - - private String getErrorText(Component routeNotFoundError) { - if (routeNotFoundError.getClass() == RouteNotFoundError.class) { - Component errorContent = routeNotFoundError.getChildren() - .findFirst().get(); - Assert.assertEquals(Html.class, errorContent.getClass()); - return ((Html) errorContent).getInnerHtml().toString(); - } else { - return routeNotFoundError.getElement().getText(); - } - } - - private void navigate(String url) { - router.navigate(ui, new Location(url), NavigationTrigger.PROGRAMMATIC); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/RoutingTestBase.java b/flow-server/src/test/java/com/vaadin/flow/router/RoutingTestBase.java deleted file mode 100644 index 190ba4558e6..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/RoutingTestBase.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import org.junit.Before; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.tests.util.MockUI; - -public class RoutingTestBase { - - @Route("") - @Tag(Tag.DIV) - public static class RootNavigationTarget extends Component { - } - - @Route("foo") - @Tag(Tag.DIV) - public static class FooNavigationTarget extends Component { - } - - @Route("foo/bar") - @Tag(Tag.DIV) - public static class FooBarNavigationTarget extends Component { - } - - @Route("navigation-target-with-title") - @PageTitle("Custom Title") - @Tag(Tag.DIV) - public static class NavigationTargetWithTitle extends Component { - } - - @Route("greeting") - @PageTitle("Custom Title") - @Tag(Tag.DIV) - public static class GreetingNavigationTarget extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Route("greeting/other") - @PageTitle("Custom Title") - @Tag(Tag.DIV) - public static class OtherGreetingNavigationTarget extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - public static class RouterTestMockUI extends MockUI { - - public RouterTestMockUI(Router router) { - super(createMockSession(router)); - } - - private static VaadinSession createMockSession(Router router) { - MockVaadinServletService service = new MockVaadinServletService(); - service.setRouter(router); - return new MockVaadinSession(service); - } - - } - - public static class RouterTestUI extends UI { - - public RouterTestUI(Router router) { - super(); - - getInternals().setSession(createMockSession(router)); - } - - private static VaadinSession createMockSession(Router router) { - - VaadinSession session = Mockito.mock(VaadinSession.class); - VaadinService service = Mockito.mock(VaadinService.class); - - Mockito.when(session.getService()).thenReturn(service); - Mockito.when(service.getRouter()).thenReturn(router); - - return session; - } - - } - - protected Router router; - - @Before - public void init() throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - router = new Router(new TestRouteRegistry()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/TestRouteRegistry.java b/flow-server/src/test/java/com/vaadin/flow/router/TestRouteRegistry.java deleted file mode 100644 index 3445b279f6c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/TestRouteRegistry.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router; - -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; - -/** - * Route registry with a public constructor for testing purposes. - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class TestRouteRegistry extends ApplicationRouteRegistry { - /** - * Creates a new test route registry. - */ - public TestRouteRegistry() { - super(new MockVaadinContext(new DefaultRoutePathProvider())); - } - - public TestRouteRegistry(RoutePathProvider provider) { - super(new MockVaadinContext(provider)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/AbstractRouteRegistryTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/AbstractRouteRegistryTest.java deleted file mode 100644 index c61460a3bc9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/AbstractRouteRegistryTest.java +++ /dev/null @@ -1,898 +0,0 @@ -package com.vaadin.flow.router.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import com.vaadin.flow.router.BeforeEvent; -import com.vaadin.flow.router.HasUrlParameter; -import com.vaadin.flow.router.NotFoundException; -import com.vaadin.flow.router.OptionalParameter; -import com.vaadin.flow.router.RouteParameterRegex; -import com.vaadin.flow.router.WildcardParameter; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteBaseData; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.RoutesChangedEvent; -import com.vaadin.flow.shared.Registration; -import org.junit.rules.ExpectedException; - -public class AbstractRouteRegistryTest { - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - private AbstractRouteRegistry registry; - - @Before - public void init() { - registry = new TestAbstractRouteRegistry(); - } - - @Test - public void lockingConfiguration_configurationIsUpdatedOnlyAfterUnlock() { - CountDownLatch waitReaderThread = new CountDownLatch(1); - CountDownLatch waitUpdaterThread = new CountDownLatch(2); - - Thread readerThread = new Thread() { - @Override - public void run() { - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - registry.getRegisteredRoutes().isEmpty()); - - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - registry.getRegisteredRoutes().isEmpty()); - - waitReaderThread.countDown(); - } - }; - - readerThread.start(); - - registry.update(() -> { - registry.setRoute("", MyRoute.class, Collections.emptyList()); - registry.setRoute("path", Secondary.class, Collections.emptyList()); - }); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 2, registry.getRegisteredRoutes().size()); - } - - @Test - public void routeChangeListener_correctChangesAreReturned() { - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - registry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - registry.setRoute("", MyRoute.class, Collections.emptyList()); - - Assert.assertFalse("Added should contain data for one entry", - added.isEmpty()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - Assert.assertEquals(MyRoute.class, added.get(0).getNavigationTarget()); - Assert.assertEquals("", added.get(0).getUrl()); - Assert.assertEquals(Collections.emptyList(), - added.get(0).getParentLayouts()); - - registry.setRoute("home", Secondary.class, Collections.emptyList()); - - Assert.assertFalse("Added should contain data for one entry", - added.isEmpty()); - Assert.assertEquals("Only latest change should be available", 1, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - Assert.assertEquals(Secondary.class, - added.get(0).getNavigationTarget()); - Assert.assertEquals("home", added.get(0).getUrl()); - - registry.removeRoute("home"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertFalse("One route should have gotten removed", - removed.isEmpty()); - - Assert.assertEquals(Secondary.class, - removed.get(0).getNavigationTarget()); - Assert.assertEquals("The 'home' route should have been removed", "home", - removed.get(0).getUrl()); - } - - @Test - public void routeChangeListener_blockChangesAreGivenCorrectlyInEvent() { - registry.setRoute("", MyRoute.class, Collections.emptyList()); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - registry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - registry.update(() -> { - registry.removeRoute(""); - registry.setRoute("path", Secondary.class, Collections.emptyList()); - registry.setRoute("", MyRoute.class, - Collections.singletonList(MainLayout.class)); - }); - - Assert.assertFalse("", added.isEmpty()); - Assert.assertEquals("", 2, added.size()); - Assert.assertFalse("", removed.isEmpty()); - - for (RouteBaseData data : added) { - if (data.getUrl().equals("")) { - Assert.assertEquals("MyRoute should have been added", - MyRoute.class, data.getNavigationTarget()); - Assert.assertEquals( - "MyRoute should have been seen as a update as the parent layouts changed.", - MainLayout.class, data.getParentLayout()); - } else { - Assert.assertEquals("", Secondary.class, - data.getNavigationTarget()); - } - } - - Assert.assertEquals("MyRoute should have been both removed and added", - MyRoute.class, removed.get(0).getNavigationTarget()); - Assert.assertEquals("Removed version should not have a parent layout", - Collections.emptyList(), removed.get(0).getParentLayouts()); - } - - @Test - public void routeWithAliases_eventShowsCorrectlyAsRemoved() { - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - registry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - registry.update(() -> { - registry.setRoute("main", Secondary.class, Collections.emptyList()); - registry.setRoute("Alias1", Secondary.class, - Collections.emptyList()); - registry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - }); - - Assert.assertEquals( - "Main route and aliases should all be seen as added.", 3, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - registry.removeRoute("Alias2"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertEquals( - "Removing the alias route should be seen in the event", 1, - removed.size()); - } - - @Test - public void changeListenerAddedDuringUpdate_eventIsFiredForListener() { - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - registry.update(() -> { - registry.setRoute("main", Secondary.class, Collections.emptyList()); - registry.setRoute("Alias1", Secondary.class, - Collections.emptyList()); - - // Long running task was done here and another thread added a - // listener - registry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - registry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - }); - - Assert.assertEquals( - "Main route and aliases should all be seen as added.", 3, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - registry.removeRoute("Alias2"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertEquals( - "Removing the alias route should be seen in the event", 1, - removed.size()); - } - - @Test - public void removeChangeListener_noEventsAreFired() { - List events = new ArrayList<>(); - - Registration registration = registry - .addRoutesChangeListener(events::add); - - registry.setRoute("home", MyRoute.class, Collections.emptyList()); - - Assert.assertEquals("Event should have been fired for listener", 1, - events.size()); - - registration.remove(); - - registry.setRoute("away", MyRoute.class, Collections.emptyList()); - - Assert.assertEquals("No new event should have fired", 1, events.size()); - } - - @Test - public void routeChangedEvent_testRouteAddedAndRemoved() { - registry.setRoute("MyRoute1", MyRoute.class, Collections.emptyList()); - - registry.addRoutesChangeListener(event -> { - Assert.assertEquals("MyRoute2 and Alias2 must be added", 2, - event.getAddedRoutes().size()); - Assert.assertEquals("MyRoute1 must be deleted", 1, - event.getRemovedRoutes().size()); - - Assert.assertTrue("MyRoute2 must be added", - event.isRouteAdded(MyRoute.class)); - Assert.assertTrue("Alias2 must be added", - event.isRouteAdded(Secondary.class)); - Assert.assertTrue("MyRoute1 must be deleted", - event.isRouteRemoved(MyRoute.class)); - Assert.assertTrue("MyRoute2 must be added", - event.getAddedNavigationTargets().contains(MyRoute.class)); - Assert.assertTrue("Alias2 must be added", event - .getAddedNavigationTargets().contains(Secondary.class)); - Assert.assertTrue("MyRoute1 must be deleted", event - .getRemovedNavigationTargets().contains(MyRoute.class)); - }); - - registry.update(() -> { - registry.setRoute("MyRoute2", MyRoute.class, - Collections.emptyList()); - registry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - registry.removeRoute("MyRoute1"); - }); - } - - @Test - public void routeChangedEvent_testPathAddedAndRemoved() { - registry.setRoute("MyRoute1", MyRoute.class, Collections.emptyList()); - - registry.addRoutesChangeListener(event -> { - Assert.assertEquals("MyRoute2 and Alias2 must be added", 2, - event.getAddedRoutes().size()); - Assert.assertEquals("MyRoute1 must be deleted", 1, - event.getRemovedRoutes().size()); - - Assert.assertTrue("MyRoute2 must be added", - event.isPathAdded("MyRoute2")); - Assert.assertTrue("Alias2 must be added", - event.isPathAdded("Alias2")); - Assert.assertTrue("MyRoute1 must be deleted", - event.isPathRemoved("MyRoute1")); - Assert.assertTrue("MyRoute2 must be added", - event.getAddedURLs().contains("MyRoute2")); - Assert.assertTrue("Alias2 must be added", - event.getAddedURLs().contains("Alias2")); - Assert.assertTrue("MyRoute1 must be deleted", - event.getRemovedURLs().contains("MyRoute1")); - }); - - registry.update(() -> { - registry.setRoute("MyRoute2", MyRoute.class, - Collections.emptyList()); - registry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - registry.removeRoute("MyRoute1"); - }); - } - - /* Parameters tests */ - - @Test - public void only_normal_target_works_as_expected() { - addTarget(NormalRoute.class); - - Assert.assertEquals("NormalRoute should have been returned", - NormalRoute.class, getTarget()); - } - - @Test - public void only_has_url_target_works_as_expected() { - addTarget(HasUrlRoute.class); - - Assert.assertNull( - "No has url should have been returned without parameter", - getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - } - - @Test - public void only_optional_target_works_as_expected() { - addTarget(OptionalRoute.class); - - Assert.assertEquals( - "OptionalRoute should have been returned with no parameter", - OptionalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("OptionalRoute should have been returned", - OptionalRoute.class, getTarget(Arrays.asList("optional"))); - } - - @Test - public void only_wildcard_target_works_as_expected() { - addTarget(WildcardRoute.class); - - Assert.assertEquals( - "WildcardRoute should have been returned with no parameter", - WildcardRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals( - "WildcardRoute should have been returned for one parameter", - WildcardRoute.class, getTarget(Arrays.asList("wild"))); - - Assert.assertEquals( - "WildcardRoute should have been returned for multiple parameters", - WildcardRoute.class, - getTarget(Arrays.asList("wild", "card", "target"))); - } - - @Test - public void normal_and_has_url_work_together() { - addTarget(NormalRoute.class); - addTarget(HasUrlRoute.class); - - Assert.assertEquals("NormalRoute should have been returned", - NormalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - } - - @Test - public void has_url_and_normal_work_together() { - addTarget(HasUrlRoute.class); - addTarget(NormalRoute.class); - - Assert.assertEquals("NormalRoute should have been returned", - NormalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - } - - @Test - public void normal_and_wildcard_work_together() { - addTarget(NormalRoute.class); - addTarget(WildcardRoute.class); - - Assert.assertEquals("NormalRoute should have been returned", - NormalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("WildcardRoute should have been returned", - WildcardRoute.class, getTarget(Arrays.asList("parameter"))); - - Assert.assertEquals( - "WildcardRoute should have been returned for multiple parameters", - WildcardRoute.class, - getTarget(Arrays.asList("wild", "card", "target"))); - } - - @Test - public void wildcard_and_normal_work_together() { - addTarget(WildcardRoute.class); - addTarget(NormalRoute.class); - - Assert.assertEquals("NormalRoute should have been returned", - NormalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("WildcardRoute should have been returned", - WildcardRoute.class, getTarget(Arrays.asList("parameter"))); - - Assert.assertEquals( - "WildcardRoute should have been returned for multiple parameters", - WildcardRoute.class, - getTarget(Arrays.asList("wild", "card", "target"))); - } - - @Test - public void normal_and_has_url_and_wildcard_work_together() - throws InvalidRouteConfigurationException { - addTarget(NormalRoute.class); - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - - assertNormalHasUrlAndWildcard(); - } - - @Test - public void normal_and_wildcard_and_has_url_work_together() - throws InvalidRouteConfigurationException { - addTarget(NormalRoute.class); - addTarget(WildcardRoute.class); - addTarget(HasUrlRoute.class); - - assertNormalHasUrlAndWildcard(); - } - - @Test - public void wildcard_and_normal_and_has_url_work_together() - throws InvalidRouteConfigurationException { - addTarget(WildcardRoute.class); - addTarget(HasUrlRoute.class); - addTarget(NormalRoute.class); - - assertNormalHasUrlAndWildcard(); - } - - @Test - public void has_url_and_wildcard_and_normal_work_together() - throws InvalidRouteConfigurationException { - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - addTarget(NormalRoute.class); - - assertNormalHasUrlAndWildcard(); - } - - @Test - public void has_url_and_normal_and_wildcard_work_together() - throws InvalidRouteConfigurationException { - addTarget(HasUrlRoute.class); - addTarget(NormalRoute.class); - addTarget(WildcardRoute.class); - - assertNormalHasUrlAndWildcard(); - } - - private void assertNormalHasUrlAndWildcard() { - Assert.assertEquals("NormalRoute should have been returned", - NormalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - - Assert.assertEquals( - "WildcardRoute should have been returned for multiple parameters", - WildcardRoute.class, - getTarget(Arrays.asList("wild", "card", "target"))); - } - - @Test - public void has_url_and_optional_parameter_work_together() - throws InvalidRouteConfigurationException { - addTarget(HasUrlRoute.class); - addTarget(OptionalRoute.class); - - Assert.assertEquals("OptionalRoute should have been returned", - OptionalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - } - - @Test - public void has_url_and_wildcard_and_optional_parameter_work_together() - throws InvalidRouteConfigurationException { - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - addTarget(OptionalRoute.class); - - assertHasUrlOptionalAndWildcard(); - } - - @Test - public void optional_parameter_and_has_url_and_wildcard_work_together() - throws InvalidRouteConfigurationException { - addTarget(OptionalRoute.class); - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - - assertHasUrlOptionalAndWildcard(); - } - - @Test - public void optional_parameter_and_wildcard_and_has_url_work_together() - throws InvalidRouteConfigurationException { - addTarget(OptionalRoute.class); - addTarget(WildcardRoute.class); - addTarget(HasUrlRoute.class); - - assertHasUrlOptionalAndWildcard(); - } - - @Test - public void wildcard_and_has_url_and_optional_parameter_work_together() - throws InvalidRouteConfigurationException { - addTarget(WildcardRoute.class); - addTarget(HasUrlRoute.class); - addTarget(OptionalRoute.class); - - assertHasUrlOptionalAndWildcard(); - } - - @Test - public void wildcard_and_optional_parameter_and_has_url_work_together() - throws InvalidRouteConfigurationException { - addTarget(WildcardRoute.class); - addTarget(OptionalRoute.class); - addTarget(HasUrlRoute.class); - - assertHasUrlOptionalAndWildcard(); - } - - @Test - public void has_url_and_optional_parameter_and_wildcard_work_together() - throws InvalidRouteConfigurationException { - addTarget(HasUrlRoute.class); - addTarget(OptionalRoute.class); - addTarget(WildcardRoute.class); - - assertHasUrlOptionalAndWildcard(); - } - - private void assertHasUrlOptionalAndWildcard() { - Assert.assertEquals("OptionalRoute should have been returned", - OptionalRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - - Assert.assertEquals( - "WildcardRoute should have been returned for multiple parameters", - WildcardRoute.class, - getTarget(Arrays.asList("wild", "card", "target"))); - } - - @Test - public void has_url_and_wildcard_work_together() - throws InvalidRouteConfigurationException { - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - - assertHasUrlAndWildcard(); - } - - @Test - public void wildcard_and_has_url_work_together() - throws InvalidRouteConfigurationException { - addTarget(WildcardRoute.class); - addTarget(HasUrlRoute.class); - - assertHasUrlAndWildcard(); - } - - private void assertHasUrlAndWildcard() { - Assert.assertEquals("WildcardRoute should have been returned", - WildcardRoute.class, getTarget(new ArrayList<>())); - - Assert.assertEquals("HasUrlRoute should have been returned", - HasUrlRoute.class, getTarget(Arrays.asList("parameter"))); - - Assert.assertEquals( - "WildcardRoute should have been returned for multiple parameters", - WildcardRoute.class, - getTarget(Arrays.asList("wild", "card", "target"))); - } - - /* Test exception cases */ - - /* "normal" target registered first */ - @Test - public void multiple_normal_routes_throw_exception() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with the same route.", - NormalRoute.class.getName(), - SecondNormalRoute.class.getName())); - - addTarget(NormalRoute.class); - addTarget(SecondNormalRoute.class); - } - - @Test - public void normal_and_optional_throws_exception() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets '%s' and '%s' have the same path and '%s' has an OptionalParameter that will never be used as optional.", - NormalRoute.class.getName(), OptionalRoute.class.getName(), - OptionalRoute.class.getName())); - - addTarget(NormalRoute.class); - addTarget(OptionalRoute.class); - } - - /* Optional target registered first */ - - @Test - public void two_optionals_throw_exception() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with parameter have the same route.", - OptionalRoute.class.getName(), - SecondOptionalRoute.class.getName())); - - addTarget(OptionalRoute.class); - addTarget(SecondOptionalRoute.class); - } - - @Test - public void optional_and_normal_throws_exception() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets '%s' and '%s' have the same path and '%s' has an OptionalParameter that will never be used as optional.", - NormalRoute.class.getName(), OptionalRoute.class.getName(), - OptionalRoute.class.getName())); - - addTarget(OptionalRoute.class); - addTarget(NormalRoute.class); - } - - /* HasUrl parameter */ - @Test - public void two_has_route_parameters_throw_exception() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with parameter have the same route.", - HasUrlRoute.class.getName(), - SecondHasUrlRoute.class.getName())); - - addTarget(HasUrlRoute.class); - addTarget(SecondHasUrlRoute.class); - } - - /* Wildcard parameters */ - @Test - public void two_wildcard_parameters_throw_exception() - throws InvalidRouteConfigurationException { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage(String.format( - "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with parameter have the same route.", - WildcardRoute.class.getName(), - SecondWildcardRoute.class.getName())); - - addTarget(WildcardRoute.class); - addTarget(SecondWildcardRoute.class); - } - - @Test - public void removing_target_leaves_others() { - addTarget(NormalRoute.class); - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - - Assert.assertEquals("Expected three routes to be registered", 3, - config().getTargetRoutes().size()); - - registry.removeRoute(HasUrlRoute.class); - - Assert.assertEquals("Only 2 routes should remain after removing one.", - 2, config().getTargetRoutes().size()); - - Assert.assertTrue("NormalRoute should still be available", - config().hasRouteTarget(NormalRoute.class)); - Assert.assertTrue("WildcardRoute should still be available", - config().hasRouteTarget(WildcardRoute.class)); - } - - @Test - public void removing_all_targets_is_possible_and_returns_empty() { - addTarget(NormalRoute.class); - addTarget(HasUrlRoute.class); - addTarget(WildcardRoute.class); - - Assert.assertEquals("Expected three routes to be registered", 3, - config().getTargetRoutes().size()); - - registry.removeRoute(HasUrlRoute.class); - registry.removeRoute(NormalRoute.class); - registry.removeRoute(WildcardRoute.class); - - Assert.assertTrue( - "All routes should have been removed from the target.", - config().getTargetRoutes().isEmpty()); - } - - @Test - public void check_has_parameters_returns_correctly() { - registry.setRoute("", NormalRoute.class, null); - registry.setRoute("url", HasUrlRoute.class, null); - registry.setRoute("optional", OptionalRoute.class, null); - registry.setRoute("wild", WildcardRoute.class, null); - registry.setRoute( - ParameterView.class.getAnnotation(Route.class).value(), - ParameterView.class, null); - - Assert.assertEquals("All routes should be registered.", 5, - config().getTargetRoutes().size()); - - Assert.assertFalse( - "Normal route should not mark as requiring parameter", - registry.hasMandatoryParameter(NormalRoute.class)); - Assert.assertFalse( - "Optional parameter should not mark as requiring parameter", - registry.hasMandatoryParameter(OptionalRoute.class)); - Assert.assertFalse( - "Wildcard parameter should not mark as requiring parameter", - registry.hasMandatoryParameter(WildcardRoute.class)); - - Assert.assertTrue("HasUrl should require parameter", - registry.hasMandatoryParameter(HasUrlRoute.class)); - Assert.assertTrue("Template parameter should require parameter", - registry.hasMandatoryParameter(ParameterView.class)); - - Assert.assertThrows( - "Checking unregistered route should throw exception", - NotFoundException.class, - () -> registry.hasMandatoryParameter(Secondary.class)); - } - - /* Private stuff */ - - private void awaitCountDown(CountDownLatch countDownLatch) { - try { - countDownLatch.await(); - } catch (InterruptedException e) { - Assert.fail(); - } - } - - @Tag("div") - @Route("MyRoute") - private static class MyRoute extends Component { - } - - @Tag("div") - private static class Secondary extends Component { - } - - @Tag("div") - private static class MainLayout extends Component implements RouterLayout { - } - - @Route("") - @Tag(Tag.DIV) - private static class NormalRoute extends Component { - } - - @Route("") - @Tag(Tag.DIV) - private static class SecondNormalRoute extends Component { - } - - @Route("") - @Tag(Tag.DIV) - private static class HasUrlRoute extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Route("") - @Tag(Tag.DIV) - private static class SecondHasUrlRoute extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Route("") - @Tag(Tag.DIV) - private static class OptionalRoute extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, - @OptionalParameter String parameter) { - } - } - - @Route("") - @Tag(Tag.DIV) - private static class SecondOptionalRoute extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, - @OptionalParameter String parameter) { - } - } - - @Route("") - @Tag(Tag.DIV) - private static class WildcardRoute extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - } - } - - @Route("") - @Tag(Tag.DIV) - private static class SecondWildcardRoute extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, - @WildcardParameter String parameter) { - } - } - - @Route(value = "item/:long(" + RouteParameterRegex.LONG + ")") - @Tag("div") - private static class ParameterView extends Component { - } - - @Tag(Tag.DIV) - private static class Parent extends Component implements RouterLayout { - } - - private ConfiguredRoutes config() { - return registry.getConfiguration(); - } - - private void addTarget(Class navigationTarget) { - registry.setRoute("", navigationTarget, Collections.emptyList()); - } - - private void addTarget(Class navigationTarget, - List> parentChain) { - registry.setRoute("", navigationTarget, parentChain); - } - - private Class getTarget() { - return registry.getNavigationTarget("").orElse(null); - } - - private Class getTarget(String segment) { - return registry.getNavigationTarget(segment).orElse(null); - } - - private Class getTarget(List segments) { - return registry.getNavigationTarget(PathUtil.getPath(segments)) - .orElse(null); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/ConfigureRoutesTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/ConfigureRoutesTest.java deleted file mode 100644 index 757812fe934..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/ConfigureRoutesTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.vaadin.flow.router.internal; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.BeforeEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.HasUrlParameter; -import com.vaadin.flow.server.AmbiguousRouteConfigurationException; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class ConfigureRoutesTest { - - @Tag("div") - public static class BaseTarget extends Component { - } - - @Tag("div") - public static class ParamTarget extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Tag("div") - public static class BaseError extends Component - implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 0; - } - } - - @Rule - public ExpectedException exceptionRule = ExpectedException.none(); - - @Test - public void mutableConfiguration_canSetRouteTarget() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute("", BaseTarget.class); - - Assert.assertTrue("Configuration should have \"\" route registered", - mutable.hasTemplate("")); - Assert.assertEquals("Configuration should have registered base target.", - BaseTarget.class, mutable.getTarget("").get()); - } - - @Test - public void mutableConfiguration_canSetTargetRoute() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute("", BaseTarget.class); - - Assert.assertTrue("", mutable.hasRouteTarget(BaseTarget.class)); - - Assert.assertEquals("Configuration should have registered base target.", - "", mutable.getTemplate(BaseTarget.class)); - } - - @Test - public void mutableConfigurationClear_removesRegisteredRoutes() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - assertSetRoutes(mutable); - - mutable.clear(); - - Assert.assertFalse(mutable.hasRouteTarget(BaseTarget.class)); - Assert.assertFalse(mutable.hasRouteTarget(ParamTarget.class)); - - Assert.assertNull( - mutable.getNavigationRouteTarget("").getRouteTarget()); - Assert.assertNull( - mutable.getNavigationRouteTarget("123").getRouteTarget()); - - assertSetRoutes(mutable); - } - - @Test - public void mutableConfigurationClear_preservesErrorRoute() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setErrorRoute(IndexOutOfBoundsException.class, BaseError.class); - - mutable.clear(); - - Assert.assertEquals("ErrorRoute shouldn't be cleared.", BaseError.class, - mutable.getExceptionHandlerByClass( - IndexOutOfBoundsException.class)); - } - - @Test - public void duplicateRootPathRegistration_throwsException() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute("", BaseTarget.class); - Assert.assertTrue(mutable.hasRouteTarget(BaseTarget.class)); - Assert.assertEquals(BaseTarget.class, mutable - .getNavigationRouteTarget("").getRouteTarget().getTarget()); - - exceptionRule.expect(AmbiguousRouteConfigurationException.class); - exceptionRule.reportMissingExceptionWithMessage( - "Duplicate routes shouldn't be accepted."); - exceptionRule.expectMessage( - "Navigation targets must have unique routes, found navigation targets 'com.vaadin.flow.router.internal.ConfigureRoutesTest$BaseTarget' and 'com.vaadin.flow.router.internal.ConfigureRoutesTest$BaseTarget' with the same route."); - mutable.setRoute("", BaseTarget.class); - } - - @Test - public void duplicateParameterPathRegistration_throwsException() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute(":param", ParamTarget.class); - Assert.assertTrue(mutable.hasRouteTarget(ParamTarget.class)); - Assert.assertEquals(ParamTarget.class, mutable - .getNavigationRouteTarget("123").getRouteTarget().getTarget()); - - exceptionRule.expect(AmbiguousRouteConfigurationException.class); - exceptionRule.reportMissingExceptionWithMessage( - "Duplicate parameter routes shouldn't be accepted."); - exceptionRule.expectMessage( - "Navigation targets must have unique routes, found navigation targets 'com.vaadin.flow.router.internal.ConfigureRoutesTest$ParamTarget' and 'com.vaadin.flow.router.internal.ConfigureRoutesTest$ParamTarget' with parameter have the same route."); - mutable.setRoute(":param", ParamTarget.class); - } - - @Test - public void mutableConfiguration_makingImmutableHasCorrectData() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute("", BaseTarget.class); - - ConfiguredRoutes immutable = new ConfiguredRoutes(mutable); - - Assert.assertTrue("Configuration should have \"\" route registered", - immutable.hasTemplate("")); - Assert.assertEquals("Configuration should have registered base target.", - BaseTarget.class, immutable.getTarget("").get()); - - Assert.assertTrue("", immutable.hasRouteTarget(BaseTarget.class)); - Assert.assertEquals("Configuration should have registered base target.", - "", immutable.getTemplate(BaseTarget.class)); - } - - @Test - public void mutableConfiguration_canSetErrorTargets() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setErrorRoute(IndexOutOfBoundsException.class, BaseError.class); - - Assert.assertFalse("Exception targets should be available", - mutable.getExceptionHandlers().isEmpty()); - Assert.assertEquals("Given exception returned unexpected handler class", - BaseError.class, mutable.getExceptionHandlerByClass( - IndexOutOfBoundsException.class)); - } - - @Test - public void populatedMutableConfiguration_clearRemovesAllContent() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute("", BaseTarget.class); - - mutable.setErrorRoute(IndexOutOfBoundsException.class, BaseError.class); - - Assert.assertFalse("Configuration should have routes.", - mutable.getRoutes().isEmpty()); - Assert.assertFalse("Configuration should have exceptions.", - mutable.getExceptionHandlers().isEmpty()); - - mutable.clear(); - - Assert.assertTrue("After clear all routes should have been removed.", - mutable.getRoutes().isEmpty()); - Assert.assertTrue( - "After clear all targetRoutes should have been removed. ", - mutable.getTargetRoutes().isEmpty()); - Assert.assertFalse( - "After clear exception targets should still be available.", - mutable.getExceptionHandlers().isEmpty()); - } - - private void assertSetRoutes(ConfigureRoutes mutable) { - mutable.setRoute("", BaseTarget.class); - mutable.setRoute(":param", ParamTarget.class); - - Assert.assertTrue(mutable.hasRouteTarget(BaseTarget.class)); - Assert.assertTrue(mutable.hasRouteTarget(ParamTarget.class)); - - Assert.assertEquals(BaseTarget.class, mutable - .getNavigationRouteTarget("").getRouteTarget().getTarget()); - Assert.assertEquals(ParamTarget.class, mutable - .getNavigationRouteTarget("123").getRouteTarget().getTarget()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/ConfiguredRoutesTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/ConfiguredRoutesTest.java deleted file mode 100644 index 10eb12d6426..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/ConfiguredRoutesTest.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.vaadin.flow.router.internal; - -import java.util.Arrays; -import java.util.EnumSet; - -import com.vaadin.flow.router.RouteParameterFormatOption; -import com.vaadin.flow.router.RouteParameterRegex; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.RouterLayout; - -public class ConfiguredRoutesTest { - - @Test - public void emptyConfiguration_allGetMethodsWork() { - ConfiguredRoutes configuration = new ConfiguredRoutes(); - - Assert.assertFalse("No routes should be configured", - configuration.hasTemplate("")); - Assert.assertFalse("No routes should be configured", - configuration.getTarget("").isPresent()); - Assert.assertTrue("Configuration should be empty", - configuration.getRoutes().isEmpty()); - Assert.assertTrue("Configuration should be empty", - configuration.getTargetRoutes().isEmpty()); - Assert.assertNull("No exception handler should be found.", configuration - .getExceptionHandlerByClass(RuntimeException.class)); - Assert.assertNull("No target route should be found", - configuration.getTemplate(BaseTarget.class)); - Assert.assertTrue("Configuration should be empty", - configuration.getExceptionHandlers().isEmpty()); - Assert.assertFalse("No route should be found", - configuration.hasRouteTarget(BaseTarget.class)); - } - - @Test - public void mutableConfiguration_makingImmutableHasCorrectData() { - ConfigureRoutes mutable = new ConfigureRoutes(); - - mutable.setRoute("", BaseTarget.class, - Arrays.asList(SecondParentTarget.class, ParentTarget.class)); - - ConfiguredRoutes immutable = new ConfiguredRoutes(mutable); - - Assert.assertTrue("Configuration should have \"\" route registered", - immutable.hasTemplate("")); - Assert.assertEquals("Configuration should have registered base target.", - BaseTarget.class, immutable.getTarget("").get()); - - Assert.assertTrue( - "BaseTarget registration should have been copied over", - immutable.hasRouteTarget(BaseTarget.class)); - Assert.assertEquals("Configuration should have registered base target.", - "", immutable.getTemplate(BaseTarget.class)); - - Assert.assertEquals( - "Given parentLayouts should have been copied correctly", - Arrays.asList(SecondParentTarget.class, ParentTarget.class), - immutable.getParentLayouts("", BaseTarget.class)); - } - - @Test - public void configuration_provides_target_url() { - ConfigureRoutes edit = new ConfigureRoutes(); - edit.setRoute("foo/:foo", FooTarget.class); - edit.setRoute("foo/:foo(qwe)", FooTarget.class); - edit.setRoute("foo/:foo/bar?(asd)", FooTarget.class); - edit.setRoute(":foo/:bar?(asd)", FooTarget.class); - edit.setRoute("foo/:foo/:bar*(asd)", FooTarget.class); - edit.setRoute("foo/:foo(qwe)/:bar*(asd)", FooTarget.class); - edit.setRoute("foo/foobar?/:foo(qwe)/:bar*(asd)", FooTarget.class); - edit.setRoute("foo/foobar?/:foo(qwe)", FooTarget.class); - edit.setRoute("foo/foobar?/:foo", FooTarget.class); - - edit.setRoute("bar/:bar?", BarTarget.class); - edit.setRoute("bar/:bar?/foobar", BarTarget.class); - edit.setRoute("bar/:bar?(qwe)", BarTarget.class); - edit.setRoute("bar/:bar?(qwe)/:foo*(asd)", BarTarget.class); - edit.setRoute("bar/:bar?/:foo*", BarTarget.class); - edit.setRoute(":bar?/:foo*", BarTarget.class); - edit.setRoute(":bar?/foobar/:foo*", BarTarget.class); - - ConfiguredRoutes config = new ConfiguredRoutes(edit); - - Assert.assertNull(config.getTargetUrl(FooTarget.class)); - Assert.assertEquals("bar", config.getTargetUrl(BarTarget.class)); - - // Make sure all routes are passed. - config.getRouteModel().getRoutes().entrySet() - .forEach(stringRouteTargetEntry -> { - final boolean requiredParameter = RouteFormat - .hasRequiredParameter( - stringRouteTargetEntry.getKey()); - - Assert.assertEquals( - stringRouteTargetEntry.getValue().getTarget() - .equals(FooTarget.class), - requiredParameter); - }); - } - - @Test - public void configuration_provides_formatted_url_template() { - ConfigureRoutes config = new ConfigureRoutes(); - - final String template = "/path/to" + "/:intType(" - + RouteParameterRegex.INTEGER + ")" + "/:longType?(" - + RouteParameterRegex.LONG + ")" - + "/:stringType?/:varargs*(thinking|of|U|and|I)"; - config.setRoute(template, BaseTarget.class); - - Assert.assertFalse( - "Template should not contain prefixed forward slash '/'", - template.equals(config.getTemplate(BaseTarget.class))); - - Assert.assertEquals("Invalid template", template.substring(1), - config.getTemplate(BaseTarget.class)); - - Assert.assertEquals("Invalid formatted template", - "path/to/:intType(integer)/:longType?(long)/:stringType?(string)/:varargs*(string)", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.NAME, - RouteParameterFormatOption.MODIFIER, - RouteParameterFormatOption.REGEX_NAME))); - - Assert.assertEquals("Invalid formatted template", - "path/to/:intType/:longType?/:stringType?/:varargs*", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.NAME, - RouteParameterFormatOption.MODIFIER))); - - Assert.assertEquals("Invalid formatted template", - "path/to/:intType/:longType/:stringType/:varargs", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.NAME))); - - Assert.assertEquals("Invalid formatted template", - "path/to/:(integer)/:?(long)/:?(string)/:*(string)", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.MODIFIER, - RouteParameterFormatOption.REGEX_NAME))); - - Assert.assertEquals("Invalid formatted template", - "path/to/:(" + RouteParameterRegex.INTEGER + ")/:?(" - + RouteParameterRegex.LONG - + ")/:?/:*(thinking|of|U|and|I)", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.MODIFIER, - RouteParameterFormatOption.REGEX))); - - Assert.assertEquals("Invalid formatted template", - "path/to/:integer/:long/:string/:string", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.REGEX_NAME))); - - Assert.assertEquals("Invalid formatted template", "path/to/:/:?/:?/:*", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.MODIFIER))); - - Assert.assertEquals("Invalid formatted template", - "path/to/:" + RouteParameterRegex.INTEGER + "/:" - + RouteParameterRegex.LONG + "/:/:thinking|of|U|and|I", - config.getTemplate(BaseTarget.class, - EnumSet.of(RouteParameterFormatOption.REGEX))); - } - - @Tag("div") - public static class FooTarget extends Component { - } - - @Tag("div") - public static class BarTarget extends Component { - } - - @Tag("div") - public static class BaseTarget extends Component { - } - - @Tag("div") - public static class ParentTarget extends Component implements RouterLayout { - } - - @Tag("div") - public static class SecondParentTarget extends Component - implements RouterLayout { - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/ErrorStateRendererTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/ErrorStateRendererTest.java deleted file mode 100644 index 9d453dedb60..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/ErrorStateRendererTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router.internal; - -import java.util.Collections; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HasElement; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.BeforeEnterObserver; -import com.vaadin.flow.router.ErrorNavigationEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.NavigationEvent; -import com.vaadin.flow.router.NavigationState; -import com.vaadin.flow.router.NavigationStateBuilder; -import com.vaadin.flow.router.NavigationTrigger; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.internal.ErrorStateRenderer.ExceptionsTrace; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; -import com.vaadin.tests.util.MockDeploymentConfiguration; -import com.vaadin.tests.util.MockUI; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class ErrorStateRendererTest { - - /** - * This view reroutes to {@link InfiniteLoopErrorTarget} - */ - @Tag(Tag.A) - @Route("npe") - public static class InfiniteLoopNPEView extends Component - implements BeforeEnterObserver { - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.rerouteToError(NullPointerException.class); - } - } - - /** - * This layout forwards to {@link InfiniteLoopNPEView} - */ - @Tag(Tag.A) - public static class InfiniteLoopErrorLayout extends Component - implements RouterLayout, BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.forwardTo(InfiniteLoopNPEView.class); - } - - } - - /** - * This class has a parent layout which forwards to - * {@link InfiniteLoopNPEView} - */ - @Tag(Tag.A) - @ParentLayout(InfiniteLoopErrorLayout.class) - public static class InfiniteLoopErrorTarget extends Component - implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 500; - } - - } - - @Tag(Tag.A) - @Route("happy") - public static class HappyPathViewView extends Component { - } - - @Tag(Tag.A) - public static class HappyPathErrorLayout extends Component - implements RouterLayout, BeforeEnterObserver { - - @Override - public void beforeEnter(BeforeEnterEvent event) { - event.forwardTo(HappyPathViewView.class); - } - - } - - @Tag(Tag.A) - @ParentLayout(HappyPathErrorLayout.class) - public static class HappyPathErrorTarget extends Component - implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 500; - } - - } - - @Test(expected = ExceptionsTrace.class) - public void handle_openNPEErrorTarget_infiniteReroute_noStackOverflow_throws() { - UI ui = configureMocks(); - - NavigationState state = new NavigationStateBuilder( - ui.getInternals().getRouter()) - .withTarget(InfiniteLoopErrorTarget.class).build(); - ErrorStateRenderer renderer = new ErrorStateRenderer(state); - - RouteConfiguration - .forRegistry(ui.getInternals().getRouter().getRegistry()) - .setAnnotatedRoute(InfiniteLoopNPEView.class); - - ErrorParameter parameter = new ErrorParameter<>( - Exception.class, new NullPointerException()); - ErrorNavigationEvent event = new ErrorNavigationEvent( - ui.getInternals().getRouter(), new Location("error"), ui, - NavigationTrigger.CLIENT_SIDE, parameter); - // event should route to ErrorTarget whose layout forwards to NPEView - // which reroute to ErrorTarget and this is an infinite loop - renderer.handle(event); - } - - @Test(expected = ExceptionsTrace.class) - public void handle_openNPEView_infiniteReroute_noStackOverflow_throws() { - UI ui = configureMocks(); - - NavigationState state = new NavigationStateBuilder( - ui.getInternals().getRouter()) - .withTarget(InfiniteLoopNPEView.class).build(); - NavigationStateRenderer renderer = new NavigationStateRenderer(state); - - RouteConfiguration - .forRegistry(ui.getInternals().getRouter().getRegistry()) - .setAnnotatedRoute(InfiniteLoopNPEView.class); - ((ApplicationRouteRegistry) ui.getInternals().getRouter().getRegistry()) - .setErrorNavigationTargets( - Collections.singleton(InfiniteLoopErrorTarget.class)); - - NavigationEvent event = new NavigationEvent( - ui.getInternals().getRouter(), new Location("npe"), ui, - NavigationTrigger.CLIENT_SIDE); - // event should route to ErrorTarget whose layout forwards to NPEView - // which reroute to ErrorTarget and this is an infinite loop - renderer.handle(event); - - JsonObject routerLinkState = Json.createObject(); - routerLinkState.put("href", "router_link"); - routerLinkState.put("scrollPositionX", 0d); - routerLinkState.put("scrollPositionY", 0d); - - event = new NavigationEvent(ui.getInternals().getRouter(), - new Location("npe"), ui, NavigationTrigger.ROUTER_LINK, - routerLinkState, false); - // event should route to ErrorTarget whose layout forwards to NPEView - // which reroute to ErrorTarget and this is an infinite loop - renderer.handle(event); - } - - @Test - public void handle_errorViewLayoutForwardsToAView_viewIsNavigated() { - UI ui = configureMocks(); - - NavigationState state = new NavigationStateBuilder( - ui.getInternals().getRouter()) - .withTarget(HappyPathErrorTarget.class).build(); - ErrorStateRenderer renderer = new ErrorStateRenderer(state); - - RouteConfiguration - .forRegistry(ui.getInternals().getRouter().getRegistry()) - .setAnnotatedRoute(HappyPathViewView.class); - - ErrorParameter parameter = new ErrorParameter<>( - Exception.class, new NullPointerException()); - ErrorNavigationEvent event = new ErrorNavigationEvent( - ui.getInternals().getRouter(), new Location("error"), ui, - NavigationTrigger.CLIENT_SIDE, parameter); - Assert.assertEquals(200, renderer.handle(event)); - - List chain = ui.getInternals() - .getActiveRouterTargetsChain(); - Assert.assertEquals(1, chain.size()); - Assert.assertEquals(HappyPathViewView.class, chain.get(0).getClass()); - } - - private UI configureMocks() { - MockVaadinServletService service = new MockVaadinServletService() { - @Override - public VaadinContext getContext() { - return new MockVaadinContext(); - } - }; - - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - MockUI ui = new MockUI(session); - return ui; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/NavigationStateRendererTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/NavigationStateRendererTest.java deleted file mode 100644 index c71b312f5dd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/NavigationStateRendererTest.java +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router.internal; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HasElement; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.Text; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.ExtendedClientDetails; -import com.vaadin.flow.component.page.History; -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.Location; -import com.vaadin.flow.router.NavigationEvent; -import com.vaadin.flow.router.NavigationState; -import com.vaadin.flow.router.NavigationStateBuilder; -import com.vaadin.flow.router.NavigationTrigger; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.PreserveOnRefresh; -import com.vaadin.flow.router.QueryParameters; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.TestRouteRegistry; -import com.vaadin.flow.server.MockInstantiator; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.RouteRegistry; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; -import com.vaadin.tests.util.MockDeploymentConfiguration; -import com.vaadin.tests.util.MockUI; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonValue; - -@NotThreadSafe -public class NavigationStateRendererTest { - - @Route(value = "preserved") - @PreserveOnRefresh - private static class PreservedView extends Text { - PreservedView() { - super(""); - } - } - - @Route(value = "regular") - private static class RegularView extends Text { - RegularView() { - super(""); - } - } - - @Route(value = "preservedLayout") - @Tag("div") - private static class PreservedLayout extends Component - implements RouterLayout { - PreservedLayout() { - } - } - - @PreserveOnRefresh - @Route(value = "preservedNested", layout = PreservedLayout.class) - private static class PreservedNestedView extends Text { - PreservedNestedView() { - super(""); - } - } - - private Router router; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void init() { - RouteRegistry registry = ApplicationRouteRegistry - .getInstance(new MockVaadinContext()); - router = new Router(registry); - } - - @Test - public void getRouterLayoutForSingle() throws Exception { - NavigationStateRenderer childRenderer = new NavigationStateRenderer( - navigationStateFromTarget(RouteParentLayout.class)); - - List> routerLayoutTypes = childRenderer - .getRouterLayoutTypes(RouteParentLayout.class, router); - - Assert.assertEquals( - "Found layout even though RouteParentLayout doesn't have any parents.", - 0, routerLayoutTypes.size()); - } - - @Test - public void getRouterLayoutForSingleParent() throws Exception { - NavigationStateRenderer childRenderer = new NavigationStateRenderer( - navigationStateFromTarget(SingleView.class)); - RouteConfiguration.forRegistry(router.getRegistry()) - .setAnnotatedRoute(SingleView.class); - - List> routerLayoutTypes = childRenderer - .getRouterLayoutTypes(SingleView.class, router); - - Assert.assertEquals("Not all expected layouts were found", 1, - routerLayoutTypes.size()); - Assert.assertEquals("Wrong class found", RouteParentLayout.class, - routerLayoutTypes.get(0)); - } - - @Test - public void getRouterLayoutForMulipleLayers() throws Exception { - NavigationStateRenderer childRenderer = new NavigationStateRenderer( - navigationStateFromTarget(ChildConfiguration.class)); - RouteConfiguration.forRegistry(router.getRegistry()) - .setAnnotatedRoute(ChildConfiguration.class); - - List> routerLayoutTypes = childRenderer - .getRouterLayoutTypes(ChildConfiguration.class, router); - - Assert.assertEquals("Not all expected layouts were found", 2, - routerLayoutTypes.size()); - Assert.assertEquals("Wrong class found as first in array", - MiddleLayout.class, routerLayoutTypes.get(0)); - Assert.assertEquals("Wrong class found as second in array", - RouteParentLayout.class, routerLayoutTypes.get(1)); - } - - @Test - public void instantiatorUse() throws ServiceException { - - MockVaadinServletService service = new MockVaadinServletService(); - service.init(new MockInstantiator() { - @Override - public T createRouteTarget( - Class routeTargetType, NavigationEvent event) { - Assert.assertEquals(Component.class, routeTargetType); - return (T) new Text("foo"); - } - }); - MockUI ui = new MockUI(new MockVaadinSession(service)); - - NavigationEvent event = new NavigationEvent( - new Router(new TestRouteRegistry()), new Location(""), ui, - NavigationTrigger.PAGE_LOAD); - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(ChildConfiguration.class)); - - Component routeTarget = renderer.getRouteTarget(Component.class, event); - - Assert.assertEquals(Text.class, routeTarget.getClass()); - - UI.setCurrent(null); - } - - @Route("parent") - private static class RouteParentLayout extends Component - implements RouterLayout { - } - - @ParentLayout(RouteParentLayout.class) - private static class MiddleLayout extends Component - implements RouterLayout { - - } - - @Route(value = "child", layout = MiddleLayout.class) - private static class ChildConfiguration extends Component { - } - - @Route(value = "single", layout = RouteParentLayout.class) - private static class SingleView extends Component { - } - - @Test - public void handle_preserveOnRefreshAndWindowNameNotKnown_clientSideCallTriggered() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - - // given a NavigationStateRenderer mapping to PreservedView - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(PreservedView.class)); - - // given the session has a cache of something at this location - AbstractNavigationStateRenderer.setPreservedChain(session, "", - new Location("preserved"), - new ArrayList<>(Arrays.asList(Mockito.mock(Component.class)))); - - // given a UI that contain no window name with an instrumented Page - // that records JS invocations - AtomicBoolean jsInvoked = new AtomicBoolean(false); - MockUI ui = new MockUI(session) { - final Page page = new Page(this) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... params) { - jsInvoked.set(true); - return super.executeJs(expression, params); - } - }; - - @Override - public Page getPage() { - return page; - } - }; - - // when a navigation event reaches the renderer - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("preserved"), ui, NavigationTrigger.PAGE_LOAD)); - - // then client-side JS was invoked - Assert.assertTrue("Expected JS invocation", jsInvoked.get()); - } - - @Test - public void handle_preserveOnRefreshAndWindowNameKnown_componentIsCachedRetrievedAndFlushed() { - // 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 ui1 = new MockUI(session); - ExtendedClientDetails details = Mockito - .mock(ExtendedClientDetails.class); - Mockito.when(details.getWindowName()).thenReturn("ROOT.123"); - ui1.getInternals().setExtendedClientDetails(details); - - // given a NavigationStateRenderer mapping to PreservedView - NavigationStateRenderer renderer1 = new NavigationStateRenderer( - navigationStateFromTarget(PreservedView.class)); - - // when a navigation event reaches the renderer - renderer1.handle(new NavigationEvent( - new Router(new TestRouteRegistry()), new Location("preserved"), - ui1, 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 Component view = (Component) ui1.getInternals() - .getActiveRouterTargetsChain().get(0); - - // given a new UI with the same window name - MockUI ui2 = new MockUI(session); - ui2.getInternals().setExtendedClientDetails(details); - - // given a new NavigationStateRenderer mapping to PreservedView - NavigationStateRenderer renderer2 = new NavigationStateRenderer( - navigationStateFromTarget(PreservedView.class)); - - // when another navigation targets the same location - renderer2.handle(new NavigationEvent( - new Router(new TestRouteRegistry()), new Location("preserved"), - ui2, NavigationTrigger.PAGE_LOAD)); - - // then the same view is routed to - Assert.assertEquals("Expected same view", view, - ui1.getInternals().getActiveRouterTargetsChain().get(0)); - - // given yet another new UI with the same window name - MockUI ui3 = new MockUI(session); - ui3.getInternals().setExtendedClientDetails(details); - - // given a new NavigationStateRenderer mapping to another location - NavigationStateRenderer renderer3 = new NavigationStateRenderer( - navigationStateFromTarget(RegularView.class)); - - // when a navigation event targets that other location - renderer3.handle(new NavigationEvent( - new Router(new TestRouteRegistry()), new Location("regular"), - ui2, NavigationTrigger.PAGE_LOAD)); - - // then session no longer has a cached record at location "preserved" - Assert.assertFalse("Session expected to not have cached view", - AbstractNavigationStateRenderer.hasPreservedChainOfLocation( - session, new Location("preserved"))); - } - - @Test - public void handle_preserveOnRefresh_otherUIChildrenAreMoved() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - // given a NavigationStateRenderer mapping to PreservedView - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(PreservedView.class)); - - // given the session has a cache of PreservedView at this location - final PreservedView view = new PreservedView(); - AbstractNavigationStateRenderer.setPreservedChain(session, "ROOT.123", - new Location("preserved"), - new ArrayList<>(Arrays.asList(view))); - - // given an old UI that contains the component and an extra element - MockUI ui0 = new MockUI(session); - ui0.add(view); - final Element otherElement = new Element("div"); - ui0.getElement().insertChild(1, otherElement); - - // given a new UI after a refresh with the same window name - MockUI ui1 = new MockUI(session); - ExtendedClientDetails details = Mockito - .mock(ExtendedClientDetails.class); - Mockito.when(details.getWindowName()).thenReturn("ROOT.123"); - ui1.getInternals().setExtendedClientDetails(details); - - // when a navigation event reaches the renderer - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("preserved"), ui1, NavigationTrigger.PAGE_LOAD)); - - // then both the view element and the other element are expected to be - // transferred from the previous UI to the new UI - final Set uiChildren = ui1.getElement().getChildren() - .collect(Collectors.toSet()); - Assert.assertEquals(2, uiChildren.size()); - Assert.assertTrue("Component element expected transferred", - uiChildren.contains(view.getElement())); - Assert.assertTrue("Extra element expected transferred", - uiChildren.contains(otherElement)); - } - - @Test - public void handle_preserveOnRefreshView_routerLayoutIsPreserved_oldUiIsClosed() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - // given a NavigationStateRenderer mapping to PreservedNestedView - Router router = session.getService().getRouter(); - NavigationStateRenderer renderer = new NavigationStateRenderer( - new NavigationStateBuilder(router) - .withTarget(PreservedNestedView.class) - .withPath("preservedNested").build()); - router.getRegistry().setRoute("preservedNested", - PreservedNestedView.class, - Arrays.asList(PreservedLayout.class)); - - // given the session has a cache of PreservedNestedView at this location - final PreservedLayout layout = new PreservedLayout(); - final PreservedNestedView nestedView = new PreservedNestedView(); - - MockUI previousUi = new MockUI(session); - previousUi.add(nestedView); - - AbstractNavigationStateRenderer.setPreservedChain(session, "ROOT.123", - new Location("preservedNested"), - new ArrayList<>(Arrays.asList(nestedView, layout))); - - // 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); - - // when a navigation event reaches the renderer - renderer.handle( - new NavigationEvent(router, new Location("preservedNested"), ui, - NavigationTrigger.PAGE_LOAD)); - - // then the view and the router layout are preserved - Assert.assertEquals("Expected same view", nestedView, - ui.getInternals().getActiveRouterTargetsChain().get(0)); - Assert.assertEquals("Expected same router layout", layout, - ui.getInternals().getActiveRouterTargetsChain().get(1)); - - Assert.assertTrue(previousUi.isClosing()); - } - - @Test - public void handle_preserveOnRefresh_sameUI_uiIsNotClosed_childrenAreNotRemoved() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - - // the path is the same, location params will be different - String path = "foo"; - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - // given a NavigationStateRenderer mapping to PreservedView - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(PreservedView.class)); - - // given the session has a cache of PreservedView at this location - final PreservedView view = new PreservedView(); - MockUI ui = new MockUI(session); - - ui.add(view); - - AbstractNavigationStateRenderer.setPreservedChain(session, "ROOT.123", - new Location(path, - new QueryParameters(Collections.singletonMap("a", - Collections.emptyList()))), - new ArrayList<>(Arrays.asList(view))); - - ExtendedClientDetails details = Mockito - .mock(ExtendedClientDetails.class); - Mockito.when(details.getWindowName()).thenReturn("ROOT.123"); - ui.getInternals().setExtendedClientDetails(details); - - AtomicInteger count = new AtomicInteger(); - - view.addDetachListener(event -> count.getAndIncrement()); - - NavigationEvent event = new NavigationEvent( - new Router(new TestRouteRegistry()), - new Location(path, - new QueryParameters(Collections.singletonMap("b", - Collections.emptyList()))), - ui, NavigationTrigger.ROUTER_LINK, Json.createObject(), false); - renderer.handle(event); - - Assert.assertFalse(ui.isClosing()); - Assert.assertEquals(0, count.get()); - } - - private MockVaadinServletService createMockServiceWithInstantiator() { - MockVaadinServletService service = new MockVaadinServletService(); - service.init(new MockInstantiator() { - @Override - public T createRouteTarget( - Class routeTargetType, NavigationEvent event) { - try { - return routeTargetType.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - }); - return service; - } - - private NavigationState navigationStateFromTarget( - Class target) { - return new NavigationStateBuilder(router).withTarget(target).build(); - } - - @Test - public void handle_RouterLinkTrigger_scrollPositionHandlerAfterServerNavigationIsInvoked() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - // given a NavigationStateRenderer mapping to RegularView - new NavigationStateBuilder(router).withTarget(RegularView.class) - .build(); - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(RegularView.class)); - - // given a UI with an instrumented Page that records JS invocations - AtomicBoolean jsInvoked = new AtomicBoolean(false); - List jsExpressions = new ArrayList<>(); - MockUI ui = new MockUI(session) { - final Page page = new Page(this) { - @Override - public PendingJavaScriptResult executeJs(String expression, - Serializable... params) { - jsInvoked.set(true); - jsExpressions.add(expression); - return super.executeJs(expression, params); - } - }; - - @Override - public Page getPage() { - return page; - } - }; - - JsonObject state = Json.createObject(); - state.put("href", "view/regular"); - state.put("scrollPositionX", 0.0); - state.put("scrollPositionY", 0.0); - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("preserved"), ui, NavigationTrigger.ROUTER_LINK, - state, false)); - - // then client-side JS was invoked - Assert.assertTrue("Expected JS invocation", jsInvoked.get()); - Assert.assertTrue(jsExpressions.stream() - .anyMatch(expression -> expression.contains( - "scrollPositionHandlerAfterServerNavigation"))); - } - - @Test - public void handle_RouterLinkTriggerNullState_IllegalStateException() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - service.setRouter(router); - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - // given a NavigationStateRenderer mapping to RegularView - new NavigationStateBuilder(router).withTarget(RegularView.class) - .build(); - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(RegularView.class)); - - MockUI ui = new MockUI(session); - - expectedException.expect(IllegalStateException.class); - renderer.handle(new NavigationEvent(router, new Location("regular"), ui, - NavigationTrigger.ROUTER_LINK, null, false)); - } - - @Test - // In any of the following criteria, pushState shouldn't be invoked: - // - forwardTo is true - // - the navigation location is the same as the current location (repeated - // navigation) - // - navigation trigger is PAGE_LOAD, HISTORY, or PROGRAMMATIC - public void handle_variousInputs_checkPushStateShouldBeCalledOrNot() { - // given a service with instantiator - MockVaadinServletService service = createMockServiceWithInstantiator(); - - // given a locked session - MockVaadinSession session = new AlwaysLockedVaadinSession(service); - session.setConfiguration(new MockDeploymentConfiguration()); - - // given a NavigationStateRenderer mapping to RegularView - new NavigationStateBuilder(router).withTarget(RegularView.class) - .build(); - NavigationStateRenderer renderer = new NavigationStateRenderer( - navigationStateFromTarget(RegularView.class)); - - // given a UI with an instrumented Page that records - // getHistory().pushState calls - AtomicBoolean pushStateCalled = new AtomicBoolean(false); - List pushStateLocations = new ArrayList<>(); - MockUI ui = new MockUI(session) { - final Page page = new Page(this) { - final History history = new History(getUI().get()) { - @Override - public void pushState(JsonValue state, Location location) { - pushStateCalled.set(true); - pushStateLocations.add(location); - } - }; - - @Override - public History getHistory() { - return history; - } - }; - - @Override - public Page getPage() { - return page; - } - }; - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("regular"), ui, NavigationTrigger.UI_NAVIGATE, - null, true)); - Assert.assertFalse( - "No pushState invocation is expected when forwardTo is true.", - pushStateCalled.get()); - - ui.getInternals().clearLastHandledNavigation(); - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("regular"), ui, NavigationTrigger.PROGRAMMATIC)); - Assert.assertFalse( - "No pushState invocation is expected when navigation trigger is PROGRAMMATIC.", - pushStateCalled.get()); - - ui.getInternals().clearLastHandledNavigation(); - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("regular"), ui, NavigationTrigger.HISTORY)); - Assert.assertFalse( - "No pushState invocation is expected when navigation trigger is HISTORY.", - pushStateCalled.get()); - - ui.getInternals().clearLastHandledNavigation(); - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("regular"), ui, NavigationTrigger.PAGE_LOAD)); - Assert.assertFalse( - "No pushState invocation is expected when navigation trigger is PAGE_LOAD.", - pushStateCalled.get()); - - pushStateCalled.set(false); - pushStateLocations.clear(); - ui.getInternals().clearLastHandledNavigation(); - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("regular"), ui, NavigationTrigger.UI_NAVIGATE)); - Assert.assertTrue("pushState invocation is expected.", - pushStateCalled.get()); - Assert.assertTrue(pushStateLocations.stream() - .anyMatch(location -> location.getPath().equals("regular"))); - - pushStateCalled.set(false); - - renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()), - new Location("regular"), ui, NavigationTrigger.UI_NAVIGATE)); - Assert.assertFalse( - "No pushState invocation is expected when navigating to the current location.", - pushStateCalled.get()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/PathUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/PathUtilTest.java deleted file mode 100644 index 8c3b281097c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/PathUtilTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router.internal; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -public class PathUtilTest { - - @Test - public void methods_output_expected_values() { - final List segments = Arrays.asList("path", "to", "foo"); - final String path = "path/to/foo"; - - Assert.assertEquals("Unexpected result", path, - PathUtil.getPath(segments)); - Assert.assertEquals("Unexpected result", "", PathUtil.getPath(null)); - Assert.assertEquals("Unexpected result", "", - PathUtil.getPath(Collections.emptyList())); - - Assert.assertEquals("Unexpected result", "prefix/" + path, - PathUtil.getPath("prefix", segments)); - Assert.assertEquals("Unexpected result", path, - PathUtil.getPath("", segments)); - Assert.assertEquals("Unexpected result", path, - PathUtil.getPath(null, segments)); - - Assert.assertEquals("Unexpected result", segments, - PathUtil.getSegmentsList(path)); - Assert.assertEquals("Unexpected result", segments, - PathUtil.getSegmentsList(path + "/")); - - List emptyStartSegment = new ArrayList<>(); - emptyStartSegment.add(""); - emptyStartSegment.addAll(segments); - Assert.assertEquals("Unexpected result", emptyStartSegment, - PathUtil.getSegmentsList("/" + path)); - Assert.assertEquals("Unexpected result", emptyStartSegment, - PathUtil.getSegmentsList("/" + path + "/")); - - Assert.assertEquals("Unexpected result", path, PathUtil.trimPath(path)); - Assert.assertEquals("Unexpected result", path, - PathUtil.trimPath("/" + path)); - Assert.assertEquals("Unexpected result", path, - PathUtil.trimPath(path + "/")); - Assert.assertEquals("Unexpected result", path, - PathUtil.trimPath("/" + path + "/")); - - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/RouteModelTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/RouteModelTest.java deleted file mode 100644 index 231f9f6acdf..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/RouteModelTest.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.router.internal; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.RouteParameterData; -import com.vaadin.flow.router.RouteParameterFormatOption; -import com.vaadin.flow.router.RouteParameterRegex; -import com.vaadin.flow.router.RouteParameters; -import org.junit.Assert; -import org.junit.Test; - -public class RouteModelTest { - - private RouteModel getRouteModel() { - RouteModel root = RouteModel.create(true); - root.addRoute("", routeTarget(Root.class)); - root.addRoute("trunk", routeTarget(Trunk.class)); - root.addRoute("trunk/branch", routeTarget(Branch.class)); - root.addRoute("trunk/branch/:id(" + RouteParameterRegex.INTEGER + ")", - routeTarget(Branch.class)); - root.addRoute( - "trunk/branch/:id(" + RouteParameterRegex.INTEGER + ")/:list*(" - + RouteParameterRegex.LONG + ")", - routeTarget(BranchChildren.class)); - root.addRoute("trunk/:name?/:type?/branch/:id?(" - + RouteParameterRegex.INTEGER + ")/edit", - routeTarget(BranchEdit.class)); - root.addRoute("trunk/:name/:type?/branch/:id(" - + RouteParameterRegex.INTEGER + ")/flower/:open(" - + RouteParameterRegex.LONG + ")/edit", - routeTarget(FlowerEdit.class)); - root.addRoute("trunk/twig/:leafs*", routeTarget(Twig.class)); - return root; - } - - @Test - public void route_model_provides_navigation_route_target() { - - RouteModel root = getRouteModel(); - - assertNavigation(root, "trunk/twig", Twig.class, parameters()); - - assertNavigation(root, "trunk/twig/a/b/c", Twig.class, - parameters("leafs", varargs("a", "b", "c"))); - - assertNavigation(root, "", Root.class, parameters()); - - assertNavigation(root, "trunk", Trunk.class, parameters()); - - assertNavigation(root, "trunk/branch", Branch.class, parameters()); - - assertNavigation(root, "trunk/branch/12", Branch.class, - parameters("id", "12")); - - assertNavigation(root, "trunk/branch/12/1/2/3/4/5/6/7", - BranchChildren.class, parameters("id", "12", "list", - varargs("1", "2", "3", "4", "5", "6", "7"))); - - assertNavigation(root, "trunk/branch/view", null, null); - - assertNavigation(root, "trunk/branch/edit", BranchEdit.class, - parameters()); - - assertNavigation(root, "trunk/red/branch/12/edit", BranchEdit.class, - parameters("id", "12", "name", "red")); - - assertNavigation(root, "trunk/branch/12/edit", BranchEdit.class, - parameters("id", "12")); - - assertNavigation(root, "trunk/red/birch/branch/12/edit", - BranchEdit.class, - parameters("id", "12", "name", "red", "type", "birch")); - - assertNavigation(root, "trunk/red/branch/12/flower/1234567890/edit", - FlowerEdit.class, - parameters("id", "12", "name", "red", "open", "1234567890")); - - assertNavigation(root, "trunk/red/branch/12/flower/edit", null, null); - - } - - @Test - public void varargs_url_parameter_defined_only_as_last_segment() { - RouteModel root = RouteModel.create(true); - try { - root.addRoute("trunk/:vararg*/edit", routeTarget(Root.class)); - - Assert.fail( - "Varargs url parameter accepted in the middle of the path."); - } catch (IllegalArgumentException e) { - } - - root.addRoute("trunk/edit/:vararg*", routeTarget(Root.class)); - - String path = "trunk/edit/1/2/3"; - assertNavigation(root, path, Root.class, - parameters("vararg", varargs("1", "2", "3"))); - } - - @Test - public void remove_route_target_not_found() { - RouteModel root = getRouteModel(); - - assertNavigation(root, "trunk/branch/12", Branch.class, - parameters("id", "12")); - - root.removeRoute( - "trunk/branch/:id(" + RouteParameterRegex.INTEGER + ")"); - - assertNavigation(root, "trunk/branch/12", BranchChildren.class, - parameters("id", "12")); - - root.removeRoute("trunk/branch/:id(" + RouteParameterRegex.INTEGER - + ")/:list*(" + RouteParameterRegex.LONG + ")"); - - assertNavigation(root, "trunk/branch/12", null, null); - } - - @Test - public void remove_route_url_not_found() { - RouteModel root = getRouteModel(); - - final String expectedUrl = "trunk/branch/12"; - final String template = "trunk/branch/:id(" - + RouteParameterRegex.INTEGER + ")"; - final RouteParameters parameters = parameters("id", "12"); - - assertUrl(root, expectedUrl, template, parameters); - - root.removeRoute(template); - - try { - assertUrl(root, expectedUrl, template, parameters); - Assert.fail("Route was just removed."); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void route_model_provides_route_target() { - RouteModel root = getRouteModel(); - - final String template = "trunk/branch/:id(" - + RouteParameterRegex.INTEGER + ")"; - final RouteParameters parameters = parameters("id", "12"); - - assertRoute(root, Branch.class, template, parameters); - - root.removeRoute(template); - - try { - root.getRouteTarget(template, parameters); - Assert.fail("Route was just removed."); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void route_model_provides_url_template_format() { - RouteModel root = getRouteModel(); - - final String template = "trunk/branch/:id(" - + RouteParameterRegex.INTEGER + ")/:list*(" - + RouteParameterRegex.LONG + ")"; - - Assert.assertEquals(template, - root.formatTemplate(template, - EnumSet.of(RouteParameterFormatOption.NAME, - RouteParameterFormatOption.REGEX, - RouteParameterFormatOption.MODIFIER))); - - Assert.assertEquals("trunk/branch/:id(integer)/:list*(long)", - root.formatTemplate(template, - EnumSet.of(RouteParameterFormatOption.NAME, - RouteParameterFormatOption.REGEX_NAME, - RouteParameterFormatOption.MODIFIER))); - - Assert.assertEquals("trunk/branch/:id(integer)/:list(long)", - root.formatTemplate(template, - EnumSet.of(RouteParameterFormatOption.NAME, - RouteParameterFormatOption.REGEX_NAME))); - - Assert.assertEquals("trunk/branch/:id/:list*", - root.formatTemplate(template, - EnumSet.of(RouteParameterFormatOption.NAME, - RouteParameterFormatOption.MODIFIER))); - - Assert.assertEquals("trunk/branch/:integer/:long", root.formatTemplate( - template, EnumSet.of(RouteParameterFormatOption.REGEX_NAME))); - } - - @Test - public void route_model_provides_parameters() { - RouteModel root = getRouteModel(); - - final String template = "trunk/branch/:id(" - + RouteParameterRegex.INTEGER + ")/:list*(" - + RouteParameterRegex.LONG + ")"; - - final Map parameters = root - .getParameters(template); - - Assert.assertEquals("Incorrect parameters size", 2, parameters.size()); - - Assert.assertTrue("Missing parameter", parameters.containsKey("id")); - Assert.assertTrue("Missing parameter", parameters.containsKey("list")); - - Assert.assertEquals("Wrong parameter data", - ":id(" + RouteParameterRegex.INTEGER + ")", - parameters.get("id").getTemplate()); - Assert.assertEquals("Wrong parameter data", - ":list*(" + RouteParameterRegex.LONG + ")", - parameters.get("list").getTemplate()); - } - - @Test - public void route_model_provides_routes() { - RouteModel root = getRouteModel(); - - final Map routes = root.getRoutes(); - - Assert.assertEquals("Incorrect routes size", 8, routes.size()); - - final String template = "trunk/branch/:id(" - + RouteParameterRegex.INTEGER + ")/:list*(" - + RouteParameterRegex.LONG + ")"; - - Assert.assertEquals("Wrong route mapping", BranchChildren.class, - routes.get(template).getTarget()); - } - - @Test - public void mutable_methods_throw_when_model_is_immutable() { - RouteModel immutable = RouteModel.create(false); - try { - immutable.addRoute("foo/:foo", routeTarget(Root.class)); - - Assert.fail("Immutable model should not be mutable."); - } catch (IllegalStateException e) { - } - - RouteModel mutable = RouteModel.create(true); - mutable.addRoute("foo/:foo", routeTarget(Root.class)); - - RouteModel immutableCopy = RouteModel.copy(mutable, false); - - try { - immutableCopy.removeRoute("foo/:foo"); - - Assert.fail("Immutable model should not be mutable."); - } catch (IllegalStateException e) { - } - } - - private void assertUrl(RouteModel root, String expectedUrl, String template, - RouteParameters parameters) { - final String modelUrl = root.getUrl(template, parameters); - Assert.assertEquals(expectedUrl, modelUrl); - } - - private void assertNavigation(RouteModel model, String url, - Class target, RouteParameters parameters) { - - NavigationRouteTarget result = model.getNavigationRouteTarget(url); - - Assert.assertEquals("Invalid url", url, result.getPath()); - - final RouteTarget routeTarget = result.getRouteTarget(); - assertTarget(target, routeTarget); - - if (target != null) { - Assert.assertEquals("Invalid url", parameters, - result.getRouteParameters()); - } - } - - private void assertRoute(RouteModel model, - Class target, String template, - RouteParameters parameters) { - assertTarget(target, model.getRouteTarget(template, parameters)); - } - - private void assertTarget(Class target, - RouteTarget routeTarget) { - Assert.assertTrue("Weird expected target [" + target + "], actual [" - + routeTarget + "]", (target == null) == (routeTarget == null)); - - if (target != null) { - Assert.assertTrue( - "Invalid expected target [" + target + "], actual " - + routeTarget.getTarget(), - routeTarget.getTarget().equals(target)); - } - } - - private RouteTarget routeTarget(Class target) { - return new RouteTarget(target, null); - } - - /** - * Creates a parameters map where any even index argument is a key (starting - * with 0) and any odd index argument is a value (starting with 1) - * - * @param namesAndValues - * the keys and values of the map. - * @return a Map containing the specified arguments. - */ - public static RouteParameters parameters(String... namesAndValues) { - if (namesAndValues.length % 2 == 1) { - throw new IllegalArgumentException( - "Input varargs must be of even size."); - } - - Map paramsMap = new HashMap<>( - namesAndValues.length / 2); - - for (int i = 0; i < namesAndValues.length; i += 2) { - final String name = namesAndValues[i]; - if (paramsMap.containsKey(name)) { - throw new IllegalArgumentException( - "Parameter " + name + " is specified more than once."); - } - - final String value = namesAndValues[i + 1]; - paramsMap.put(name, value); - } - - return new RouteParameters(paramsMap); - } - - /** - * Creates a List out of the specified arguments. - * - * @param varargs - * an array of strings. - * @return a List containing the specified arguments. - */ - public static String varargs(String... varargs) { - return PathUtil.getPath(Arrays.asList(varargs)); - } - - @Tag(Tag.DIV) - public static class Root extends Component { - } - - @Tag(Tag.DIV) - public static class Trunk extends Component { - } - - @Tag(Tag.DIV) - public static class Branch extends Component { - } - - @Tag(Tag.DIV) - public static class BranchChildren extends Component { - } - - @Tag(Tag.DIV) - public static class Twig extends Component { - } - - @Tag(Tag.DIV) - public static class BranchEdit extends Component { - } - - @Tag(Tag.DIV) - public static class FlowerEdit extends Component { - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/RouteUtilTest.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/RouteUtilTest.java deleted file mode 100644 index d41e0802d0c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/RouteUtilTest.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.router.internal; - -import java.util.Collections; -import java.util.List; - -import org.hamcrest.MatcherAssert; -import org.hamcrest.collection.IsIterableContainingInOrder; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteAlias; -import com.vaadin.flow.router.RoutePrefix; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; - -/** - * Test that {@link RouteUtil} route resolving works as intended for both simple - * and complex cases. - */ -public class RouteUtilTest { - - @Tag(Tag.DIV) - public static class Parent extends Component implements RouterLayout { - } - - @Tag(Tag.DIV) - @RoutePrefix("parent") - public static class RoutePrefixParent extends Component - implements RouterLayout { - } - - @Tag(Tag.DIV) - @RoutePrefix("aliasparent") - public static class RouteAliasPrefixParent extends Component - implements RouterLayout { - } - - @Route(value = "", layout = RoutePrefixParent.class) - @RouteAlias("alias") - @Tag(Tag.DIV) - public static class BaseRouteWithParentPrefixAndRouteAlias - extends Component { - } - - @Route(value = "flow", layout = RoutePrefixParent.class) - @RouteAlias("alias") - @Tag(Tag.DIV) - public static class RouteWithParentPrefixAndRouteAlias extends Component { - } - - @Route(value = "flow", layout = RoutePrefixParent.class) - @RouteAlias(value = "alias", layout = RouteAliasPrefixParent.class) - @Tag(Tag.DIV) - public static class RouteAliasWithParentPrefix extends Component { - } - - @Route(value = "single", layout = RoutePrefixParent.class, absolute = true) - @RouteAlias(value = "alias", layout = RoutePrefixParent.class, absolute = true) - public static class AbsoluteRoute extends Component { - } - - @Tag(Tag.DIV) - @ParentLayout(RoutePrefixParent.class) - @RoutePrefix(value = "absolute", absolute = true) - public static class AbsoluteCenterParent extends Component - implements RouterLayout { - } - - @Route(value = "child", layout = AbsoluteCenterParent.class) - @RouteAlias(value = "alias", layout = AbsoluteCenterParent.class) - public static class AbsoluteCenterRoute extends Component { - } - - @Tag(Tag.DIV) - @ParentLayout(Parent.class) - public static class MiddleParent extends Component implements RouterLayout { - } - - @Route(value = "", layout = MiddleParent.class) - @Tag(Tag.DIV) - public static class RootWithParents extends Component { - } - - @Tag(Tag.DIV) - @ParentLayout(Parent.class) - public static class NonRouteTargetWithParents extends Component { - } - - @Route(value = "", layout = Parent.class) - @RouteAlias(value = "alias", layout = MiddleParent.class) - @Tag(Tag.DIV) - @ParentLayout(RoutePrefixParent.class) - public static class MultiTarget extends Component implements RouterLayout { - } - - @Route(value = "sub", layout = MultiTarget.class) - @Tag(Tag.DIV) - public static class SubLayout extends Component { - } - - @Test - public void route_path_should_contain_parent_prefix() { - String routePath = RouteUtil.getRoutePath( - BaseRouteWithParentPrefixAndRouteAlias.class, - BaseRouteWithParentPrefixAndRouteAlias.class - .getAnnotation(Route.class)); - Assert.assertEquals( - "Expected path should only have been parent RoutePrefix", - "parent", routePath); - } - - @Test - public void absolute_route_should_not_contain_parent_prefix() { - String routePath = RouteUtil.getRoutePath(AbsoluteRoute.class, - AbsoluteRoute.class.getAnnotation(Route.class)); - Assert.assertEquals("No parent prefix should have been added.", - "single", routePath); - } - - @Test - public void absolute_middle_parent_route_should_not_contain_parent_prefix() { - String routePath = RouteUtil.getRoutePath(AbsoluteRoute.class, - AbsoluteCenterRoute.class.getAnnotation(Route.class)); - Assert.assertEquals("No parent prefix should have been added.", - "absolute/child", routePath); - } - - @Test - public void absolute_route_alias_should_not_contain_parent_prefix() { - String routePath = RouteUtil.getRouteAliasPath(AbsoluteRoute.class, - AbsoluteRoute.class.getAnnotation(RouteAlias.class)); - Assert.assertEquals("No parent prefix should have been added.", "alias", - routePath); - } - - @Test - public void absolute_middle_parent_for_route_alias_should_not_contain_parent_prefix() { - String routePath = RouteUtil.getRouteAliasPath(AbsoluteRoute.class, - AbsoluteCenterRoute.class.getAnnotation(RouteAlias.class)); - Assert.assertEquals("No parent prefix should have been added.", - "absolute/alias", routePath); - } - - @Test - public void route_path_should_contain_route_and_parent_prefix() { - String routePath = RouteUtil.getRoutePath( - RouteWithParentPrefixAndRouteAlias.class, - RouteWithParentPrefixAndRouteAlias.class - .getAnnotation(Route.class)); - Assert.assertEquals( - "Expected path should only have been parent RoutePrefix", - "parent/flow", routePath); - } - - @Test - public void route_alias_path_should_not_contain_parent_prefix() { - String routePath = RouteUtil.getRouteAliasPath( - BaseRouteWithParentPrefixAndRouteAlias.class, - BaseRouteWithParentPrefixAndRouteAlias.class - .getAnnotation(RouteAlias.class)); - Assert.assertEquals( - "Expected path should only have been parent RoutePrefix", - "alias", routePath); - routePath = RouteUtil.getRouteAliasPath( - RouteWithParentPrefixAndRouteAlias.class, - RouteWithParentPrefixAndRouteAlias.class - .getAnnotation(RouteAlias.class)); - Assert.assertEquals( - "Expected path should only have been parent RoutePrefix", - "alias", routePath); - } - - @Test - public void route_alias_should_contain_parent_prefix() { - String routePath = RouteUtil.getRouteAliasPath( - RouteAliasWithParentPrefix.class, - RouteAliasWithParentPrefix.class - .getAnnotation(RouteAlias.class)); - Assert.assertEquals( - "Expected path should only have been parent RoutePrefix", - "aliasparent/alias", routePath); - } - - @Test - public void top_parent_layout_should_be_found_for_base_route() { - Class parent = RouteUtil.getTopParentLayout( - BaseRouteWithParentPrefixAndRouteAlias.class, "parent"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RoutePrefixParent.class, parent); - } - - @Test - public void top_parent_layout_should_be_found_for_non_base_route() { - Class parent = RouteUtil.getTopParentLayout( - RouteWithParentPrefixAndRouteAlias.class, "parent/flow"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RoutePrefixParent.class, parent); - } - - @Test - public void no_top_parent_layout_for_route_alias() { - Class parent = RouteUtil.getTopParentLayout( - BaseRouteWithParentPrefixAndRouteAlias.class, "alias"); - - Assert.assertNull("Found parent for RouteAlias without parent.", - parent); - } - - @Test - public void top_parent_layout_for_route_alias() { - Class parent = RouteUtil.getTopParentLayout( - RouteAliasWithParentPrefix.class, "aliasparent/alias"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RouteAliasPrefixParent.class, parent); - } - - @Test - public void top_parent_layout_for_absolute_route() { - Class parent = RouteUtil - .getTopParentLayout(AbsoluteRoute.class, "single"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RoutePrefixParent.class, parent); - } - - @Test - public void top_parent_layout_for_absolute_route_parent() { - Class parent = RouteUtil.getTopParentLayout( - AbsoluteCenterRoute.class, "absolute/child"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RoutePrefixParent.class, parent); - } - - @Test - public void top_parent_layout_for_absolute_route_alias() { - Class parent = RouteUtil - .getTopParentLayout(AbsoluteRoute.class, "alias"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RoutePrefixParent.class, parent); - } - - @Test - public void top_parent_layout_for_absolute_route_alias_parent() { - Class parent = RouteUtil.getTopParentLayout( - AbsoluteCenterRoute.class, "absolute/alias"); - - Assert.assertNotNull("Didn't find any parent for route", parent); - Assert.assertEquals("Received wrong parent class.", - RoutePrefixParent.class, parent); - } - - @Test - public void expected_parent_layouts_are_found_for_route() { - List> parentLayouts = RouteUtil - .getParentLayouts(BaseRouteWithParentPrefixAndRouteAlias.class, - "parent"); - - MatcherAssert.assertThat( - "Get parent layouts for route \"\" with parent prefix \"parent\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder - .contains(new Class[] { RoutePrefixParent.class })); - - parentLayouts = RouteUtil.getParentLayouts(RootWithParents.class, ""); - - MatcherAssert.assertThat( - "Expected to receive MiddleParent and Parent classes as parents.", - parentLayouts, IsIterableContainingInOrder.contains( - new Class[] { MiddleParent.class, Parent.class })); - } - - @Test - public void expected_to_get_parent_layout() { - List> parentLayouts = RouteUtil - .getParentLayoutsForNonRouteTarget( - NonRouteTargetWithParents.class); - - Assert.assertEquals("Expected one parent layout", 1, - parentLayouts.size()); - - MatcherAssert.assertThat( - "Get parent layouts for route \"\" with parent prefix \"parent\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder - .contains(new Class[] { Parent.class })); - } - - @Test - public void expected_parent_layouts_are_found_for_route_alias() { - List> parentLayouts = RouteUtil - .getParentLayouts(RouteAliasWithParentPrefix.class, - "aliasparent/alias"); - - MatcherAssert.assertThat( - "Get parent layouts for route \"\" with parent prefix \"parent\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder.contains( - new Class[] { RouteAliasPrefixParent.class })); - } - - @Test - public void absolute_route_gets_expected_parent_layouts() { - List> parentLayouts = RouteUtil - .getParentLayouts(AbsoluteRoute.class, "single"); - - MatcherAssert.assertThat( - "Get parent layouts for route \"\" with parent prefix \"parent\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder - .contains(new Class[] { RoutePrefixParent.class })); - - parentLayouts = RouteUtil.getParentLayouts(AbsoluteCenterRoute.class, - "absolute/child"); - - MatcherAssert.assertThat( - "Expected to receive MiddleParent and Parent classes as parents.", - parentLayouts, - IsIterableContainingInOrder.contains(new Class[] { - AbsoluteCenterParent.class, RoutePrefixParent.class })); - } - - @Test - public void abolute_route_alias_gets_expected_parent_layouts() { - List> parentLayouts = RouteUtil - .getParentLayouts(AbsoluteRoute.class, "alias"); - - MatcherAssert.assertThat( - "Get parent layouts for route \"\" with parent prefix \"parent\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder - .contains(new Class[] { RoutePrefixParent.class })); - - parentLayouts = RouteUtil.getParentLayouts(AbsoluteCenterRoute.class, - "absolute/alias"); - - MatcherAssert.assertThat( - "Expected to receive MiddleParent and Parent classes as parents.", - parentLayouts, - IsIterableContainingInOrder.contains(new Class[] { - AbsoluteCenterParent.class, RoutePrefixParent.class })); - - } - - @Test - public void also_non_routes_can_be_used_to_get_top_parent_layout() { - Class topParentLayout = RouteUtil - .getTopParentLayout(MiddleParent.class, null); - Assert.assertEquals( - "Middle parent should have gotten Parent as top parent layout", - Parent.class, topParentLayout); - } - - @Test // 3424 - public void top_layout_resolves_correctly_for_route_parent() { - Class topParentLayout = RouteUtil - .getTopParentLayout(MultiTarget.class, ""); - Assert.assertEquals( - "@Route path should have gotten Parent as top parent layout", - Parent.class, topParentLayout); - - topParentLayout = RouteUtil.getTopParentLayout(MultiTarget.class, - "alias"); - Assert.assertEquals( - "@RouteAlias path should have gotten Parent as top parent layout", - Parent.class, topParentLayout); - - topParentLayout = RouteUtil.getTopParentLayout(SubLayout.class, - "parent/sub"); - Assert.assertEquals( - "SubLayout using MultiTarget as parent should have gotten RoutePrefixParent as top parent layout", - RoutePrefixParent.class, topParentLayout); - - } - - @Test // 3424 - public void parent_layouts_resolve_correctly_for_route_parent() { - List> parentLayouts = RouteUtil - .getParentLayouts(MultiTarget.class, ""); - - MatcherAssert.assertThat( - "Get parent layouts for route \"\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder - .contains(new Class[] { Parent.class })); - - parentLayouts = RouteUtil.getParentLayouts(MultiTarget.class, "alias"); - - MatcherAssert.assertThat( - "Get parent layouts for routeAlias \"alias\" gave wrong result.", - parentLayouts, IsIterableContainingInOrder.contains( - new Class[] { MiddleParent.class, Parent.class })); - - parentLayouts = RouteUtil.getParentLayouts(SubLayout.class, - "parent/sub"); - - MatcherAssert.assertThat( - "Get parent layouts for route \"parent/sub\" with parent Route + ParentLayout gave wrong result.", - parentLayouts, - IsIterableContainingInOrder.contains(new Class[] { - MultiTarget.class, RoutePrefixParent.class })); - } - - @Test - public void newRouteAnnotatedClass_updateRouteRegistry_routeIsAddedToRegistry() { - // given - @Route("a") - class A extends Component { - } - MockVaadinServletService service = new MockVaadinServletService() { - @Override - public VaadinContext getContext() { - return new MockVaadinContext(); - } - }; - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(service.getContext()); - - // when - RouteUtil.updateRouteRegistry(registry, Collections.singleton(A.class), - Collections.emptySet(), Collections.emptySet()); - - // then - Assert.assertTrue(registry.getConfiguration().hasRoute("a")); - } - - @Test - public void deletedRouteAnnotatedClass_updateRouteRegistry_routeIsRemovedFromRegistry() { - // given - @Route("a") - class A extends Component { - } - - MockVaadinServletService service = new MockVaadinServletService(); - - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(service.getContext()); - registry.setRoute("a", A.class, Collections.emptyList()); - Assert.assertTrue(registry.getConfiguration().hasRoute("a")); - - // when - RouteUtil.updateRouteRegistry(registry, Collections.emptySet(), - Collections.emptySet(), Collections.singleton(A.class)); - - // then - Assert.assertFalse(registry.getConfiguration().hasRoute("a")); - } - - @Test - public void renamedRouteAnnotatedClass_updateRouteRegistry_routeIsUpdatedInRegistry() { - // given - @Route("aa") - class A extends Component { - } - MockVaadinServletService service = new MockVaadinServletService() { - @Override - public VaadinContext getContext() { - return new MockVaadinContext(); - } - }; - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(service.getContext()); - registry.setRoute("a", A.class, Collections.emptyList()); - Assert.assertTrue(registry.getConfiguration().hasRoute("a")); - - // when - RouteUtil.updateRouteRegistry(registry, Collections.emptySet(), - Collections.singleton(A.class), Collections.emptySet()); - - // then - Assert.assertFalse(registry.getConfiguration().hasRoute("a")); - Assert.assertTrue(registry.getConfiguration().hasRoute("aa")); - } - - @Test - public void deannotatedRouteClass_updateRouteRegistry_routeIsRemovedFromRegistry() { - // given - class A extends Component { - } - - MockVaadinServletService service = new MockVaadinServletService(); - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(service.getContext()); - registry.setRoute("a", A.class, Collections.emptyList()); - Assert.assertTrue(registry.getConfiguration().hasRoute("a")); - - // when - RouteUtil.updateRouteRegistry(registry, Collections.emptySet(), - Collections.singleton(A.class), Collections.emptySet()); - - // then - Assert.assertFalse(registry.getConfiguration().hasRoute("a")); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/router/internal/TestAbstractRouteRegistry.java b/flow-server/src/test/java/com/vaadin/flow/router/internal/TestAbstractRouteRegistry.java deleted file mode 100644 index 87ffd2abbfd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/router/internal/TestAbstractRouteRegistry.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.router.internal; - -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.VaadinContext; - -public class TestAbstractRouteRegistry extends AbstractRouteRegistry { - - @Override - public VaadinContext getContext() { - return new MockVaadinContext(); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/AbstractDeploymentConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/server/AbstractDeploymentConfigurationTest.java deleted file mode 100644 index a9988be1b08..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/AbstractDeploymentConfigurationTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.Collections; -import java.util.Optional; -import java.util.Properties; -import java.util.UUID; -import java.util.function.Function; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.shared.communication.PushMode; - -/** - * Test for {@link AbstractDeploymentConfiguration} - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class AbstractDeploymentConfigurationTest { - - @Test - public void getUIClass_returnsUIParameterPropertyValue() { - String ui = UUID.randomUUID().toString(); - DeploymentConfiguration config = getConfig(InitParameters.UI_PARAMETER, - ui); - Assert.assertEquals("Unexpected UI class configuration option value", - ui, config.getUIClassName()); - } - - @Test - public void getClassLoader_returnsClassloaderPropertyValue() { - String classLoader = UUID.randomUUID().toString(); - DeploymentConfiguration config = getConfig("ClassLoader", classLoader); - Assert.assertEquals("Unexpected classLoader configuration option value", - classLoader, config.getClassLoaderName()); - } - - private DeploymentConfiguration getConfig(String property, String value) { - Properties props = new Properties(); - if (property != null) { - props.put(property, value); - } - return new DeploymentConfigImpl(props); - } - - private static class DeploymentConfigImpl - extends AbstractDeploymentConfiguration { - - private Properties properties; - - DeploymentConfigImpl(Properties props) { - super(Collections.emptyMap()); - properties = props; - } - - @Override - public boolean isProductionMode() { - return false; - } - - @Override - public boolean isRequestTiming() { - return !isProductionMode(); - } - - @Override - public boolean isXsrfProtectionEnabled() { - return false; - } - - @Override - public boolean isSyncIdCheckEnabled() { - return false; - } - - @Override - public int getHeartbeatInterval() { - return 0; - } - - @Override - public int getMaxMessageSuspendTimeout() { - return 0; - } - - @Override - public int getWebComponentDisconnect() { - return 0; - } - - @Override - public boolean isCloseIdleSessions() { - return false; - } - - @Override - public PushMode getPushMode() { - return null; - } - - @Override - public String getPushURL() { - return ""; - } - - @Override - public Properties getInitParameters() { - return null; - } - - @Override - public T getApplicationOrSystemProperty(String propertyName, - T defaultValue, Function converter) { - return Optional.ofNullable(properties.getProperty(propertyName)) - .map(converter).orElse(defaultValue); - } - - @Override - public boolean isDevModeLiveReloadEnabled() { - return false; - } - - @Override - public boolean isDevToolsEnabled() { - return false; - } - - @Override - public boolean isSendUrlsAsParameters() { - return DefaultDeploymentConfiguration.DEFAULT_SEND_URLS_AS_PARAMETERS; - } - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapContextTest.java b/flow-server/src/test/java/com/vaadin/flow/server/BootstrapContextTest.java deleted file mode 100644 index 9d3649cb3b8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapContextTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.Collections; -import java.util.Optional; -import java.util.function.Function; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.RouteNotFoundError; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.BootstrapHandler.BootstrapContext; -import com.vaadin.flow.server.communication.JavaScriptBootstrapHandler.JavaScriptBootstrapContext; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.flow.shared.communication.PushMode; -import com.vaadin.flow.shared.ui.Transport; - -public class BootstrapContextTest { - - private MockVaadinSession session; - private UI ui; - private VaadinRequest request = Mockito.mock(VaadinRequest.class); - - private Function callback = request -> "";; - - @Tag(Tag.A) - @Push(value = PushMode.MANUAL, transport = Transport.LONG_POLLING) - private static class MainView extends Component implements RouterLayout { - - } - - @Tag(Tag.A) - private static class OtherView extends Component { - - } - - @Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET) - private static class CustomRouteNotFound extends RouteNotFoundError { - - } - - @ParentLayout(MainView.class) - private static class AnotherCustomRouteNotFound extends RouteNotFoundError { - - } - - @Before - public void setUp() throws ServiceException { - MockVaadinSession session = new MockVaadinSession(); - ui = new UI(); - ui.getInternals().setSession(session); - } - - @Test - public void getPushAnnotation_routeTargetPresents_pushFromTheClassDefinitionIsUsed() { - ui.getInternals().getRouter().getRegistry().setRoute("foo", - MainView.class, Collections.emptyList()); - Mockito.when(request - .getParameter(ApplicationConstants.REQUEST_LOCATION_PARAMETER)) - .thenReturn("foo"); - - BootstrapContext context = new JavaScriptBootstrapContext(request, - Mockito.mock(VaadinResponse.class), ui, callback); - - Optional push = context - .getPageConfigurationAnnotation(Push.class); - Assert.assertTrue(push.isPresent()); - Push pushAnnotation = push.get(); - Assert.assertEquals(PushMode.MANUAL, pushAnnotation.value()); - Assert.assertEquals(Transport.LONG_POLLING, pushAnnotation.transport()); - } - - @Test - public void getPushAnnotation_routeTargetPresents_pushDefinedOnParentLayout_pushFromTheClassDefinitionIsUsed() { - ui.getInternals().getRouter().getRegistry().setRoute("foo", - OtherView.class, Collections.singletonList(MainView.class)); - Mockito.when(request - .getParameter(ApplicationConstants.REQUEST_LOCATION_PARAMETER)) - .thenReturn("foo"); - - BootstrapContext context = new JavaScriptBootstrapContext(request, - Mockito.mock(VaadinResponse.class), ui, callback); - - Optional push = context - .getPageConfigurationAnnotation(Push.class); - Assert.assertTrue(push.isPresent()); - Push pushAnnotation = push.get(); - Assert.assertEquals(PushMode.MANUAL, pushAnnotation.value()); - Assert.assertEquals(Transport.LONG_POLLING, pushAnnotation.transport()); - } - - @Test - public void getPushAnnotation_routeTargetIsAbsent_pushFromTheErrorNavigationTargetIsUsed() { - Mockito.when(request - .getParameter(ApplicationConstants.REQUEST_LOCATION_PARAMETER)) - .thenReturn("bar"); - - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(ui.getSession().getService().getContext()); - registry.setErrorNavigationTargets( - Collections.singleton(CustomRouteNotFound.class)); - - BootstrapContext context = new BootstrapContext(request, - Mockito.mock(VaadinResponse.class), session, ui, request -> ""); - - Optional push = context - .getPageConfigurationAnnotation(Push.class); - Assert.assertTrue(push.isPresent()); - Push pushAnnotation = push.get(); - Assert.assertEquals(PushMode.AUTOMATIC, pushAnnotation.value()); - Assert.assertEquals(Transport.WEBSOCKET, pushAnnotation.transport()); - } - - @Test - public void getPushAnnotation_routeTargetIsAbsent_pushIsDefinedOnParentLayout_pushFromTheErrorNavigationTargetParentLayoutIsUsed() { - Mockito.when(request - .getParameter(ApplicationConstants.REQUEST_LOCATION_PARAMETER)) - .thenReturn("bar"); - - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(ui.getSession().getService().getContext()); - registry.setErrorNavigationTargets( - Collections.singleton(AnotherCustomRouteNotFound.class)); - - BootstrapContext context = new BootstrapContext(request, - Mockito.mock(VaadinResponse.class), session, ui, request -> ""); - - Optional push = context - .getPageConfigurationAnnotation(Push.class); - Assert.assertTrue(push.isPresent()); - Push pushAnnotation = push.get(); - Assert.assertEquals(PushMode.MANUAL, pushAnnotation.value()); - Assert.assertEquals(Transport.LONG_POLLING, pushAnnotation.transport()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerDependenciesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerDependenciesTest.java deleted file mode 100644 index a9fa9a8b512..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerDependenciesTest.java +++ /dev/null @@ -1,775 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.http.HttpServletRequest; - -import java.io.InputStream; -import java.util.List; -import java.util.Optional; -import java.util.Properties; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.jcip.annotations.NotThreadSafe; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.StyleSheet; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.server.BootstrapHandler.BootstrapContext; -import com.vaadin.flow.server.MockServletServiceSessionSetup.TestVaadinServlet; -import com.vaadin.flow.server.MockServletServiceSessionSetup.TestVaadinServletService; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.flow.shared.ui.LoadMode; - -import static org.hamcrest.CoreMatchers.both; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.either; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.Matchers.lessThan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -@NotThreadSafe -public class BootstrapHandlerDependenciesTest { - private static final String BOOTSTRAP_SCRIPT_CONTENTS = "// { - }, ui); - } catch (IllegalStateException expected) { - exceptionCaught = true; - } finally { - assertFalse( - "The exception was expected, but not thrown for ui " - + ui.getClass().getCanonicalName(), - exceptionCaught); - } - } - - @Test - public void checkDependenciesPresence_addedViaAnnotation() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - assertCssElementLoadedEagerly(head, "eager.css"); - assertCssElementLoadedEagerly(head, "./eager-relative.css"); - - assertCssElementInlined(head, "inline.css"); - - assertElementLazyLoaded(head, "lazy.css"); - }; - testUis(uiPageTestingMethod, new UIAnnotated_LoadingOrderTest()); - } - - @Test - public void checkDependenciesPresence_addedViaAPI() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - assertJavaScriptElementLoadedEagerly(head, "eager.js"); - assertCssElementLoadedEagerly(head, "eager.css"); - assertCssElementLoadedEagerly(head, "./eager-relative.css"); - - assertCssElementInlined(head, "inline.css"); - assertJavaScriptElementInlined(head, "inline.js"); - - assertElementLazyLoaded(head, "lazy.js"); - assertElementLazyLoaded(head, "lazy.css"); - }; - testUis(uiPageTestingMethod, new UIWithMethods_LoadingOrderTest()); - } - - @Test - public void checkUidlDependencies_addedViaAnnotations() { - Consumer uiPageTestingMethod = page -> { - String uidlData = extractUidlData(page); - assertFalse(uidlData.contains("eager.css")); - assertFalse(uidlData.contains("./eager-relative.css")); - - assertFalse(uidlData.contains("inline.css")); - - assertTrue(uidlData.contains("lazy.css")); - }; - testUis(uiPageTestingMethod, new UIAnnotated_LoadingOrderTest()); - } - - @Test - public void checkUidlDependencies_addedViaAPI() { - Consumer uiPageTestingMethod = page -> { - String uidlData = extractUidlData(page); - assertFalse(uidlData.contains("eager.css")); - assertFalse(uidlData.contains("./eager-relative.css")); - assertFalse(uidlData.contains("eager.js")); - - assertFalse(uidlData.contains("inline.js")); - assertFalse(uidlData.contains("inline.css")); - - assertTrue(uidlData.contains("lazy.js")); - assertTrue(uidlData.contains("lazy.css")); - }; - testUis(uiPageTestingMethod, new UIWithMethods_LoadingOrderTest()); - } - - @Test - public void everyLazyJavaScriptIsIncludedWithDeferAttribute() { - Consumer uiPageTestingMethod = page -> { - Elements jsElements = page.getElementsByTag("script"); - Elements deferElements = page.getElementsByAttribute("defer"); - - // Ignore polyfills that should be loaded immediately and scripts - // without src (separate test) - jsElements.removeIf(element -> { - String type = element.attr("type"); - String jsUrl = element.attr("src"); - return jsUrl.isEmpty() || jsUrl.contains("es6-collections.js") - || jsUrl.contains("webcomponents-loader.js") - || type.equals("module"); - }); - - assertEquals( - "Expected to have all script elements with defer attribute", - jsElements, deferElements); - }; - testUis(uiPageTestingMethod, new UIAnnotated_LoadingOrderTest(), - new UIWithMethods_LoadingOrderTest(), - new UIAnnotated_ImportOrderTest_Lazy(), - new UIWithMethods_ImportOrderTest_Lazy()); - } - - @Test - public void eagerDependenciesAreImportedInConsequentOrder() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List cssImportUrls = head.getElementsByTag("link").stream() - .filter(element -> "stylesheet".equals(element.attr("rel"))) - .map(element -> element.attr("href")) - .collect(Collectors.toList()); - assertImportOrder(cssImportUrls, "1.css", "2.css"); - }; - testUis(uiPageTestingMethod, new UIAnnotated_ImportOrderTest_Eager(), - new UIWithMethods_ImportOrderTest_Eager()); - } - - @Test - public void lazyDependenciesAreImportedInConsequentOrder() { - Consumer uiPageTestingMethod = page -> { - String uidlData = extractUidlData(page); - assertDependenciesOrderInUidl(uidlData, "1.css", "2.css"); - }; - testUis(uiPageTestingMethod, new UIAnnotated_ImportOrderTest_Lazy(), - new UIWithMethods_ImportOrderTest_Lazy()); - } - - @Test - public void inlineDependenciesAreImportedInConsequentOrder_depsAreAddedViaAnnotations() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List cssImportContents = head.getElementsByTag("style") - .stream().map(Element::toString) - .collect(Collectors.toList()); - assertImportOrder(cssImportContents, "1.css", "2.css"); - }; - testUis(uiPageTestingMethod, new UIAnnotated_ImportOrderTest_Inline()); - } - - @Test - public void inlineDependenciesAreImportedInConsequentOrder_depsAreAddedViaAPI() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List jsImportContents = head.getElementsByTag("script") - .stream().filter(element -> !element.hasAttr("src")) - .filter(element -> !element.toString() - .contains(BOOTSTRAP_SCRIPT_CONTENTS)) - .map(Element::toString).collect(Collectors.toList()); - assertImportOrder(jsImportContents, "1.js", "2.js"); - - List cssImportContents = head.getElementsByTag("style") - .stream().map(Element::toString) - .collect(Collectors.toList()); - assertImportOrder(cssImportContents, "1.css", "2.css"); - - }; - testUis(uiPageTestingMethod, - new UIWithMethods_ImportOrderTest_Inline()); - } - - @Test - public void duplicateDependenciesAreDiscarded_Eager() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List jsImportUrls = head.getElementsByTag("link").stream() - .filter(el -> el.attr("type").equals("text/css")) - .map(Element::toString).collect(Collectors.toList()); - assertImportOrder(jsImportUrls, "1.css", "2.css"); - }; - testUis(uiPageTestingMethod, - new UIAnnotated_DuplicateDependencies_Eager(), - new UIWithMethods_DuplicateDependencies_Eager()); - } - - @Test - public void duplicateDependenciesAreDiscarded_Eager_JSDepsAddedViaAPI() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List jsImportUrls = head.getElementsByTag("script").stream() - .map(element -> element.attr("src")) - .collect(Collectors.toList()); - assertImportOrder(jsImportUrls, "1.js", "2.js"); - }; - testUis(uiPageTestingMethod, - new UIWithMethods_DuplicateDependencies_Eager()); - } - - @Test - public void duplicateDependenciesAreDiscarded_Lazy() { - Consumer uiPageTestingMethod = page -> { - String uidlData = extractUidlData(page); - assertDependenciesOrderInUidl(uidlData, "1.css", "2.css"); - }; - testUis(uiPageTestingMethod, - new UIAnnotated_DuplicateDependencies_Lazy(), - new UIWithMethods_DuplicateDependencies_Lazy()); - } - - @Test - public void duplicateDependenciesAreDiscarded_Lazy_JSdepsAreAddedViaAPI() { - Consumer uiPageTestingMethod = page -> { - String uidlData = extractUidlData(page); - assertDependenciesOrderInUidl(uidlData, "1.js", "2.js"); - }; - testUis(uiPageTestingMethod, - new UIWithMethods_DuplicateDependencies_Lazy()); - } - - @Test - public void duplicateDependenciesAreDiscarded_Inline() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List jsImportContents = head.getElementsByTag("style") - .stream().map(Element::toString) - .collect(Collectors.toList()); - assertImportOrder(jsImportContents, "1.css", "2.css"); - }; - testUis(uiPageTestingMethod, - new UIAnnotated_DuplicateDependencies_Inline(), - new UIWithMethods_DuplicateDependencies_Inline()); - } - - @Test - public void duplicateDependenciesAreDiscarded_Inline_JSDepsAddedViaAPI() { - Consumer uiPageTestingMethod = page -> { - Element head = page.head(); - - List jsImportContents = head.getElementsByTag("script") - .stream().filter(element -> !element.hasAttr("src")) - .filter(element -> !element.toString() - .contains(BOOTSTRAP_SCRIPT_CONTENTS)) - .map(Element::toString).collect(Collectors.toList()); - assertImportOrder(jsImportContents, "1.js", "2.js"); - }; - testUis(uiPageTestingMethod, - new UIWithMethods_DuplicateDependencies_Inline()); - } - - @Test - public void flowDependenciesShouldBeImportedBeforeUserDependenciesWithCorrectAttributes() { - Consumer uiPageTestingMethod = page -> { - boolean foundClientEngine = false; - int flowDependencyMaxIndex = Integer.MAX_VALUE; - int userDependencyMinIndex = Integer.MAX_VALUE; - - Elements children = page.head().children(); - for (int i = 0; i < children.size(); i++) { - Element element = children.get(i); - String elementString = element.toString(); - if (foundClientEngine) { - if (userDependencyMinIndex > i) { - userDependencyMinIndex = i; - } - if (elementString.contains("dndConnector.js")) { - continue; - } - assertThat( - "Expected to have here dependencies added with Flow public api", - elementString, - either(containsString("eager")) - .or(containsString("lazy")) - .or(containsString("inline"))); - } else { - flowDependencyMaxIndex = i; - // skip element with uidl that contains lazy dependencies - if (!elementString.contains(BOOTSTRAP_SCRIPT_CONTENTS)) { - assertThat( - "Flow dependencies should not contain user dependencies", - elementString, - both(not(containsString("eager"))) - .and(not(containsString("lazy"))) - .and(not(containsString("inline")))); - - if (elementString.contains(clientEngine)) { - foundClientEngine = true; - } - - } else { - assertThat( - "uidl should not contain eager and inline dependencies", - elementString, - both(not(containsString("eager"))) - .and(not(containsString("inline")))); - } - } - - assertThat(String.format( - "All javascript dependencies should be loaded without 'async' attribute. Dependency with url %s has this attribute", - element.attr("src")), element.attr("async"), is("")); - } - - assertThat( - "Flow dependencies should be imported before user dependencies", - flowDependencyMaxIndex, - is(lessThan(userDependencyMinIndex))); - - }; - - testUis(uiPageTestingMethod, new UIAnnotated_LoadingOrderTest(), - new UIWithMethods_LoadingOrderTest()); - } - - @Test - public void checkThatJsImportsWithoutSrcHaveNoDeferAttribute() { - Consumer uiPageTestingMethod = page -> { - List scriptsWithNoSrc = page.getElementsByTag("script") - .stream().filter(jsElement -> !jsElement.hasAttr("src")) - .collect(Collectors.toList()); - - for (Element element : scriptsWithNoSrc) { - String deferAttributeValue = element.attr("defer"); - // https://developer.mozilla.org/en/docs/Web/HTML/Element/script - assertThat("Scripts without src should not be loaded as defer", - deferAttributeValue, either(is("")).or(is("false"))); - } - }; - - testUis(uiPageTestingMethod, new UIAnnotated_LoadingOrderTest(), - new UIWithMethods_LoadingOrderTest(), - new UIAnnotated_ImportOrderTest_Lazy(), - new UIWithMethods_ImportOrderTest_Lazy(), - new UIAnnotated_ImportOrderTest_Inline(), - new UIWithMethods_ImportOrderTest_Inline()); - } - - private void testUis(Consumer uiPageTestingMethod, - UI... uisToTest) { - assertTrue("Got no uis to test", uisToTest.length > 0); - Stream.of(uisToTest).forEach( - ui -> uiPageTestingMethod.accept(initUIAndGetPage(ui))); - } - - private String contextRootRelativePath(VaadinRequest request) { - VaadinServletService service = Mockito.mock(VaadinServletService.class); - Mockito.doCallRealMethod().when(service) - .getContextRootRelativePath(Mockito.any()); - return service.getContextRootRelativePath(request); - } - - private Document initUIAndGetPage(UI ui) { - ui.getInternals().setSession(mocks.getSession()); - VaadinServletRequest request = new VaadinServletRequest(createRequest(), - service); - ui.doInit(request, 0); - ui.getInternals().setContextRoot(contextRootRelativePath(request)); - UI.setCurrent(ui); - return new BootstrapHandler.BootstrapPageBuilder() - .getBootstrapPage(new BootstrapContext(request, null, - mocks.getSession(), ui, this::contextRootRelativePath)); - } - - private HttpServletRequest createRequest() { - HttpServletRequest request = mock(HttpServletRequest.class); - Mockito.doAnswer(invocation -> "").when(request).getServletPath(); - return request; - } - - private void assertCssElementLoadedEagerly(Element head, String url) { - Elements cssLinks = head.getElementsByAttributeValue("href", url); - assertEquals(1, cssLinks.size()); - Element linkElement = cssLinks.get(0); - assertEquals("link", linkElement.tagName()); - assertEquals("text/css", linkElement.attr("type")); - assertEquals(url, linkElement.attr("href")); - } - - private void assertJavaScriptElementLoadedEagerly(Element head, - String url) { - Elements jsLinks = head.getElementsByAttributeValue("src", url); - assertEquals(1, jsLinks.size()); - Element linkElement = jsLinks.get(0); - assertEquals("script", linkElement.tagName()); - assertEquals("text/javascript", linkElement.attr("type")); - assertEquals(url, linkElement.attr("src")); - } - - private void assertHtmlElementLoadedEagerly(Element head, String url) { - Elements cssLinks = head.getElementsByAttributeValue("href", url); - assertEquals(1, cssLinks.size()); - Element linkElement = cssLinks.get(0); - assertEquals("link", linkElement.tagName()); - assertEquals("import", linkElement.attr("rel")); - assertEquals(url, linkElement.attr("href")); - } - - private void assertElementLazyLoaded(Element head, String url) { - Stream.of("href", "src").forEach(attribute -> { - Elements elements = head.getElementsByAttributeValue(attribute, - url); - assertTrue(String.format( - "Expected not to have element with url %s for attribute %s", - url, attribute), elements.isEmpty()); - }); - } - - private void assertJavaScriptElementInlined(Element head, - String expectedContents) { - List scriptsWithoutExpectedContents = head - .getElementsByTag("script").stream() - .filter(element -> element.toString() - .contains(expectedContents)) - .collect(Collectors.toList()); - assertThat( - "Expected to have only one inlined js element with contents = " - + expectedContents, - scriptsWithoutExpectedContents.size(), is(1)); - Element inlinedElement = scriptsWithoutExpectedContents.get(0); - assertThat("The element should have correct js type attribute", - inlinedElement.attr("type"), is("text/javascript")); - assertThat("Inlined js element should not have defer attribute", - inlinedElement.attr("defer"), is("")); - assertThat("Inlined js element should not have src attribute", - inlinedElement.attr("src"), is("")); - } - - private void assertCssElementInlined(Element head, - String expectedContents) { - List stylesWithExpectedContents = head - .getElementsByTag("style").stream() - .filter(element -> element.toString() - .contains(expectedContents)) - .collect(Collectors.toList()); - assertThat( - "Expected to have one inlined css element with contents = " - + expectedContents, - stylesWithExpectedContents.size(), is(1)); - Element inlinedElement = stylesWithExpectedContents.get(0); - assertThat("The element should have correct css type attribute", - inlinedElement.attr("type"), is("text/css")); - } - - private void assertHtmlElementInlined(Element body, - String expectedContents) { - List inlinedHtmlElements = body.getElementsByTag("span") - .stream() - .filter(element -> element.toString() - .contains(expectedContents)) - .collect(Collectors.toList()); - assertThat( - "Expected to have only one inlined html element with contents = " - + expectedContents, - inlinedHtmlElements.size(), is(1)); - Element inlinedElement = inlinedHtmlElements.get(0); - assertThat("The element should be hidden", - inlinedElement.hasAttr("hidden"), is(true)); - } - - private String extractUidlData(Document page) { - Optional dataOptional = page.head().getElementsByTag("script") - .stream().filter(scriptTag -> !scriptTag.hasAttr("src")) - .map(Element::data).filter(data -> data.contains("var uidl =")) - .findAny(); - - assertTrue("Expected to find uidl tag in the page", - dataOptional.isPresent()); - return dataOptional.get(); - } - - private void assertImportOrder(List allContents, - String firstContents, String secondContents) { - int firstPosition = -1; - int secondPosition = -1; - for (int i = 0; i < allContents.size(); i++) { - String currentContents = allContents.get(i); - if (currentContents.contains(firstContents)) { - firstPosition = i; - } else if (currentContents.contains(secondContents)) { - secondPosition = i; - } - - if (firstPosition >= 0 && secondPosition >= 0) { - break; - } - } - - assertCorrectDependencyPositions(firstContents, secondContents, - firstPosition, secondPosition); - } - - private void assertDependenciesOrderInUidl(String uidlData, - String firstDependencyUrl, String secondDependencyUrl) { - int firstPosition = uidlData.indexOf(firstDependencyUrl); - int secondPosition = uidlData.indexOf(secondDependencyUrl); - assertCorrectDependencyPositions(firstDependencyUrl, - secondDependencyUrl, firstPosition, secondPosition); - } - - private void assertCorrectDependencyPositions(String firstDependencyUrl, - String secondDependencyUrl, int firstPosition, int secondPosition) { - assertNotEquals(String.format("Could not find url %s in uidl", - firstDependencyUrl), -1, firstPosition); - assertNotEquals(String.format("Could not find url %s in uidl", - secondDependencyUrl), -1, secondPosition); - - assertTrue(String.format( - "Expected url %s to be contained before url %s in the uidl, because it is expected to be first to be imported", - firstDependencyUrl, secondDependencyUrl), - firstPosition < secondPosition); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerPushConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerPushConfigurationTest.java deleted file mode 100644 index 2e21c6b8352..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerPushConfigurationTest.java +++ /dev/null @@ -1,262 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.http.HttpServletRequest; - -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Collections; -import java.util.Enumeration; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.PushConfiguration; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.TestRouteRegistry; -import com.vaadin.flow.server.MockServletServiceSessionSetup.TestVaadinServletService; -import com.vaadin.flow.server.communication.AtmospherePushConnection; -import com.vaadin.flow.server.communication.PushConnection; -import com.vaadin.flow.server.communication.PushConnectionFactory; -import com.vaadin.flow.shared.communication.PushMode; -import com.vaadin.flow.shared.ui.Transport; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; - -public class BootstrapHandlerPushConfigurationTest { - - private BootstrapHandlerTest.TestUI testUI; - private MockServletServiceSessionSetup mocks; - private VaadinSession session; - private TestVaadinServletService service; - - @Before - public void setup() throws Exception { - mocks = new MockServletServiceSessionSetup(); - TestRouteRegistry routeRegistry = new TestRouteRegistry(); - - session = mocks.getSession(); - service = mocks.getService(); - service.setRouteRegistry(routeRegistry); - service.setRouter(new Router(routeRegistry) { - @Override - public void initializeUI(UI ui, Location location) { - // Skip initial navigation during UI.init if no routes have been - // injected - if (routeRegistry.hasNavigationTargets()) { - super.initializeUI(ui, location); - } - } - }); - // Update sessionRegistry due to after init change of global registry - SessionRouteRegistry sessionRegistry = new SessionRouteRegistry( - session); - Mockito.when(session.getAttribute(SessionRouteRegistry.class)) - .thenReturn(sessionRegistry); - - testUI = new BootstrapHandlerTest.TestUI(); - testUI.getInternals().setSession(session); - - } - - @After - public void tearDown() { - mocks.cleanup(); - } - - @Test - public void uiInitialization_pushNotConfiguredWhenAnnotationIsNotPresent() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinResponse response = mock(VaadinResponse.class); - final BootstrapHandler.BootstrapContext context = bootstrapHandler - .createAndInitUI(BootstrapHandlerTest.TestUI.class, - createVaadinRequest(), response, session); - - PushConfiguration pushConfiguration = context.getUI() - .getPushConfiguration(); - Assert.assertEquals( - "Push mode should be disabled without @Push annotation.", - PushMode.DISABLED, pushConfiguration.getPushMode()); - Assert.assertEquals("Push transport should be WEBSOCKET_XHR", - Transport.WEBSOCKET_XHR, pushConfiguration.getTransport()); - Assert.assertEquals("Push fallback transport should be LONG_POLLING.", - Transport.LONG_POLLING, - pushConfiguration.getFallbackTransport()); - } - - @Test - public void uiInitialization_defaultPushConfigurationIsApplied() - throws InvalidRouteConfigurationException { - assertPushConfigurationForComponent(PushDefaultTest.class, - AtmospherePushConnection.class); - } - - @Test - public void uiInitialization_pushConfigurationIsApplied() - throws InvalidRouteConfigurationException { - assertPushConfigurationForComponent(PushConfiguredTest.class, - AtmospherePushConnection.class); - } - - @Test - public void uiInitialization_customPushConnectionFactoryIsApplied() - throws Exception { - ClassLoader classLoader = service.getClassLoader(); - ClassLoader mockClassLoader = mockClassloaderForServiceLoader( - classLoader, "PushConnectionFactory_serviceLoader_single.txt"); - service.setClassLoader(mockClassLoader); - try { - assertPushConfigurationForComponent(PushDefaultTest.class, - TestPushConnection.class); - } finally { - service.setClassLoader(classLoader); - } - } - - @Test - public void uiInitialization_shouldFailIfMultiplePushConnectionFactoryAreAvailable() - throws Exception { - ClassLoader classLoader = service.getClassLoader(); - ClassLoader mockClassLoader = mockClassloaderForServiceLoader( - classLoader, - "PushConnectionFactory_serviceLoader_multiple.txt"); - - service.setClassLoader(mockClassLoader); - try { - assertPushConfigurationForComponent(PushDefaultTest.class, - TestPushConnection.class); - fail("Should fail due to Multiple PushConnectionFactory providers"); - } catch (BootstrapException ex) { - assertThat("Not multiple PushConnectionFactory error", - ex.getMessage(), - containsString(PushConnectionFactory.class.getName())); - } finally { - service.setClassLoader(classLoader); - } - } - - private ClassLoader mockClassloaderForServiceLoader(ClassLoader classLoader, - String s) throws IOException { - URLClassLoader loader = new URLClassLoader(new URL[0], classLoader) { - @Override - public Enumeration findResources(String name) - throws IOException { - if (name.equals( - "META-INF/services/com.vaadin.flow.server.communication.PushConnectionFactory")) { - return Collections.enumeration(Collections - .singletonList(getClass().getResource(s))); - } - return super.findResources(name); - } - }; - return loader; - } - - private void assertPushConfigurationForComponent( - Class annotatedClazz, - Class pushConnectionType) - throws InvalidRouteConfigurationException { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinResponse response = mock(VaadinResponse.class); - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(service.getRouteRegistry()); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - routeConfiguration.setAnnotatedRoute(annotatedClazz); - }); - - final BootstrapHandler.BootstrapContext context = bootstrapHandler - .createAndInitUI(UI.class, createVaadinRequest(), response, - session); - Push pushAnnotation = annotatedClazz.getAnnotation(Push.class); - Assert.assertNotNull("Should have @Push annotated component", - pushAnnotation); - PushConfiguration pushConfiguration = context.getUI() - .getPushConfiguration(); - assertPushConfiguration(pushConfiguration, pushAnnotation); - assertThat(context.getUI().getInternals().getPushConnection(), - instanceOf(pushConnectionType)); - } - - private VaadinRequest createVaadinRequest() { - HttpServletRequest request = createRequest(); - return new VaadinServletRequest(request, service); - } - - private HttpServletRequest createRequest() { - HttpServletRequest request = mock(HttpServletRequest.class); - Mockito.doAnswer(invocation -> "").when(request).getServletPath(); - return request; - } - - private static void assertPushConfiguration( - PushConfiguration pushConfiguration, Push pushAnnotation) { - assertPushConfiguration(pushConfiguration, pushAnnotation.value(), - pushAnnotation.transport(), Transport.LONG_POLLING); - } - - private static void assertPushConfiguration( - PushConfiguration pushConfiguration, PushMode pushMode, - Transport transport, Transport fallbackTransport) { - Assert.assertEquals( - "Push mode should be the same as in @Push annotation.", - pushMode, pushConfiguration.getPushMode()); - Assert.assertEquals( - "Push transport should be the same as in @Push annotation.", - transport, pushConfiguration.getTransport()); - Assert.assertEquals("Push fallback transport should be LONG_POLLING.", - fallbackTransport, Transport.LONG_POLLING); - } - - @Route("") - @Tag(Tag.DIV) - @Push - public static class PushDefaultTest extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Push(value = PushMode.MANUAL, transport = Transport.LONG_POLLING) - public static class PushConfiguredTest extends Component { - } - - public static class TestPushConnection implements PushConnection { - - @Override - public void push() { - } - - @Override - public void disconnect() { - } - - @Override - public boolean isConnected() { - return false; - } - } - - public static class TestPushConnectionFactory1 - implements PushConnectionFactory { - - @Override - public PushConnection apply(UI ui) { - return new TestPushConnection(); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerTest.java deleted file mode 100644 index bfe378db68a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/BootstrapHandlerTest.java +++ /dev/null @@ -1,1836 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.http.HttpServletRequest; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.commons.io.IOUtils; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Html; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.Text; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.StyleSheet; -import com.vaadin.flow.component.page.BodySize; -import com.vaadin.flow.component.page.Inline; -import com.vaadin.flow.component.page.Meta; -import com.vaadin.flow.component.page.TargetElement; -import com.vaadin.flow.component.page.Viewport; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.QueryParameters; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteAlias; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.TestRouteRegistry; -import com.vaadin.flow.server.BootstrapHandler.BootstrapContext; -import com.vaadin.flow.server.MockServletServiceSessionSetup.TestVaadinServletService; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.flow.shared.Registration; -import com.vaadin.flow.shared.VaadinUriResolver; -import com.vaadin.flow.shared.communication.PushMode; -import com.vaadin.flow.shared.ui.Dependency; -import com.vaadin.flow.shared.ui.LoadMode; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import static com.vaadin.flow.server.Constants.VAADIN_MAPPING; -import static com.vaadin.flow.server.Constants.VAADIN_WEBAPP_RESOURCES; -import static com.vaadin.flow.server.frontend.FrontendUtils.INDEX_HTML; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -public class BootstrapHandlerTest { - - static final String UI_TITLE = "UI_TITLE"; - - @PageTitle(UI_TITLE) - @JavaScript(value = "lazy.js", loadMode = LoadMode.LAZY) - @StyleSheet(value = "lazy.css", loadMode = LoadMode.LAZY) - @JavaScript("eager.js") - @StyleSheet("context://eager-relative.css") - @StyleSheet("eager.css") - protected static class TestUI extends UI { - - public TestUI() { - } - - @Override - protected void init(VaadinRequest request) { - super.init(request); - add(new Html("
    foobar
    ")); - add(new Text("Hello world")); - } - - } - - @Route("") - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class InitialPageConfiguratorViewportOverride - extends Component implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.setViewport("width=100"); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorPrependContents extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addInlineWithContents(InitialPageSettings.Position.PREPEND, - "window.messages = window.messages || [];\n" - + "window.messages.push(\"content script\");", - InitialPageSettings.WrapMode.JAVASCRIPT); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorPrependFile extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addInlineFromFile(InitialPageSettings.Position.PREPEND, - "inline.js", InitialPageSettings.WrapMode.JAVASCRIPT); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorAppendFiles extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addInlineFromFile("inline.js", - InitialPageSettings.WrapMode.JAVASCRIPT); - settings.addInlineFromFile("inline.html", - InitialPageSettings.WrapMode.NONE); - settings.addInlineFromFile("inline.css", - InitialPageSettings.WrapMode.STYLESHEET); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorLinks extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addLink("icons/favicon.ico", - new LinkedHashMap() { - { - put("rel", "shortcut icon"); - } - }); - settings.addLink("icons/icon-192.png", - new LinkedHashMap() { - { - put("rel", "icon"); - put("sizes", "192x192"); - } - }); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorLinkShorthands extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addLink("shortcut icon", "icons/favicon.ico"); - settings.addFavIcon("icon", "icons/icon-192.png", "192x192"); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorMetaTag extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addMetaTag(InitialPageSettings.Position.PREPEND, - "theme-color", "#227aef"); - } - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorBodyStyle extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - settings.addInlineWithContents( - "body {width: 100%; height:100vh; margin:0;}", - InitialPageSettings.WrapMode.STYLESHEET); - } - } - - @Route("") - @Tag(Tag.DIV) - @BodySize(height = "10px", width = "20px") - public static class BodySizeAnnotated extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @BodySize - public static class EmptyBodySizeAnnotated extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @BodySize(height = "10px", width = "20px") - @StyleSheet("bodysize.css") - public static class BodySizeAnnotatedAndCss extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class RootNavigationTarget extends Component { - } - - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class Parent extends Component implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(Parent.class) - public static class MiddleParent extends Component implements RouterLayout { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - public static class RootWithParent extends Component { - } - - @Route(value = "", layout = MiddleParent.class) - @Tag(Tag.DIV) - public static class RootWithParents extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = Parent.class) - @Tag(Tag.DIV) - public static class AliasLayout extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Inline("inline.js") - @Inline("inline.html") - @Inline("inline.css") - public static class InlineAnnotations extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Inline(value = "inline.css", position = Inline.Position.PREPEND) - @Inline(value = "inline.html", position = Inline.Position.PREPEND) - @Inline(value = "inline.js", position = Inline.Position.PREPEND) - public static class PrependInlineAnnotations extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Inline(value = "inline.css", target = TargetElement.BODY) - @Inline(value = "inline.html", target = TargetElement.BODY) - @Inline(value = "inline.js", target = TargetElement.BODY) - public static class InlineAnnotationsBodyTarget extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Inline(value = "inline.css", target = TargetElement.BODY, position = Inline.Position.PREPEND) - @Inline(value = "inline.html", target = TargetElement.BODY, position = Inline.Position.PREPEND) - @Inline(value = "inline.js", target = TargetElement.BODY, position = Inline.Position.PREPEND) - public static class PrependInlineAnnotationsBodyTarget extends Component { - } - - @Route("") - @Tag(Tag.DIV) - @Inline(value = "inline.js", wrapping = Inline.Wrapping.STYLESHEET) - public static class ForcedWrapping extends Component { - } - - @Tag(Tag.DIV) - public static abstract class AbstractMain extends Component { - } - - @Route("") - @Tag(Tag.DIV) - public static class ExtendingView extends AbstractMain { - } - - @Route("") - @Tag(Tag.DIV) - public static class InitialPageConfiguratorRoute extends Component - implements PageConfigurator { - - public static final int SECOND_DELAY = 700000; - - @Override - public void configurePage(InitialPageSettings settings) { - settings.getLoadingIndicatorConfiguration() - .setApplyDefaultTheme(false); - settings.getLoadingIndicatorConfiguration() - .setSecondDelay(SECOND_DELAY); - - settings.getPushConfiguration().setPushMode(PushMode.MANUAL); - } - } - - private TestUI testUI; - private BootstrapContext context; - private VaadinRequest request; - private VaadinSession session; - private TestVaadinServletService service; - private MockDeploymentConfiguration deploymentConfiguration; - private MockServletServiceSessionSetup mocks; - private BootstrapHandler.BootstrapPageBuilder pageBuilder = new BootstrapHandler.BootstrapPageBuilder(); - - @Rule - public final TemporaryFolder tmpDir = new TemporaryFolder(); - - @Before - public void setup() throws Exception { - mocks = new MockServletServiceSessionSetup(); - TestRouteRegistry routeRegistry = new TestRouteRegistry(); - - testUI = new TestUI(); - - deploymentConfiguration = mocks.getDeploymentConfiguration(); - deploymentConfiguration.setEnableDevServer(false); - - service = mocks.getService(); - service.setRouteRegistry(routeRegistry); - service.setRouter(new Router(routeRegistry) { - @Override - public void initializeUI(UI ui, Location location) { - // Skip initial navigation during UI.init if no routes have been - // injected - if (routeRegistry.hasNavigationTargets()) { - super.initializeUI(ui, location); - } - } - }); - - session = mocks.getSession(); - - // Update sessionRegistry due to after init change of global registry - SessionRouteRegistry sessionRegistry = new SessionRouteRegistry( - session); - Mockito.when(session.getAttribute(SessionRouteRegistry.class)) - .thenReturn(sessionRegistry); - - testUI.getInternals().setSession(session); - } - - @After - public void tearDown() { - service.setDependencyFilters(null); // Reset to default - session.unlock(); - mocks.cleanup(); - } - - private void initUI(UI ui) { - initUI(ui, createVaadinRequest()); - } - - private void initUI(UI ui, VaadinRequest request) { - this.request = request; - - ui.doInit(request, 0); - ui.getInternals().getRouter().initializeUI(ui, - requestToLocation(request)); - context = new BootstrapContext(request, null, session, ui, - this::contextRootRelativePath); - ui.getInternals().setContextRoot(contextRootRelativePath(request)); - } - - private void initUI(UI ui, VaadinRequest request, - Set> navigationTargets) - throws InvalidRouteConfigurationException { - - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(service.getRouteRegistry()); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - navigationTargets.forEach(routeConfiguration::setAnnotatedRoute); - }); - - initUI(ui, request); - } - - @Test - public void testInitialPageTitle_pageSetTitle_noExecuteJavascript() { - initUI(testUI, createVaadinRequest()); - String overriddenPageTitle = "overridden"; - testUI.getPage().setTitle(overriddenPageTitle); - - assertEquals(overriddenPageTitle, - BootstrapHandler.resolvePageTitle(context).get()); - - assertEquals(0, testUI.getInternals().dumpPendingJavaScriptInvocations() - .size()); - } - - @Test - public void testInitialPageTitle_nullTitle_noTitle() { - initUI(testUI, createVaadinRequest()); - assertFalse(BootstrapHandler.resolvePageTitle(context).isPresent()); - } - - @Test - public void renderUI() throws IOException { - TestUI anotherUI = new TestUI(); - initUI(testUI); - anotherUI.getInternals().setSession(session); - VaadinRequest vaadinRequest = createVaadinRequest(); - anotherUI.doInit(vaadinRequest, 0); - anotherUI.getInternals().getRouter().initializeUI(anotherUI, - requestToLocation(request)); - anotherUI.getInternals() - .setContextRoot(contextRootRelativePath(request)); - BootstrapContext bootstrapContext = new BootstrapContext(vaadinRequest, - null, session, anotherUI, this::contextRootRelativePath); - - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - Element body = page.body(); - - assertEquals(2, body.childNodeSize()); - assertEquals("noscript", body.child(0).tagName()); - } - - @Test // #1134 - public void testBody() throws Exception { - initUI(testUI, createVaadinRequest()); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Element body = page.head().nextElementSibling(); - - assertEquals("body", body.tagName()); - assertEquals("html", body.parent().tagName()); - assertEquals(2, body.parent().childNodeSize()); - } - - @Test // #2956 - public void head_has_ui_lang() throws Exception { - initUI(testUI, createVaadinRequest()); - testUI.setLocale(Locale.FRENCH); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Element body = page.head().nextElementSibling(); - - assertEquals("Expected body element", "body", body.tagName()); - assertEquals("Expected html element as parent to body element", "html", - body.parent().tagName()); - - assertTrue("Html tag was missing lang attribute", - body.parent().hasAttr("lang")); - assertEquals("Lang did not have UI defined language", - testUI.getLocale().getLanguage(), body.parent().attr("lang")); - } - - @Test // #3008 - public void bootstrap_page_has_viewport_for_route() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(RootNavigationTarget.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Assert.assertTrue("Viewport meta tag was missing", - page.toString().contains( - "")); - } - - @Test // #3008 - public void bootstrap_page_has_viewport_for_route_parent() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(RootWithParent.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Assert.assertTrue("Viewport meta tag was missing", - page.toString().contains( - "")); - } - - @Test // #3008 - public void bootstrap_page_has_viewport_for_route_top_parent() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(RootWithParents.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Assert.assertTrue("Viewport meta tag was missing", - page.toString().contains( - "")); - } - - @Test // #3008 - public void bootstrap_page_has_viewport_for_route_alias_parent() - throws InvalidRouteConfigurationException { - HttpServletRequest httpRequest = Mockito.mock(HttpServletRequest.class); - Mockito.doAnswer(invocation -> "").when(httpRequest).getServletPath(); - VaadinServletRequest vaadinRequest = new VaadinServletRequest( - httpRequest, service); - - initUI(testUI, vaadinRequest, Collections.singleton(AliasLayout.class)); - - Document page = pageBuilder - .getBootstrapPage(new BootstrapContext(vaadinRequest, null, - session, testUI, this::contextRootRelativePath)); - - Assert.assertFalse("Viewport found even though not part of Route", - page.toString().contains( - "")); - - Mockito.doAnswer(invocation -> "/alias").when(httpRequest) - .getPathInfo(); - - page = pageBuilder.getBootstrapPage(new BootstrapContext(vaadinRequest, - null, session, testUI, this::contextRootRelativePath)); - - Assert.assertTrue( - "Viewport meta tag was missing even tough alias route parent has annotation", - page.toString().contains( - "")); - } - - @Test // 3036 - public void page_configurator_overrides_viewport() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), Collections - .singleton(InitialPageConfiguratorViewportOverride.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Assert.assertFalse( - "Viewport annotation value found even if it should be overridden.", - page.toString().contains( - "")); - - Assert.assertTrue("Viewport annotation value not the expected one.", - page.toString().contains( - "")); - } - - @Test // 3036 - public void page_configurator_inlines_javascript_from_content() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), Collections - .singleton(InitialPageConfiguratorPrependContents.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - // Note element 0 is the full head element. - assertStringEquals( - "Content javascript should have been prepended to head element", - "", - allElements.get(2).toString()); - } - - @Test // 3036 - public void page_configurator_inlines_prepend_javascript_from_file() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), Collections - .singleton(InitialPageConfiguratorPrependFile.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - // Note element 0 is the full head element. - assertStringEquals( - "Content javascript should have been prepended to head element", - "", - allElements.get(2).toString()); - } - - @Test // 3036 - public void page_configurator_append_inline_form_files() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), Collections - .singleton(InitialPageConfiguratorAppendFiles.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - String scripts = page.getElementsByTag("script").toString(); - // Note element 0 is the full head element. - Assert.assertTrue( - "File javascript should have been appended to head element", - scripts.contains(String.format( - ""))); - Assert.assertTrue("File html should have been appended to head element", - scripts.contains( - String.format(""))); - - String styles = page.getElementsByTag("style").toString(); - Assert.assertTrue("File css should have been appended to head element", - styles.contains(String - .format(""))); - } - - @Test // 3036 - public void page_configurator_adds_link() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(InitialPageConfiguratorLinks.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - - Assert.assertEquals( - "", - allElements.get(allElements.size() - 2).toString()); - Assert.assertEquals( - "", - allElements.get(allElements.size() - 1).toString()); - } - - @Test // 3036 - public void page_configurator_adds_meta_tags() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(InitialPageConfiguratorMetaTag.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - - Assert.assertEquals("", - allElements.get(2).toString()); - } - - @Test // 3203 - public void page_configurator_link_shorthands_are_added_correctly() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), Collections - .singleton(InitialPageConfiguratorLinkShorthands.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - - Assert.assertEquals( - "", - allElements.get(allElements.size() - 2).toString()); - Assert.assertEquals( - "", - allElements.get(allElements.size() - 1).toString()); - } - - @Test // 2344 - public void page_configurator_adds_styles_for_body() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(InitialPageConfiguratorBodyStyle.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - - Assert.assertEquals( - "", - allElements.get(allElements.size() - 1).toString()); - } - - @Test // 2344 - public void body_size_adds_styles_for_body() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(BodySizeAnnotated.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - - Optional styleTag = allElements.stream() - .filter(element -> element.tagName().equals("style")) - .findFirst(); - - Assert.assertTrue("Expected a style element in head.", - styleTag.isPresent()); - - Assert.assertTrue( - "The first style tag should start with body style from @BodySize", - styleTag.get().toString().startsWith( - "", - allElements.get(allElements.size() - 1).toString()); - } - - @Test // 3010 - public void use_inline_to_prepend_files_to_head() - throws InvalidRouteConfigurationException { - initUI(testUI, createVaadinRequest(), - Collections.singleton(PrependInlineAnnotations.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - // Note element 0 is the full head element. - assertStringEquals( - "File javascript should have been prepended to head element", - "", - allElements.get(2).toString()); - assertStringEquals( - "File html should have been prepended to head element", - "", - allElements.get(3).toString()); - assertStringEquals( - "File css should have been prepended to head element", - "", - allElements.get(4).toString()); - } - - @Test // 3010 - public void use_inline_to_append_files_to_body() - throws InvalidRouteConfigurationException { - initUI(testUI, createVaadinRequest(), - Collections.singleton(InlineAnnotationsBodyTarget.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.body().getAllElements(); - assertStringEquals("File css should have been appended to body element", - "", - allElements.get(allElements.size() - 4).toString()); - assertStringEquals( - "File html should have been appended to body element", - "", - allElements.get(allElements.size() - 3).toString()); - assertStringEquals( - "File javascript should have been appended to body element", - "", - allElements.get(allElements.size() - 2).toString()); - } - - @Test // 3010 - public void use_inline_to_prepend_files_to_body() - throws InvalidRouteConfigurationException { - initUI(testUI, createVaadinRequest(), Collections - .singleton(PrependInlineAnnotationsBodyTarget.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.body().getAllElements(); - // Note element 0 is the full head element. - assertStringEquals( - "File javascript should have been prepended to body element", - "", - allElements.get(1).toString()); - assertStringEquals( - "File html should have been prepended to body element", - "", - allElements.get(2).toString()); - assertStringEquals( - "File css should have been prepended to body element", - "", - allElements.get(3).toString()); - } - - @Test // 3010 - public void force_wrapping_of_file() - throws InvalidRouteConfigurationException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(ForcedWrapping.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - assertTrue("File css should have been prepended to body element", page - .getElementsByTag("style").toString() - .contains(String.format( - ""))); - } - - @Test - public void webpack_index_appended_to_head_in_npm() - throws InvalidRouteConfigurationException, IOException { - - initUI(testUI, createVaadinRequest(), - Collections.singleton(AliasLayout.class)); - - enableWebpackFeature(); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements allElements = page.head().getAllElements(); - - Assert.assertTrue( - "index.js should be added to head for ES6 browsers. (type module with crossorigin)", - allElements.stream().map(Object::toString) - .anyMatch(element -> element - .equals(""))); - } - - @Test - public void headHasMetaTags() throws Exception { - initUI(testUI, createVaadinRequest()); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Element head = page.head(); - Elements metas = head.getElementsByTag("meta"); - - Assert.assertEquals(3, metas.size()); - Element meta = metas.get(0); - assertEquals("Content-Type", meta.attr("http-equiv")); - assertEquals("text/html; charset=utf-8", meta.attr("content")); - - meta = metas.get(1); - assertEquals("X-UA-Compatible", meta.attr("http-equiv")); - assertEquals("IE=edge", meta.attr("content")); - - meta = metas.get(2); - assertEquals(BootstrapHandler.VIEWPORT, meta.attr("name")); - assertEquals(Viewport.DEFAULT, - meta.attr(BootstrapHandler.CONTENT_ATTRIBUTE)); - } - - @Test - public void bootstrapListener_isInvokedInServerSideMode() - throws ServiceException { - AtomicReference resolver = new AtomicReference<>(); - service.addBootstrapListener(evt -> evt.getDocument().head() - .getElementsByTag("script").remove()); - service.addBootstrapListener(evt -> { - resolver.set(evt.getUriResolver()); - evt.getDocument().head().appendElement("script").attr("src", - "testing.1"); - }); - service.addBootstrapListener(evt -> evt.getDocument().head() - .appendElement("script").attr("src", "testing.2")); - - initUI(testUI); - - BootstrapContext bootstrapContext = new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath); - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - - Elements scripts = page.head().getElementsByTag("script"); - assertEquals(2, scripts.size()); - assertEquals("testing.1", scripts.get(0).attr("src")); - assertEquals("testing.2", scripts.get(1).attr("src")); - - Assert.assertNotNull(resolver.get()); - Assert.assertEquals(bootstrapContext.getUriResolver(), resolver.get()); - } - - @Test(expected = IllegalStateException.class) - public void bootstrapListener_throwsInClientSideMode() - throws ServiceException { - ServiceInitEvent event = new ServiceInitEvent(service); - event.addBootstrapListener(evt -> { - }); - } - - @Test - public void useDependencyFilters_removeDependenciesAndAddNewOnes() - throws ServiceException { - List filters = Arrays.asList((list, context) -> { - list.clear(); // remove everything - return list; - }, (list, context) -> { - list.add(new Dependency(Dependency.Type.JAVASCRIPT, - "imported-by-filter.js", LoadMode.EAGER)); - list.add(new Dependency(Dependency.Type.JAVASCRIPT, - "imported-by-filter2.js", LoadMode.EAGER)); - return list; - }, (list, context) -> { - list.remove(1); // removes the imported-by-filter2.js - return list; - }, (list, context) -> { - list.add(new Dependency(Dependency.Type.STYLESHEET, - "imported-by-filter.css", LoadMode.EAGER)); - return list; - }); - service.setDependencyFilters(filters); - - initUI(testUI); - - BootstrapContext bootstrapContext = new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath); - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - - Elements scripts = page.head().getElementsByTag("script"); - boolean found = scripts.stream().anyMatch( - element -> element.attr("src").equals("imported-by-filter.js")); - Assert.assertTrue( - "imported-by-filter.js should be in the head of the page", - found); - - found = scripts.stream().anyMatch(element -> element.attr("src") - .equals("imported-by-filter2.js")); - Assert.assertFalse( - "imported-by-filter2.js shouldn't be in the head of the page", - found); - - found = scripts.stream() - .anyMatch(element -> element.attr("src").equals("./eager.js")); - Assert.assertFalse("eager.js shouldn't be in the head of the page", - found); - - Elements links = page.head().getElementsByTag("link"); - found = links.stream().anyMatch(element -> element.attr("href") - .equals("imported-by-filter.css")); - Assert.assertTrue( - "imported-by-filter.css should be in the head of the page", - found); - } - - @Test - public void bootstrapPage_configJsonPatternIsReplacedBeforeInitialUidl() { - TestUI anotherUI = new TestUI(); - initUI(testUI); - - SystemMessages messages = Mockito.mock(SystemMessages.class); - service.setSystemMessagesProvider(info -> messages); - Mockito.when(messages.isSessionExpiredNotificationEnabled()) - .thenReturn(true); - Mockito.when(session.getSession()) - .thenReturn(Mockito.mock(WrappedSession.class)); - - String url = "http://{{CONFIG_JSON}}/file"; - Mockito.when(messages.getSessionExpiredURL()).thenReturn(url); - - anotherUI.getInternals().setSession(session); - VaadinRequest vaadinRequest = createVaadinRequest(); - anotherUI.doInit(vaadinRequest, 0); - anotherUI.getInternals().getRouter().initializeUI(anotherUI, - requestToLocation(request)); - BootstrapContext bootstrapContext = new BootstrapContext(vaadinRequest, - null, session, anotherUI, this::contextRootRelativePath); - anotherUI.getInternals() - .setContextRoot(contextRootRelativePath(request)); - - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - Element head = page.head(); - Assert.assertTrue(head.outerHtml().contains(url)); - } - - @Test // UIInitListeners - public void uiInitialization_allRegisteredListenersAreNotified() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinResponse response = Mockito.mock(VaadinResponse.class); - AtomicReference uiReference = new AtomicReference<>(); - - Registration registration = service.addUIInitListener( - event -> Assert.assertTrue("Atomic reference was not empty.", - uiReference.compareAndSet(null, event.getUI()))); - final BootstrapContext context = bootstrapHandler.createAndInitUI( - TestUI.class, createVaadinRequest(), response, session); - - Assert.assertEquals("Event UI didn't match initialized UI instance.", - context.getUI(), uiReference.get()); - - // unregister listener - registration.remove(); - - AtomicReference secondListenerReference = new AtomicReference<>(); - service.addUIInitListener(event -> Assert.assertTrue( - "Atomic reference did not contain previous UI.", - uiReference.compareAndSet(context.getUI(), event.getUI()))); - service.addUIInitListener(event -> Assert.assertTrue( - "Atomic reference was not empty.", - secondListenerReference.compareAndSet(null, event.getUI()))); - - final BootstrapContext secondInit = bootstrapHandler.createAndInitUI( - TestUI.class, createVaadinRequest(), response, session); - - Assert.assertEquals("Event UI didn't match initialized UI instance.", - secondInit.getUI(), uiReference.get()); - Assert.assertEquals( - "Second event UI didn't match initialized UI instance.", - secondInit.getUI(), secondListenerReference.get()); - } - - @Test // UIInitListeners - public void uiInitialization_changingListenersOnEventWorks() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinResponse response = Mockito.mock(VaadinResponse.class); - - AtomicReference uiReference = new AtomicReference<>(); - - Registration registration = service.addUIInitListener( - event -> service.addUIInitListener(laterEvent -> uiReference - .compareAndSet(null, laterEvent.getUI()))); - bootstrapHandler.createAndInitUI(TestUI.class, createVaadinRequest(), - response, session); - - Assert.assertEquals("Event UI didn't match initialized UI instance.", - null, uiReference.get()); - - // unregister listener - registration.remove(); - - service.addUIInitListener(event -> registration.remove()); - - final BootstrapContext secondInit = bootstrapHandler.createAndInitUI( - TestUI.class, createVaadinRequest(), response, session); - - Assert.assertEquals("Event UI didn't match initialized UI instance.", - secondInit.getUI(), uiReference.get()); - } - - private void bootstrapPage_productionModeTest(boolean productionMode) { - mocks.setProductionMode(productionMode); - TestUI anotherUI = new TestUI(); - initUI(testUI); - - anotherUI.getInternals().setSession(session); - VaadinRequest vaadinRequest = createVaadinRequest(); - anotherUI.doInit(vaadinRequest, 0); - anotherUI.getInternals().getRouter().initializeUI(anotherUI, - requestToLocation(request)); - BootstrapContext bootstrapContext = new BootstrapContext(vaadinRequest, - null, session, anotherUI, this::contextRootRelativePath); - anotherUI.getInternals() - .setContextRoot(contextRootRelativePath(request)); - - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - - Element head = page.head(); - Assert.assertTrue( - head.outerHtml().contains("mode = " + productionMode)); - } - - @Test - public void bootstrapPage_productionModeTrueIsReplaced() { - bootstrapPage_productionModeTest(true); - } - - @Test - public void bootstrapPage_productionModeFalseIsReplaced() { - bootstrapPage_productionModeTest(false); - } - - @Route("") - @Tag(Tag.DIV) - @Meta(name = "apple-mobile-web-app-capable", content = "yes") - @Meta(name = "apple-mobile-web-app-status-bar-style", content = "black") - public static class MetaAnnotations extends Component { - } - - @Test - public void addMultiMetaTagViaMetaAnnotation_MetaSizeCorrect_ContentCorrect() - throws InvalidRouteConfigurationException { - initUI(testUI, createVaadinRequest(), - Collections.singleton(MetaAnnotations.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Element head = page.head(); - Elements metas = head.getElementsByTag("meta"); - - Assert.assertEquals(5, metas.size()); - Element meta = metas.get(0); - assertEquals("Content-Type", meta.attr("http-equiv")); - assertEquals("text/html; charset=utf-8", meta.attr("content")); - - meta = metas.get(1); - assertEquals("X-UA-Compatible", meta.attr("http-equiv")); - assertEquals("IE=edge", meta.attr("content")); - - meta = metas.get(2); - assertEquals(BootstrapHandler.VIEWPORT, meta.attr("name")); - assertEquals(Viewport.DEFAULT, - meta.attr(BootstrapHandler.CONTENT_ATTRIBUTE)); - - meta = metas.get(3); - assertEquals("apple-mobile-web-app-status-bar-style", - meta.attr("name")); - assertEquals("black", meta.attr(BootstrapHandler.CONTENT_ATTRIBUTE)); - - meta = metas.get(4); - assertEquals("apple-mobile-web-app-capable", meta.attr("name")); - assertEquals("yes", meta.attr(BootstrapHandler.CONTENT_ATTRIBUTE)); - } - - @Route("") - @Tag(Tag.DIV) - @Meta(name = "", content = "yes") - public static class MetaAnnotationsContainsNull extends Component { - } - - @Test(expected = IllegalStateException.class) - public void AnnotationContainsNullValue_ExceptionThrown() - throws InvalidRouteConfigurationException { - initUI(testUI, createVaadinRequest(), - Collections.singleton(MetaAnnotationsContainsNull.class)); - - pageBuilder.getBootstrapPage(new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath)); - } - - @Tag(Tag.DIV) - @Meta(name = "apple-mobile-web-app-capable", content = "yes") - public static class MetaAnnotationsWithoutRoute extends Component { - } - - @Test(expected = InvalidRouteConfigurationException.class) - public void AnnotationsWithoutRoute_ExceptionThrown() - throws InvalidRouteConfigurationException { - initUI(testUI, createVaadinRequest(), - Collections.singleton(MetaAnnotationsWithoutRoute.class)); - - pageBuilder.getBootstrapPage(new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath)); - } - - @Test - public void webpack_getBootstrapPage_jsModulesDoNotContainDeferAttribute() - throws ServiceException, IOException { - List filters = Arrays.asList((list, context) -> { - list.clear(); // remove everything - return list; - }, (list, context) -> { - list.add(new Dependency(Dependency.Type.JS_MODULE, "//module.js", - LoadMode.EAGER)); - return list; - }); - service.setDependencyFilters(filters); - - initUI(testUI); - - enableWebpackFeature(); - - BootstrapContext bootstrapContext = new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath); - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - - Elements scripts = page.head().getElementsByTag("script"); - - Element element = scripts.stream() - .filter(elem -> elem.attr("src").equals("//module.js")) - .findFirst().get(); - Assert.assertFalse(element.hasAttr("defer")); - - Element bundle = scripts.stream() - .filter(el -> el.attr("src") - .equals("./VAADIN/build/vaadin-bundle-1111.cache.js")) - .findFirst().get(); - Assert.assertFalse(bundle.hasAttr("defer")); - } - - @Test - public void webpack_getBootstrapPage_removesExportScript() - throws IOException { - initUI(testUI); - enableWebpackFeature(); - - BootstrapContext bootstrapContext = new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath); - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - - Elements scripts = page.head().getElementsByTag("script"); - - Assert.assertTrue(scripts.stream() - .filter(el -> el.attr("src") - .equals("./VAADIN/build/vaadin-bundle-1111.cache.js")) - .findFirst().isPresent()); - Assert.assertFalse(scripts.stream() - .filter(el -> el.attr("src") - .equals("./VAADIN/build/vaadin-export-2222.cache.js")) - .findFirst().isPresent()); - } - - @Test // #7158 - public void webpack_getBootstrapPage_assetChunksIsAnARRAY_bootstrapParsesOk() - throws ServiceException, IOException { - - initUI(testUI); - - enableWebpackFeature(); - - String statsJson = "{\n" + " \"errors\": [],\n" + " \"warnings\": [],\n" - + " \"assetsByChunkName\": {\n" + " \"bundle\": [\n" - + " \"VAADIN/build/vaadin-bundle-e77008557c8d410bf0dc" - + ".cache.js\",\n" - + " \"VAADIN/build/vaadin-bundle-e77008557c8d410bf0dc" - + ".cache.js.map\"\n" + " ],\n" + " }" + "}"; - - File tmpFile = tmpDir.newFile(); - try (FileOutputStream stream = new FileOutputStream(tmpFile)) { - IOUtils.write(statsJson, stream, StandardCharsets.UTF_8); - } - - Lookup lookup = testUI.getSession().getService().getContext() - .getAttribute(Lookup.class); - ResourceProvider provider = lookup.lookup(ResourceProvider.class); - Mockito.when(provider.getApplicationResource(Mockito.anyString())) - .thenReturn(tmpFile.toURI().toURL()); - - BootstrapContext bootstrapContext = new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath); - Document page = pageBuilder.getBootstrapPage(bootstrapContext); - - Elements scripts = page.head().getElementsByTag("script"); - - Element bundle = scripts.stream().filter(el -> el.attr("src").equals( - "./VAADIN/build/vaadin-bundle-e77008557c8d410bf0dc.cache.js")) - .findFirst().get(); - Assert.assertFalse(bundle.hasAttr("defer")); - } - - private void assertStringEquals(String message, String expected, - String actual) { - MatcherAssert.assertThat(message, - actual.replaceAll(System.getProperty("line.separator"), "\n"), - CoreMatchers.equalTo(expected)); - } - - private Element initTestUI() { - TestUI anotherUI = new TestUI(); - initUI(testUI); - anotherUI.getInternals().setSession(session); - VaadinServletRequest vaadinRequest = createVaadinRequest(); - anotherUI.doInit(vaadinRequest, 0); - anotherUI.getInternals().getRouter().initializeUI(anotherUI, - requestToLocation(request)); - BootstrapContext bootstrapContext = new BootstrapContext(vaadinRequest, - null, session, anotherUI, this::contextRootRelativePath); - anotherUI.getInternals() - .setContextRoot(contextRootRelativePath(vaadinRequest)); - return pageBuilder.getBootstrapPage(bootstrapContext).head(); - } - - private String contextRootRelativePath(VaadinRequest request) { - VaadinServletService service = Mockito.mock(VaadinServletService.class); - Mockito.doCallRealMethod().when(service) - .getContextRootRelativePath(Mockito.any()); - return service.getContextRootRelativePath(request); - } - - private VaadinServletRequest createVaadinRequest() { - return createVaadinRequest(null); - } - - private VaadinServletRequest createVaadinRequest(String pathInfo) { - HttpServletRequest request = createRequest(pathInfo); - return new VaadinServletRequest(request, service); - } - - private HttpServletRequest createRequest() { - return createRequest(null); - } - - private HttpServletRequest createRequest(String pathInfo) { - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Mockito.doAnswer(invocation -> "").when(request).getServletPath(); - if (pathInfo != null) { - Mockito.doAnswer(invocation -> pathInfo).when(request) - .getPathInfo(); - Mockito.doAnswer(invocation -> new StringBuffer(pathInfo)) - .when(request).getRequestURL(); - } - return request; - } - - private void checkInlinedScript(Element head, String scriptName, - boolean shouldBeInlined) { - StringBuilder builder = new StringBuilder(); - try (InputStream stream = getClass().getResourceAsStream(scriptName)) { - - IOUtils.readLines(stream, StandardCharsets.UTF_8) - .forEach(builder::append); - } catch (IOException ioe) { - throw new AssertionError(ioe); - } - - boolean inlined = head.getElementsByTag("script").stream() - .anyMatch(script -> script.data().contains(builder.toString())); - if (shouldBeInlined) { - assertTrue(String.format( - "Expect the script '%s' to be inlined in document head", - scriptName), inlined); - } else { - assertFalse(String.format( - "Expect document head NOT to contain script '%s'", - scriptName), inlined); - } - } - - @Test - public void defaultViewport() { - initUI(testUI); - Document page = pageBuilder.getBootstrapPage(context); - Element head = page.head(); - Elements viewports = head.getElementsByAttributeValue("name", - BootstrapHandler.VIEWPORT); - Assert.assertEquals(1, viewports.size()); - Element viewport = viewports.get(0); - Assert.assertEquals(Viewport.DEFAULT, - viewport.attr(BootstrapHandler.CONTENT_ATTRIBUTE)); - - } - - @Viewport("viewport-annotation-value") - @Tag("div") - @Route("") - public static class RouteWithViewport extends Component { - - } - - @Test - public void viewportAnnotationOverridesDefault() throws Exception { - initUI(testUI, createVaadinRequest(), - Collections.singleton(RouteWithViewport.class)); - Document page = pageBuilder.getBootstrapPage(context); - Element head = page.head(); - Elements viewports = head.getElementsByAttributeValue("name", - BootstrapHandler.VIEWPORT); - Assert.assertEquals(1, viewports.size()); - Element viewport = viewports.get(0); - Assert.assertEquals("viewport-annotation-value", - viewport.attr(BootstrapHandler.CONTENT_ATTRIBUTE)); - - } - - @Test - public void testUIConfiguration_usingPageSettings() throws Exception { - Assert.assertTrue("By default loading indicator is themed", testUI - .getLoadingIndicatorConfiguration().isApplyDefaultTheme()); - - initUI(testUI, createVaadinRequest(), - Collections.singleton(InitialPageConfiguratorRoute.class)); - pageBuilder.getBootstrapPage(new BootstrapContext(request, null, - session, testUI, this::contextRootRelativePath)); - - Assert.assertFalse("Default indicator theme is not themed anymore", - testUI.getLoadingIndicatorConfiguration() - .isApplyDefaultTheme()); - - Assert.assertEquals(InitialPageConfiguratorRoute.SECOND_DELAY, - testUI.getLoadingIndicatorConfiguration().getSecondDelay()); - - Assert.assertEquals(PushMode.MANUAL, - testUI.getPushConfiguration().getPushMode()); - } - - @Test - public void internal_request_no_bootstrap_page() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getPathInfo()).thenReturn(null); - Mockito.when(request.getParameter("v-r")).thenReturn("hello-foo-bar"); - Assert.assertTrue(BootstrapHandler.isFrameworkInternalRequest(request)); - Assert.assertFalse(bootstrapHandler.canHandleRequest(request)); - - Mockito.when(request.getParameter("v-r")).thenReturn("init"); - Assert.assertTrue(BootstrapHandler.isFrameworkInternalRequest(request)); - Assert.assertFalse(bootstrapHandler.canHandleRequest(request)); - } - - @Test - public void vaadin_request_no_bootstrap_page() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getPathInfo()).thenReturn("/VAADIN/hello.js"); - Assert.assertFalse(bootstrapHandler.canHandleRequest(request)); - - Mockito.when(request.getPathInfo()) - .thenReturn("/VAADIN/bundle/notfound"); - Assert.assertFalse(bootstrapHandler.canHandleRequest(request)); - - } - - @Test - public void serviceWorkerRequest_canNotHandleRequest() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - - Mockito.when(request.getHeader(BootstrapHandler.SERVICE_WORKER_HEADER)) - .thenReturn("script"); - - Assert.assertFalse(bootstrapHandler.canHandleRequest(request)); - } - - @Test - public void notServiceWorkerRequest_canHandleRequest() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - - Mockito.when(request.getHeader(BootstrapHandler.SERVICE_WORKER_HEADER)) - .thenReturn(null); - - Assert.assertTrue(bootstrapHandler.canHandleRequest(request)); - } - - @Test - public void canHandleRequest_allow_oldBrowser() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - Assert.assertTrue(bootstrapHandler.canHandleRequest( - createRequestWithDestination("/", null, null))); - } - - @Test - public void canHandleRequest_handle_indexHtmlRequest() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - Assert.assertTrue(bootstrapHandler.canHandleRequest( - createRequestWithDestination("/", "document", "navigate"))); - } - - @Test - public void canHandleRequest_doNotHandle_scriptRequest() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - Assert.assertFalse(bootstrapHandler.canHandleRequest( - createRequestWithDestination("/", "script", "no-cors"))); - } - - @Test - public void canHandleRequest_doNotHandle_imageRequest() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - Assert.assertFalse(bootstrapHandler.canHandleRequest( - createRequestWithDestination("/", "image", "no-cors"))); - } - - @Test - public void canHandleRequest_handle_serviceWorkerDocumentRequest() { - BootstrapHandler bootstrapHandler = new BootstrapHandler(); - Assert.assertTrue(bootstrapHandler.canHandleRequest( - createRequestWithDestination("/", "empty", "same-origin"))); - } - - private VaadinServletRequest createRequestWithDestination(String pathInfo, - String fetchDest, String fetchMode) { - VaadinServletRequest req = createVaadinRequest(pathInfo); - Mockito.when(req.getHeader(Mockito.anyString())).thenAnswer(arg -> { - if ("Sec-Fetch-Dest".equals(arg.getArgument(0))) { - return fetchDest; - } else if ("Sec-Fetch-Mode".equals(arg.getArgument(0))) { - return fetchMode; - } - return null; - }); - - return req; - } - - @Test - public void synchronizedHandleRequest_badLocation_noUiCreated() - throws IOException { - final BootstrapHandler bootstrapHandler = new BootstrapHandler(); - - final VaadinServletRequest request = Mockito - .mock(VaadinServletRequest.class); - Mockito.doAnswer(invocation -> "..**").when(request).getPathInfo(); - - final MockServletServiceSessionSetup.TestVaadinServletResponse response = mocks - .createResponse(); - - final boolean value = bootstrapHandler.synchronizedHandleRequest( - mocks.getSession(), request, response); - Assert.assertTrue("No further request handlers should be called", - value); - - Assert.assertEquals("Invalid status code reported", 400, - response.getErrorCode()); - Assert.assertEquals("Invalid message reported", - "Invalid location: Relative path cannot contain .. segments", - response.getErrorMessage()); - } - - @Test - public void synchronizedHandleRequest_requestPathInfoStartsWithSlash_stripped() - throws IOException { - final BootstrapHandler bootstrapHandler = new BootstrapHandler(); - - final VaadinServletRequest request = Mockito - .mock(VaadinServletRequest.class); - Mockito.doAnswer(invocation -> "/foo").when(request).getPathInfo(); - Mockito.doAnswer(invocation -> service).when(request).getService(); - Mockito.doAnswer(invocation -> "/").when(request).getServletPath(); - - final MockServletServiceSessionSetup.TestVaadinServletResponse response = mocks - .createResponse(); - - final boolean value = bootstrapHandler.synchronizedHandleRequest( - mocks.getSession(), request, response); - Assert.assertTrue("No further request handlers should be called", - value); - // status code 200 is set later and tested elsewhere - Assert.assertEquals("Invalid status code reported", 0, - response.getErrorCode()); - } - - @Test - public void synchronizedHandleRequest_requestPathInfoNull_works() - throws IOException { - final BootstrapHandler bootstrapHandler = new BootstrapHandler(); - - final VaadinServletRequest request = Mockito - .mock(VaadinServletRequest.class); - Mockito.doAnswer(invocation -> null).when(request).getPathInfo(); - Mockito.doAnswer(invocation -> service).when(request).getService(); - Mockito.doAnswer(invocation -> "/").when(request).getServletPath(); - - final MockServletServiceSessionSetup.TestVaadinServletResponse response = mocks - .createResponse(); - - final boolean value = bootstrapHandler.synchronizedHandleRequest( - mocks.getSession(), request, response); - Assert.assertTrue("No further request handlers should be called", - value); - - // status code 200 is set later and tested elsewhere - Assert.assertEquals("Invalid status code reported", 0, - response.getErrorCode()); - } - - @Test - public void runViteFeatureDevMode_viteClientAddedToHead() - throws IOException { - initUI(testUI); - - final Document bootstrapPage = pageBuilder.getBootstrapPage(context); - Assert.assertTrue("@vite/client should be added to head.", bootstrapPage - .head().toString().contains("VAADIN/@vite/client")); - } - - @Test - public void runViteFeatureProdMode_bundleAddedToHead() throws IOException { - initUI(testUI); - - deploymentConfiguration.setProductionMode(true); - - final Lookup lookup = service.getContext().getAttribute(Lookup.class); - ResourceProvider resourceProvider = lookup - .lookup(ResourceProvider.class); - - URL resource = Mockito.mock(URL.class); - Mockito.when(resourceProvider - .getApplicationResource(VAADIN_WEBAPP_RESOURCES + INDEX_HTML)) - .thenReturn(resource); - - when(resource.openStream()) - .thenReturn(new ByteArrayInputStream(("\n" - + "\n" + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + "").getBytes())); - - final Document bootstrapPage = pageBuilder.getBootstrapPage(context); - Assert.assertFalse("@vite/client should not be added in productionMode", - bootstrapPage.head().toString() - .contains("VAADIN/@vite/client")); - Assert.assertTrue( - "Bundle should be gotten from index and added to bootstrap page", - bootstrapPage.head().toString() - .contains("src=\"VAADIN/build/main.d253dd35.js\"")); - Assert.assertTrue( - "Bundled css should be gotten from index and added to bootstrap page", - bootstrapPage.head().toString() - .contains("href=\"VAADIN/build/main.688a5538.css\"")); - } - - @Test - public void getBootstrapPage_setsUpHiddenStyles() { - initUI(testUI, createVaadinRequest(), Collections - .singleton(InitialPageConfiguratorAppendFiles.class)); - - Document page = pageBuilder.getBootstrapPage(new BootstrapContext( - request, null, session, testUI, this::contextRootRelativePath)); - - Elements styles = page.head().getElementsByTag("style"); - - assertEquals(2, styles.size()); - - Element addedByBootstrapHandler = styles.get(0); - assertEquals(3, addedByBootstrapHandler.childNodeSize()); - - assertTrue(addedByBootstrapHandler.childNode(2).toString() - .contains("[hidden] { display: none !important; }")); - } - - private void enableWebpackFeature() { - VaadinContext vaadinContext = Mockito.mock(VaadinContext.class); - Lookup lookup = testUI.getSession().getService().getContext() - .getAttribute(Lookup.class); - - Map vaadinContextStore = new HashMap<>(); - vaadinContextStore.put(Lookup.class, lookup); - - Mockito.when(vaadinContext.getAttribute(any())) - .then(i -> vaadinContextStore.get(i.getArgument(0))); - Mockito.when(vaadinContext.getAttribute(any(), any())) - .then(i -> vaadinContextStore.get(i.getArgument(0))); - Mockito.doAnswer( - i -> vaadinContextStore.put(i.getArgument(0), i.getArgument(1))) - .when(vaadinContext).setAttribute(any(), any()); - Mockito.doAnswer(i -> vaadinContextStore - .put(i.getArgument(0).getClass(), i.getArgument(0))) - .when(vaadinContext).setAttribute(any()); - - service.setContext(vaadinContext); - - ApplicationConfiguration configuration = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(configuration.isProductionMode()).thenReturn(false); - Mockito.when(configuration.getJavaResourceFolder()) - .thenReturn(tmpDir.getRoot()); - vaadinContextStore.put(ApplicationConfiguration.class, configuration); - - final FeatureFlags featureFlags = FeatureFlags - .get(testUI.getSession().getService().getContext()); - - featureFlags.setEnabled(FeatureFlags.WEBPACK.getId(), true); - - } - - public static Location requestToLocation(VaadinRequest request) { - return new Location(request.getPathInfo(), - QueryParameters.full(request.getParameterMap())); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/CustomUIClassLoaderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/CustomUIClassLoaderTest.java deleted file mode 100644 index 5cc5cbb60c3..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/CustomUIClassLoaderTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.vaadin.flow.server; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; - -import org.junit.Test; -import org.mockito.Mockito; - -public class CustomUIClassLoaderTest { - - /** - * Stub root - */ - public static class MyUI extends UI { - @Override - protected void init(VaadinRequest request) { - // Nothing to see here - } - } - - /** - * Dummy ClassLoader that just saves the name of the requested class before - * delegating to the default implementation. - */ - public class LoggingClassLoader extends ClassLoader { - - private List requestedClasses = new ArrayList<>(); - - @Override - protected synchronized Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - requestedClasses.add(name); - return super.loadClass(name, resolve); - } - } - - /** - * Tests that a UI class can be loaded even if no classloader has been - * provided. - * - * @throws Exception - * if thrown - */ - @Test - public void testWithDefaultClassLoader() throws Exception { - VaadinSession application = createStubApplication(); - application.setConfiguration(createConfigurationMock()); - - Class uiClass = BootstrapHandler - .getUIClass(createRequestMock(getClass().getClassLoader())); - - assertEquals(MyUI.class, uiClass); - } - - private static DeploymentConfiguration createConfigurationMock() { - Properties properties = new Properties(); - properties.put(InitParameters.UI_PARAMETER, MyUI.class.getName()); - VaadinContext context = new MockVaadinContext(); - ApplicationConfiguration config = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(config.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - Mockito.when(config.getBuildFolder()).thenReturn("."); - Mockito.when(config.getContext()).thenReturn(context); - return new DefaultDeploymentConfiguration(config, - CustomUIClassLoaderTest.class, properties); - } - - private static VaadinRequest createRequestMock(ClassLoader classloader) { - // Mock a VaadinService to give the passed classloader - VaadinService configurationMock = Mockito.mock(VaadinService.class); - DeploymentConfiguration deploymentConfiguration = createConfigurationMock(); - Mockito.when(configurationMock.getDeploymentConfiguration()) - .thenReturn(deploymentConfiguration); - Mockito.when(configurationMock.getClassLoader()) - .thenReturn(classloader); - - // Mock a VaadinRequest to give the mocked vaadin service - VaadinRequest requestMock = Mockito.mock(VaadinRequest.class); - Mockito.when(requestMock.getService()).thenReturn(configurationMock); - Mockito.when(requestMock.getService()).thenReturn(configurationMock); - Mockito.when(requestMock.getService()).thenReturn(configurationMock); - - return requestMock; - } - - /** - * Tests that the ClassLoader passed in the ApplicationStartEvent is used to - * load UI classes. - * - * @throws Exception - * if thrown - */ - @Test - public void testWithClassLoader() throws Exception { - LoggingClassLoader loggingClassLoader = new LoggingClassLoader(); - - Class uiClass = BootstrapHandler - .getUIClass(createRequestMock(loggingClassLoader)); - - assertEquals(MyUI.class, uiClass); - assertEquals(1, loggingClassLoader.requestedClasses.size()); - assertEquals(MyUI.class.getName(), - loggingClassLoader.requestedClasses.get(0)); - - } - - private VaadinSession createStubApplication() { - return new AlwaysLockedVaadinSession(new MockVaadinServletService()) { - @Override - public DeploymentConfiguration getConfiguration() { - return createConfigurationMock(); - } - }; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/DefaultDeploymentConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/server/DefaultDeploymentConfigurationTest.java deleted file mode 100644 index fc6d5b2a43f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/DefaultDeploymentConfigurationTest.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.Collections; -import java.util.Properties; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.server.startup.ApplicationConfiguration; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; - -/** - * Tests for {@link DefaultDeploymentConfiguration} - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class DefaultDeploymentConfigurationTest { - - VaadinContext context; - - @Before - public void setup() { - context = new MockVaadinContext(); - } - - @Test - public void testGetSystemPropertyForDefaultPackage() - throws ClassNotFoundException { - Class clazz = Class.forName("ClassInDefaultPackage"); - String value = "value"; - String prop = "prop"; - System.setProperty(prop, value); - Properties initParameters = new Properties(); - ApplicationConfiguration appConfig = setupAppConfig(); - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - DefaultDeploymentConfiguration config = new DefaultDeploymentConfiguration( - appConfig, clazz, initParameters); - assertEquals(value, config.getSystemProperty(prop)); - } - - @Test - public void testGetSystemProperty() { - String value = "value"; - String prop = "prop"; - System.setProperty( - DefaultDeploymentConfigurationTest.class.getPackage().getName() - + '.' + prop, - value); - Properties initParameters = new Properties(); - ApplicationConfiguration appConfig = setupAppConfig(); - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - DefaultDeploymentConfiguration config = new DefaultDeploymentConfiguration( - appConfig, DefaultDeploymentConfigurationTest.class, - initParameters); - assertEquals(value, config.getSystemProperty(prop)); - } - - @Test - public void booleanValueReadIgnoreTheCase_true() { - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_SEND_URLS_AS_PARAMETERS, - "tRUe"); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - assertTrue( - "Boolean value equal to 'true' ignoring case should be interpreted as 'true'", - config.isSendUrlsAsParameters()); - } - - @Test - public void booleanValueReadIgnoreTheCase_false() { - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_SEND_URLS_AS_PARAMETERS, - "FaLsE"); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - - assertFalse( - "Boolean value equal to 'false' ignoring case should be interpreted as 'false'", - config.isSendUrlsAsParameters()); - } - - @Test - public void booleanValueRead_emptyIsTrue() { - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_SEND_URLS_AS_PARAMETERS, ""); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - - assertTrue("Empty boolean value should be interpreted as 'true'", - config.isSendUrlsAsParameters()); - } - - @Test(expected = IllegalArgumentException.class) - public void booleanValueRead_exceptionOnNonBooleanValue() { - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_SEND_URLS_AS_PARAMETERS, - "incorrectValue"); - - createDeploymentConfig(initParameters); - } - - @Test - public void defaultPushUrl() { - Properties initParameters = new Properties(); - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - assertThat(config.getPushURL(), is("")); - } - - @Test - public void pushUrl() { - Properties initParameters = new Properties(); - initParameters.setProperty(InitParameters.SERVLET_PARAMETER_PUSH_URL, - "foo"); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - assertThat(config.getPushURL(), is("foo")); - } - - @Test - public void maxMessageSuspendTimeout_validValue_accepted() { - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_MAX_MESSAGE_SUSPEND_TIMEOUT, - "2700"); - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - assertEquals(2700, config.getMaxMessageSuspendTimeout()); - } - - @Test - public void maxMessageSuspendTimeout_invalidValue_defaultValue() { - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_MAX_MESSAGE_SUSPEND_TIMEOUT, - "kk"); - DefaultDeploymentConfiguration config = createDeploymentConfig( - initParameters); - assertEquals(5000, config.getMaxMessageSuspendTimeout()); - } - - @Test - public void isProductionMode_productionModeIsSetViaParentOnly_productionModeIsTakenFromParent() { - ApplicationConfiguration appConfig = setupAppConfig(); - Mockito.when(appConfig.isProductionMode()).thenReturn(true); - - // Note: application configuration doesn't contain production mode - // parameter ! - Assert.assertNull(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, null)); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - appConfig, new Properties()); - Assert.assertTrue(config.isProductionMode()); - Assert.assertTrue(config.getProperties().isEmpty()); - } - - @Test - public void isProductionMode_productionModeIsSetViaPropertiesAndViaParent_productionModeIsTakenFromProperties() { - ApplicationConfiguration appConfig = setupAppConfig(); - Mockito.when(appConfig.isProductionMode()).thenReturn(false); - - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, - Boolean.TRUE.toString()); - DefaultDeploymentConfiguration config = createDeploymentConfig( - appConfig, initParameters); - // the deployment configuration parameter takes precedence over parent - // config - Assert.assertTrue(config.isProductionMode()); - } - - @Test - public void isXsrfProtectionEnabled_valueIsSetViaParentOnly_valueIsTakenFromParent() { - ApplicationConfiguration appConfig = setupAppConfig(); - Mockito.when(appConfig.isXsrfProtectionEnabled()).thenReturn(true); - - // Note: application configuration doesn't contain production mode - // parameter ! - Assert.assertNull(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, - null)); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - appConfig, new Properties()); - Assert.assertTrue(config.isXsrfProtectionEnabled()); - Assert.assertTrue(config.getProperties().isEmpty()); - } - - @Test - public void isXsrfProtectionEnabled_valueIsSetViaParentOnlyAndViaParent_valueIsTakenFromParent() { - ApplicationConfiguration appConfig = setupAppConfig(); - Mockito.when(appConfig.isXsrfProtectionEnabled()).thenReturn(false); - - Properties initParameters = new Properties(); - initParameters.setProperty( - InitParameters.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, - Boolean.FALSE.toString()); - - DefaultDeploymentConfiguration config = createDeploymentConfig( - appConfig, initParameters); - // the deployment configuration parameter takes precedence over parent - // config - Assert.assertTrue(config.isXsrfProtectionEnabled()); - } - - private DefaultDeploymentConfiguration createDeploymentConfig( - Properties initParameters) { - ApplicationConfiguration appConfig = setupAppConfig(); - return createDeploymentConfig(appConfig, initParameters); - } - - private DefaultDeploymentConfiguration createDeploymentConfig( - ApplicationConfiguration appConfig, Properties initParameters) { - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - Mockito.when(appConfig.getBuildFolder()).thenReturn("."); - Mockito.when(appConfig.getContext()).thenReturn(context); - return new DefaultDeploymentConfiguration(appConfig, - DefaultDeploymentConfigurationTest.class, initParameters); - } - - private ApplicationConfiguration setupAppConfig() { - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(appConfig.getContext()).thenReturn(context); - return appConfig; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/DeploymentConfigurationFactoryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/DeploymentConfigurationFactoryTest.java deleted file mode 100644 index 841130b404a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/DeploymentConfigurationFactoryTest.java +++ /dev/null @@ -1,770 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Files; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.ArrayList; - -import org.apache.commons.io.FileUtils; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.frontend.FallbackChunk; -import com.vaadin.flow.server.frontend.FallbackChunk.CssImportData; -import com.vaadin.flow.server.frontend.FrontendUtils; -import com.vaadin.flow.server.startup.ApplicationConfiguration; - -import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES; -import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE; -import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_TOKEN_FILE; -import static com.vaadin.flow.server.frontend.FrontendUtils.TOKEN_FILE; -import static com.vaadin.flow.server.startup.AbstractConfigurationFactory.DEV_FOLDER_MISSING_MESSAGE; -import static java.util.Collections.emptyMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class DeploymentConfigurationFactoryTest { - - @Rule - public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - private File tokenFile; - private ServletContext contextMock; - - private ApplicationConfiguration appConfiguration; - - private FallbackChunk fallbackChunk; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private Map defaultServletParams = new HashMap<>(); - - private static String globalUserDirValue; - - private static class NoSettings extends VaadinServlet { - } - - private static class TestUI extends UI { - private static class ServletWithEnclosingUi extends VaadinServlet { - } - } - - @Before - public void setup() throws IOException { - System.setProperty("user.dir", - temporaryFolder.getRoot().getAbsolutePath()); - tokenFile = new File(temporaryFolder.getRoot(), - VAADIN_SERVLET_RESOURCES + TOKEN_FILE); - FileUtils.writeLines(tokenFile, Arrays.asList("{", "}")); - appConfiguration = mockApplicationConfiguration(); - contextMock = Mockito.mock(ServletContext.class); - - defaultServletParams.put(PARAM_TOKEN_FILE, tokenFile.getPath()); - } - - @After - public void tearDown() { - tokenFile.delete(); - } - - @BeforeClass - public static void setupBeforeClass() { - globalUserDirValue = System.getProperty("user.dir"); - } - - @AfterClass - public static void tearDownAfterClass() { - if (globalUserDirValue != null) { - System.setProperty("user.dir", globalUserDirValue); - } - } - - @Test - public void servletWithEnclosingUI_hasItsNameInConfig() throws Exception { - Class servlet = TestUI.ServletWithEnclosingUi.class; - - Map servletConfigParams = new HashMap<>( - new HashMap<>(defaultServletParams)); - - DeploymentConfiguration config = new DeploymentConfigurationFactory() - .createDeploymentConfiguration(servlet, - createVaadinConfigMock(servletConfigParams, - Collections.singletonMap(PARAM_TOKEN_FILE, - tokenFile.getPath()))); - - Class customUiClass = servlet.getEnclosingClass(); - assertTrue(String.format( - "Servlet '%s' should have its enclosing class to be UI subclass, but got: '%s'", - customUiClass, servlet), - UI.class.isAssignableFrom(customUiClass)); - assertEquals(String.format( - "Expected DeploymentConfiguration for servlet '%s' to have its enclosing UI class", - servlet), customUiClass.getName(), config.getUIClassName()); - } - - @Test - public void servletWithNoEnclosingUI_hasDefaultUiInConfig() - throws Exception { - Class servlet = NoSettings.class; - - Map servletConfigParams = new HashMap<>( - defaultServletParams); - - DeploymentConfiguration config = new DeploymentConfigurationFactory() - .createDeploymentConfiguration(servlet, createVaadinConfigMock( - servletConfigParams, emptyMap())); - - Class notUiClass = servlet.getEnclosingClass(); - assertFalse(String.format( - "Servlet '%s' should not have its enclosing class to be UI subclass, but got: '%s'", - notUiClass, servlet), UI.class.isAssignableFrom(notUiClass)); - assertEquals(String.format( - "Expected DeploymentConfiguration for servlet '%s' to have its enclosing UI class", - servlet), UI.class.getName(), config.getUIClassName()); - } - - @Test - public void servletConfigParametersOverrideServletContextParameters() - throws Exception { - Class servlet = NoSettings.class; - - boolean servletConfigProductionModeValue = true; - int servletConfigHeartbeatIntervalValue = 333; - - Map servletConfigParams = new HashMap<>( - defaultServletParams); - servletConfigParams.put(SERVLET_PARAMETER_PRODUCTION_MODE, - Boolean.toString(servletConfigProductionModeValue)); - servletConfigParams.put( - InitParameters.SERVLET_PARAMETER_HEARTBEAT_INTERVAL, - Integer.toString(servletConfigHeartbeatIntervalValue)); - - boolean servletContextProductionModeValue = false; - int servletContextHeartbeatIntervalValue = 444; - - Map servletContextParams = new HashMap<>(); - servletContextParams.put(SERVLET_PARAMETER_PRODUCTION_MODE, - Boolean.toString(servletContextProductionModeValue)); - servletContextParams.put( - InitParameters.SERVLET_PARAMETER_HEARTBEAT_INTERVAL, - Integer.toString(servletContextHeartbeatIntervalValue)); - - DeploymentConfiguration config = new DeploymentConfigurationFactory() - .createDeploymentConfiguration(servlet, createVaadinConfigMock( - servletConfigParams, servletContextParams)); - - assertEquals( - "Unexpected value for production mode, should be the same as in servlet context parameters", - servletConfigProductionModeValue, config.isProductionMode()); - assertEquals( - "Unexpected value for heartbeat interval, should be the same as in servlet context parameters", - servletConfigHeartbeatIntervalValue, - config.getHeartbeatInterval()); - } - - @Test - public void shouldNotThrow_noTokenFile_correctWebPackConfigExists() - throws Exception { - Map map = new HashMap<>(); - map.put(FrontendUtils.PROJECT_BASEDIR, - temporaryFolder.getRoot().getAbsolutePath()); - - File webPack = new File(temporaryFolder.getRoot().getAbsolutePath(), - FrontendUtils.WEBPACK_CONFIG); - FileUtils.writeLines(webPack, Arrays.asList("./webpack.generated.js")); - - new DeploymentConfigurationFactory().createDeploymentConfiguration( - VaadinServlet.class, createVaadinConfigMock(map, emptyMap())); - } - - @Test - public void should_readConfigurationFromTokenFile() throws Exception { - FileUtils.writeLines(tokenFile, - Arrays.asList("{", "\"productionMode\": true", "}")); - - DeploymentConfiguration config = createConfig(Collections - .singletonMap(PARAM_TOKEN_FILE, tokenFile.getPath())); - assertTrue(config.isProductionMode()); - } - - @Test - public void shouldThrow_tokenFileContainsNonExistingNpmFolderInDevMode() - throws Exception { - exception.expect(IllegalStateException.class); - exception.expectMessage( - String.format(DEV_FOLDER_MISSING_MESSAGE, "npm")); - FileUtils.writeLines(tokenFile, - Arrays.asList("{", "\"productionMode\": false,", - "\"npmFolder\": \"npm\",", - "\"generatedFolder\": \"generated\",", - "\"frontendFolder\": \"frontend\"", "}")); - - createConfig(Collections.singletonMap(PARAM_TOKEN_FILE, - tokenFile.getPath())); - } - - @Test - public void shouldThrow_tokenFileContainsNonExistingFrontendFolderNoNpmFolder() - throws Exception { - exception.expect(IllegalStateException.class); - exception.expectMessage( - String.format(DEV_FOLDER_MISSING_MESSAGE, "frontend")); - FileUtils.writeLines(tokenFile, - Arrays.asList("{", "\"productionMode\": false,", - "\"frontendFolder\": \"frontend\"", "}")); - - createConfig(Collections.singletonMap(PARAM_TOKEN_FILE, - tokenFile.getPath())); - } - - @Test - public void shouldThrow_tokenFileContainsNonExistingFrontendFolderOutsideNpmSubFolder() - throws Exception { - exception.expect(IllegalStateException.class); - exception.expectMessage( - String.format(DEV_FOLDER_MISSING_MESSAGE, "frontend")); - temporaryFolder.newFolder("npm"); - String tempFolder = temporaryFolder.getRoot().getAbsolutePath() - .replace("\\", "/"); - FileUtils.writeLines(tokenFile, - Arrays.asList("{", "\"productionMode\": false,", - "\"npmFolder\": \"" + tempFolder + "/npm\",", - "\"frontendFolder\": \"frontend\"", "}")); - - createConfig(Collections.singletonMap(PARAM_TOKEN_FILE, - tokenFile.getPath())); - } - - @Test - public void shouldNotThrow_tokenFileFrontendFolderInDevMode() - throws Exception { - temporaryFolder.newFolder("npm"); - String tempFolder = temporaryFolder.getRoot().getAbsolutePath() - .replace("\\", "/"); - FileUtils.writeLines(tokenFile, Arrays.asList("{", - "\"productionMode\": false,", - "\"npmFolder\": \"" + tempFolder + "/npm\",", - "\"frontendFolder\": \"" + tempFolder + "/npm/frontend\"", - "}")); - - createConfig(Collections.singletonMap(PARAM_TOKEN_FILE, - tokenFile.getPath())); - } - - @Test - public void shouldNotThrow_tokenFileFoldersExist() throws Exception { - temporaryFolder.newFolder("npm"); - temporaryFolder.newFolder("frontend"); - String tempFolder = temporaryFolder.getRoot().getAbsolutePath() - .replace("\\", "/"); - FileUtils.writeLines(tokenFile, - Arrays.asList("{", "\"productionMode\": false,", - "\"npmFolder\": \"" + tempFolder + "/npm\",", - "\"frontendFolder\": \"" + tempFolder + "/frontend\"", - "}")); - - createConfig(Collections.singletonMap(PARAM_TOKEN_FILE, - tokenFile.getPath())); - } - - @Test - public void createInitParameters_valuesFromContextAreIgnored_valuesAreTakenFromservletConfig() - throws Exception { - DeploymentConfigurationFactory factory = new DeploymentConfigurationFactory(); - - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinConfig config = Mockito.mock(VaadinConfig.class); - - Mockito.when(config.getVaadinContext()).thenReturn(context); - - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - - Mockito.when(config.getConfigParameterNames()).thenReturn( - Collections.enumeration(Collections.singleton("foo"))); - Mockito.when(context.getContextParameterNames()).thenReturn( - Collections.enumeration(Collections.singleton("bar"))); - - Mockito.when(config.getConfigParameter("foo")).thenReturn("baz"); - Mockito.when(context.getContextParameter("bar")).thenReturn("foobar"); - - Mockito.when(context.getAttribute( - Mockito.eq(ApplicationConfiguration.class), Mockito.any())) - .thenReturn(appConfig); - - Properties parameters = factory.createInitParameters(Object.class, - config); - - Assert.assertEquals("baz", parameters.get("foo")); - Assert.assertFalse(parameters.contains("bar")); - } - - @Test - public void createInitParameters_valuesAreTakenFromservletConfigAndTokenFile_valuesFromTokenFileOverridenByServletConfig() - throws Exception { - DeploymentConfigurationFactory factory = new DeploymentConfigurationFactory(); - - Set stringParams = new HashSet<>(Arrays.asList( - InitParameters.UI_PARAMETER, - InitParameters.SERVLET_PARAMETER_REQUEST_TIMING, - InitParameters.SERVLET_PARAMETER_HEARTBEAT_INTERVAL, - InitParameters.SERVLET_PARAMETER_PUSH_URL, - InitParameters.SERVLET_PARAMETER_PUSH_SUSPEND_TIMEOUT_LONGPOLLING, - InitParameters.SERVLET_PARAMETER_MAX_MESSAGE_SUSPEND_TIMEOUT, - InitParameters.SERVLET_PARAMETER_STATISTICS_JSON, - InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_SUCCESS_PATTERN, - InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_ERROR_PATTERN, - InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_TIMEOUT, - InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_OPTIONS, - InitParameters.SERVLET_PARAMETER_DEVMODE_VITE_OPTIONS, - InitParameters.COMPILED_WEB_COMPONENTS_PATH, - InitParameters.NODE_VERSION, InitParameters.NODE_DOWNLOAD_ROOT, - InitParameters.BUILD_FOLDER)); - Field[] initParamFields = InitParameters.class.getDeclaredFields(); - String mockTokenJsonString = generateJsonStringFromFields( - initParamFields, stringParams); - VaadinConfig config = mockTokenFileViaContextParam(mockTokenJsonString); - List allParamsList = mockParamsFromFields(initParamFields, - config, stringParams); - allParamsList.add(FrontendUtils.PARAM_TOKEN_FILE); - // let's not set production mode to see if token setting still - // works - allParamsList.removeIf(paramString -> paramString - .equals(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE)); - Mockito.when(config.getConfigParameterNames()) - .thenReturn(Collections.enumeration(allParamsList)); - - Properties parameters = factory.createInitParameters(Object.class, - config); - - for (int i = 0; i < initParamFields.length; i++) { - String paramName = (String) initParamFields[i].get(null); - mockTokenJsonString += "'" + paramName + "': "; - if (!stringParams.contains(paramName)) { - // the one we set from flow-build-info.json - if (paramName.equals( - InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE)) { - Assert.assertEquals( - InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE - + " (boolean parameter) does not have expected value set from token file", - "true", parameters.get(paramName)); - } else { - Assert.assertEquals(paramName - + " (boolean parameter) does not have expected value set from servlet config", - "false", parameters.get(paramName)); - } - } else { - Assert.assertEquals(paramName - + "(string parameter) does not have expected value set from servlet config", - "foo", parameters.get(paramName)); - } - } - } - - private List mockParamsFromFields(Field[] fields, - VaadinConfig config, Set stringParams) { - List allParamsList = new ArrayList(); - for (int i = 0; i < fields.length; i++) { - try { - String paramName = (String) fields[i].get(null); - if (!stringParams.contains(paramName)) { - Mockito.when(config.getConfigParameter(paramName)) - .thenReturn("false"); - } else { - Mockito.when(config.getConfigParameter(paramName)) - .thenReturn("foo"); - } - allParamsList.add(paramName); - } catch (IllegalAccessException illegalAccess) { - Assert.fail("Illegal access to InitParameters class: " - + illegalAccess.getMessage()); - } - } - return allParamsList; - } - - private String generateJsonStringFromFields(Field[] fields, - Set stringParams) { - String mockTokenJsonString = "{"; - for (int i = 0; i < fields.length; i++) { - try { - String paramName = (String) fields[i].get(null); - mockTokenJsonString += "'" + paramName + "': "; - if (!stringParams.contains(paramName)) { - mockTokenJsonString += "true"; - } else { - mockTokenJsonString += " 'bar'"; - } - - } catch (IllegalAccessException illegalAccess) { - Assert.fail("Illegal access to InitParameters class: " - + illegalAccess.getMessage()); - } - if (i < fields.length - 1) { - mockTokenJsonString += ","; - } - } - mockTokenJsonString += " }"; - return mockTokenJsonString; - } - - @Test - public void createInitParameters_tokenFileIsSetViaContext_externalStatsUrlIsReadFromTokenFile_predefinedProperties() - throws Exception { - DeploymentConfigurationFactory factory = new DeploymentConfigurationFactory(); - - VaadinConfig config = mockTokenFileViaContextParam( - "{ 'externalStatsUrl': 'http://my.server/static/stats.json'}"); - - Properties parameters = factory.createInitParameters(Object.class, - config); - - Assert.assertEquals("http://my.server/static/stats.json", - parameters.get(Constants.EXTERNAL_STATS_URL)); - Assert.assertEquals(Boolean.TRUE.toString(), - parameters.get(Constants.EXTERNAL_STATS_FILE)); - Assert.assertEquals(Boolean.FALSE.toString(), parameters - .get(InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER)); - } - - @Test - public void createInitParameters_tokenFileIsSetViaContext_externalStatsFileIsReadFromTokenFile_predefinedProperties() - throws Exception { - DeploymentConfigurationFactory factory = new DeploymentConfigurationFactory(); - - VaadinConfig config = mockTokenFileViaContextParam( - "{ 'externalStatsFile': true}"); - - Properties parameters = factory.createInitParameters(Object.class, - config); - - Assert.assertEquals(Boolean.TRUE.toString(), - parameters.get(Constants.EXTERNAL_STATS_FILE)); - Assert.assertEquals(Boolean.FALSE.toString(), parameters - .get(InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER)); - } - - @Test - public void createInitParameters_tokenFileIsSetViaContext_setPropertyFromTokenFile() - throws Exception { - DeploymentConfigurationFactory factory = new DeploymentConfigurationFactory(); - - VaadinConfig config = mockTokenFileViaContextParam( - "{ '" + SERVLET_PARAMETER_PRODUCTION_MODE + "': true}"); - - Properties parameters = factory.createInitParameters(Object.class, - config); - - Assert.assertEquals(Boolean.TRUE.toString(), - parameters.get(SERVLET_PARAMETER_PRODUCTION_MODE)); - } - - private VaadinConfig mockTokenFileViaContextParam(String content) - throws IOException { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinConfig config = Mockito.mock(VaadinConfig.class); - - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - - Mockito.when(config.getConfigParameterNames()) - .thenReturn(Collections.enumeration( - Collections.singleton(FrontendUtils.PARAM_TOKEN_FILE))); - Mockito.when(context.getContextParameterNames()) - .thenReturn(Collections.emptyEnumeration()); - - Mockito.when(config.getVaadinContext()).thenReturn(context); - - File tmpFile = temporaryFolder.newFile(); - Files.write(tmpFile.toPath(), Collections.singletonList(content)); - - Mockito.when( - context.getContextParameter(FrontendUtils.PARAM_TOKEN_FILE)) - .thenReturn(tmpFile.getPath()); - - Mockito.when(config.getConfigParameter(FrontendUtils.PARAM_TOKEN_FILE)) - .thenReturn(tmpFile.toString()); - - Mockito.when(context.getAttribute( - Mockito.eq(ApplicationConfiguration.class), Mockito.any())) - .thenReturn(appConfig); - - return config; - } - - @Test - public void externalStatsFileTrue_predefinedValuesAreNotOverridden() - throws Exception { - // note that this situation shouldn't happen that the other - // settings - // would be against the external usage. - FileUtils.writeLines(tokenFile, - Arrays.asList("{", "\"enableDevServer\": true,", - // production mode can be - // altered even when external - // stats - // are used - "\"productionMode\": true,", - "\"externalStatsFile\": true", "}")); - - DeploymentConfiguration config = createConfig(Collections - .singletonMap(PARAM_TOKEN_FILE, tokenFile.getPath())); - - assertEquals(true, config.isProductionMode()); - assertEquals(false, config.enableDevServer()); - assertEquals(true, config.isStatsExternal()); - assertEquals(Constants.DEFAULT_EXTERNAL_STATS_URL, - config.getExternalStatsUrl()); - } - - @Test - public void createInitParameters_fallbackChunkIsCreatedViaAppConfig_fallbackChunkObjectIsInInitParams() - throws IOException { - ServletContext context = Mockito.mock(ServletContext.class); - ServletConfig config = Mockito.mock(ServletConfig.class); - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(config.getServletContext()).thenReturn(context); - - Mockito.when(config.getInitParameterNames()) - .thenReturn(Collections.emptyEnumeration()); - - Mockito.when( - context.getAttribute(ApplicationConfiguration.class.getName())) - .thenReturn(appConfig); - - Mockito.when(appConfig.getFallbackChunk()).thenReturn(fallbackChunk); - - Properties properties = new DeploymentConfigurationFactory() - .createInitParameters(Object.class, - new VaadinServletConfig(config)); - Object object = properties - .get(DeploymentConfigurationFactory.FALLBACK_CHUNK); - - Assert.assertSame(fallbackChunk, object); - } - - @Test - public void createInitParameters_servletConfigDefinesTokenFile_fallbackChunkObjectIsInInitParams() - throws IOException { - ServletContext context = Mockito.mock(ServletContext.class); - ServletConfig config = Mockito.mock(ServletConfig.class); - Mockito.when(config.getServletContext()).thenReturn(context); - Mockito.when(config.getInitParameterNames()) - .thenReturn(Collections.enumeration( - Collections.singleton(FrontendUtils.PARAM_TOKEN_FILE))); - - File tokenFile = temporaryFolder.newFile(); - - Mockito.when(config.getInitParameter(FrontendUtils.PARAM_TOKEN_FILE)) - .thenReturn(tokenFile.getPath()); - - Files.write(tokenFile.toPath(), - Collections.singletonList("{ 'chunks': { " + "'fallback': {" - + " 'jsModules': ['foo', 'bar']," - + " 'cssImports': [ { 'value' :'foo-value' , 'id': 'bar-id'}]" - + "}}" + "}")); - - Mockito.when(context.getInitParameter(FrontendUtils.PARAM_TOKEN_FILE)) - .thenReturn(tokenFile.getPath()); - - Properties properties = new DeploymentConfigurationFactory() - .createInitParameters(Object.class, - new VaadinServletConfig(config)); - - Object object = properties - .get(DeploymentConfigurationFactory.FALLBACK_CHUNK); - - Assert.assertTrue(object instanceof FallbackChunk); - - FallbackChunk chunk = (FallbackChunk) object; - Set modules = chunk.getModules(); - Assert.assertEquals(2, modules.size()); - Assert.assertTrue(modules.contains("foo")); - Assert.assertTrue(modules.contains("bar")); - - Set cssImports = chunk.getCssImports(); - Assert.assertEquals(1, cssImports.size()); - CssImportData data = cssImports.iterator().next(); - Assert.assertEquals("foo-value", data.getValue()); - Assert.assertEquals("bar-id", data.getId()); - } - - @Test - public void createInitParameters_readDevModeProperties() throws Exception { - FileUtils.writeLines(tokenFile, Arrays.asList("{", - "\"pnpm.enable\": true,", "\"require.home.node\": true,", "}")); - - DeploymentConfiguration config = createConfig(Collections - .singletonMap(PARAM_TOKEN_FILE, tokenFile.getPath())); - - Assert.assertEquals(Boolean.TRUE.toString(), config.getInitParameters() - .getProperty(InitParameters.SERVLET_PARAMETER_ENABLE_PNPM)); - Assert.assertEquals(Boolean.TRUE.toString(), config.getInitParameters() - .getProperty(InitParameters.REQUIRE_HOME_NODE_EXECUTABLE)); - } - - @Test - public void createInitParameters_initParamtersAreSet_tokenDevModePropertiesAreNotSet() - throws Exception { - FileUtils.writeLines(tokenFile, Arrays.asList("{", - "\"pnpm.enable\": true,", "\"require.home.node\": true,", "}")); - - DeploymentConfiguration config = createConfig(Collections - .singletonMap(PARAM_TOKEN_FILE, tokenFile.getPath())); - - config.getInitParameters().setProperty( - InitParameters.SERVLET_PARAMETER_ENABLE_PNPM, - Boolean.FALSE.toString()); - config.getInitParameters().setProperty( - InitParameters.REQUIRE_HOME_NODE_EXECUTABLE, - Boolean.FALSE.toString()); - config.getInitParameters().setProperty( - InitParameters.SERVLET_PARAMETER_DEVMODE_OPTIMIZE_BUNDLE, - Boolean.FALSE.toString()); - - Assert.assertEquals(Boolean.FALSE.toString(), config.getInitParameters() - .getProperty(InitParameters.SERVLET_PARAMETER_ENABLE_PNPM)); - Assert.assertEquals(Boolean.FALSE.toString(), config.getInitParameters() - .getProperty(InitParameters.REQUIRE_HOME_NODE_EXECUTABLE)); - Assert.assertEquals(Boolean.FALSE.toString(), - config.getInitParameters().getProperty( - InitParameters.SERVLET_PARAMETER_DEVMODE_OPTIMIZE_BUNDLE)); - } - - private DeploymentConfiguration createConfig(Map map) - throws Exception { - return new DeploymentConfigurationFactory() - .createDeploymentConfiguration(VaadinServlet.class, - createVaadinConfigMock(map, emptyMap())); - } - - private VaadinConfig createVaadinConfigMock( - Map servletConfigParameters, - Map servletContextParameters) throws Exception { - return new VaadinServletConfig(createServletConfigMock( - servletConfigParameters, servletContextParameters)); - } - - private ApplicationConfiguration mockApplicationConfiguration() { - VaadinContext context = new MockVaadinContext(); - ApplicationConfiguration configuration = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(configuration.enableDevServer()).thenReturn(true); - Mockito.when(configuration.isProductionMode()).thenReturn(true); - Mockito.when(configuration.getContext()).thenReturn(context); - Mockito.when(configuration.getStringProperty(Mockito.anyString(), - Mockito.anyString())).thenReturn(null); - Mockito.when(configuration.isXsrfProtectionEnabled()).thenReturn(false); - - Mockito.when(configuration.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - - fallbackChunk = Mockito.mock(FallbackChunk.class); - - Mockito.when(configuration.getFallbackChunk()) - .thenReturn(fallbackChunk); - return configuration; - - } - - private ServletConfig createServletConfigMock( - Map servletConfigParameters, - Map servletContextParameters) throws Exception { - - URLClassLoader classLoader = new URLClassLoader( - new URL[] { temporaryFolder.getRoot().toURI().toURL() }); - - Mockito.when(contextMock - .getAttribute(ApplicationConfiguration.class.getName())) - .thenReturn(appConfiguration); - - Mockito.when(contextMock.getInitParameterNames()).thenReturn( - Collections.enumeration(servletContextParameters.keySet())); - Mockito.when(contextMock.getClassLoader()).thenReturn(classLoader); - - Mockito.when(contextMock.getInitParameter(Mockito.anyString())) - .thenAnswer(answer -> { - String name = answer.getArgument(0); - return servletContextParameters.get(name); - }); - - ResourceProvider provider = Mockito.mock(ResourceProvider.class); - - Lookup lookup = new Lookup() { - - @Override - public Collection lookupAll(Class serviceClass) { - return null; - } - - @Override - public T lookup(Class serviceClass) { - if (ResourceProvider.class.equals(serviceClass)) { - return serviceClass.cast(provider); - } - return null; - } - }; - - Mockito.when(provider - .getApplicationResources(VAADIN_SERVLET_RESOURCES + TOKEN_FILE)) - .thenReturn(Collections.emptyList()); - - Mockito.when(contextMock.getAttribute(Lookup.class.getName())) - .thenReturn(lookup); - - return new ServletConfig() { - @Override - public String getServletName() { - return "whatever"; - } - - @Override - public ServletContext getServletContext() { - return contextMock; - } - - @Override - public String getInitParameter(String name) { - return servletConfigParameters.get(name); - } - - @Override - public Enumeration getInitParameterNames() { - return Collections - .enumeration(servletConfigParameters.keySet()); - } - }; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/HandlerHelperTest.java b/flow-server/src/test/java/com/vaadin/flow/server/HandlerHelperTest.java deleted file mode 100644 index 5fac3bdb5a0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/HandlerHelperTest.java +++ /dev/null @@ -1,380 +0,0 @@ -package com.vaadin.flow.server; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; - -import jakarta.servlet.http.HttpServletRequest; - -import com.vaadin.flow.server.HandlerHelper.RequestType; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -public class HandlerHelperTest { - - private HttpServletRequest createRequest(String pathInfo, - RequestType type) { - return createRequest(pathInfo, - type == null ? null : type.getIdentifier()); - } - - private HttpServletRequest createRequest(String pathInfo, - String typeString) { - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - if ("".equals(pathInfo)) { - pathInfo = null; - } - - Mockito.when(request.getPathInfo()).thenReturn(pathInfo); - Mockito.when(request.getParameter("v-r")).thenReturn(typeString); - return request; - } - - @Test - public void isFrameworkInternalRequest_validType_nullPathInfo() { - HttpServletRequest request = createRequest(null, RequestType.INIT); - - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo", request)); - } - - @Test - public void isFrameworkInternalRequest_validType_emptyPathinfo() { - HttpServletRequest request = createRequest("", RequestType.INIT); - - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo/*", request)); - } - - @Test - public void isFrameworkInternalRequest_validType_slashPathinfo() { - // This is how requests to /vaadinServlet/ are interpreted - HttpServletRequest request = createRequest("/", RequestType.INIT); - - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo/*", request)); - } - - @Test - public void isFrameworkInternalRequest_unknownType() { - HttpServletRequest request = createRequest(null, "unknown"); - - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo/*", request)); - - } - - @Test - public void isFrameworkInternalRequest_noType() { - HttpServletRequest request = createRequest(null, (RequestType) null); - - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo/*", request)); - - } - - @Test - public void isFrameworkInternalRequest_validType_withPath() { - HttpServletRequest request = createRequest("hello", RequestType.INIT); - - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/*", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/foo/*", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/hello", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/hello/*", request)); - } - - @Test - public void isFrameworkInternalRequest_validType_withServletMappingAndPath() { - HttpServletRequest request = createRequest("", RequestType.INIT); - Mockito.when(request.getServletPath()).thenReturn("/servlet"); - - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("", request)); - Assert.assertTrue( - HandlerHelper.isFrameworkInternalRequest("/servlet", request)); - } - - @Test - public void isFrameworkInternalRequest_noType_withServletMappingAndPath() { - HttpServletRequest request = createRequest("/", (RequestType) null); - Mockito.when(request.getServletPath()).thenReturn("/servlet"); - - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/", request)); - Assert.assertFalse( - HandlerHelper.isFrameworkInternalRequest("/servlet", request)); - } - - @Test - public void isFrameworkInternalRequest_vaadinRequest_servletRoot() { - VaadinRequest request = createVaadinRequest("", "/*", RequestType.INIT); - - Assert.assertTrue(BootstrapHandler.isFrameworkInternalRequest(request)); - } - - @Test - public void isFrameworkInternalRequest_vaadinRequest_servletRoot_noType() { - VaadinRequest request = createVaadinRequest("", "/*", null); - - Assert.assertFalse( - BootstrapHandler.isFrameworkInternalRequest(request)); - } - - @Test - public void isFrameworkInternalRequest_vaadinRequest_pathInsideServlet() { - VaadinRequest request = createVaadinRequest("/foo", "/*", - RequestType.INIT); - - Assert.assertFalse( - BootstrapHandler.isFrameworkInternalRequest(request)); - } - - @Test - public void isFrameworkInternalRequest_vaadinRequest_pathInsideServlet_noType() { - VaadinRequest request = createVaadinRequest("/foo", "/*", null); - - Assert.assertFalse( - BootstrapHandler.isFrameworkInternalRequest(request)); - } - - @Test - public void isFrameworkInternalRequest_vaadinRequest_nonRootServlet() { - VaadinRequest request = createVaadinRequest("", "/myservlet/", - RequestType.INIT); - - Assert.assertTrue(BootstrapHandler.isFrameworkInternalRequest(request)); - } - - @Test - public void isFrameworkInternalRequest_vaadinRequest_nonRootServlet_pathInsideServlet() { - VaadinRequest request = createVaadinRequest("/hello", "/myservlet", - null); - - Assert.assertFalse( - BootstrapHandler.isFrameworkInternalRequest(request)); - } - - @Test - public void isFrameworkInternalRequest_uploadUrl() { - VaadinServletRequest request = createVaadinRequest( - "VAADIN/dynamic/resource/1/e83d6b6d-2b75-4960-8922-5431f4a23e49/upload", - "", null); - - Assert.assertTrue(HandlerHelper.isFrameworkInternalRequest("/*", - request.getHttpServletRequest())); - } - - @Test - public void isFrameworkInternalRequest_hillaPushUrl() { - VaadinServletRequest request = createVaadinRequest("HILLA/push", "", - null); - - Assert.assertTrue(HandlerHelper.isFrameworkInternalRequest("/*", - request.getHttpServletRequest())); - } - - @Test - public void isFrameworkInternalRequest_fakeUploadUrl() { - VaadinServletRequest request = createVaadinRequest( - "VAADIN/dynamic/resource/../../../upload", "", null); - - Assert.assertFalse(HandlerHelper.isFrameworkInternalRequest("/*", - request.getHttpServletRequest())); - } - - @Test - public void isFrameworkInternalRequest_staticFileUrl() { - VaadinServletRequest request = createVaadinRequest( - "VAADIN/static/file.png", "", null); - - Assert.assertFalse(HandlerHelper.isFrameworkInternalRequest("/*", - request.getHttpServletRequest())); - } - - @Test - public void getPathIfInsideServlet_default_servlet() { - String servletMapping = "/*"; - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "")); - Assert.assertEquals(Optional.of("/"), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/")); - Assert.assertEquals(Optional.of("foo"), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo")); - Assert.assertEquals(Optional.of("/foo"), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/foo")); - } - - @Test - public void getPathIfInsideServlet_root_only_servlet() { - String servletMapping = ""; - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/foo")); - } - - @Test - public void getPathIfInsideServlet_all_urls_servlet() { - String servletMapping = "/"; - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "")); - Assert.assertEquals(Optional.of("/"), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/")); - Assert.assertEquals(Optional.of("foo"), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo")); - Assert.assertEquals(Optional.of("/foo"), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/foo")); - } - - @Test - public void getPathIfInsideServlet_sevlet_using_single_path() { - String servletMapping = "/foo"; - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "bar")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/bar")); - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo/")); - Assert.assertEquals(Optional.empty(), HandlerHelper - .getPathIfInsideServlet(servletMapping, "foo/bar")); - } - - @Test - public void getPathIfInsideServlet_sevlet_with_context_path() { - String servletMapping = "/foo/*"; - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "bar")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/bar")); - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo")); - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "foo/")); - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/foo")); - Assert.assertEquals(Optional.empty(), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/foos")); - Assert.assertEquals(Optional.empty(), HandlerHelper - .getPathIfInsideServlet(servletMapping, "/foos/bar")); - Assert.assertEquals(Optional.of(""), - HandlerHelper.getPathIfInsideServlet(servletMapping, "/foo/")); - Assert.assertEquals(Optional.of("bar"), HandlerHelper - .getPathIfInsideServlet(servletMapping, "/foo/bar")); - } - - private VaadinServletRequest createVaadinRequest(String requestPath, - String servletPath, RequestType type) { - HttpServletRequest servletRequest = createRequest(requestPath, type); - if (servletPath.equals("/*")) { - // This is what the spec says - // HttpServletRequest#getServletPath - servletPath = ""; - } - Mockito.when(servletRequest.getServletPath()).thenReturn(servletPath); - return new VaadinServletRequest(servletRequest, - Mockito.mock(VaadinServletService.class)); - } - - @Test - public void publicResources() { - Set expected = new HashSet<>(); - expected.add("/favicon.ico"); - expected.add("/manifest.webmanifest"); - expected.add("/sw.js"); - expected.add("/sw-runtime-resources-precache.js"); - expected.add("/offline.html"); - expected.add("/offline-stub.html"); - expected.add("/icons/icon.png"); - expected.add("/icons/icon-144x144.png"); - expected.add("/icons/icon-192x192.png"); - expected.add("/icons/icon-512x512.png"); - expected.add("/icons/icon-16x16.png"); - expected.add("/icons/icon-32x32.png"); - expected.add("/icons/icon-96x96.png"); - expected.add("/icons/icon-180x180.png"); - expected.add("/icons/icon-2048x2732.png"); - expected.add("/icons/icon-2732x2048.png"); - expected.add("/icons/icon-1668x2388.png"); - expected.add("/icons/icon-2388x1668.png"); - expected.add("/icons/icon-1668x2224.png"); - expected.add("/icons/icon-2224x1668.png"); - expected.add("/icons/icon-1620x2160.png"); - expected.add("/icons/icon-2160x1620.png"); - expected.add("/icons/icon-1536x2048.png"); - expected.add("/icons/icon-2048x1536.png"); - expected.add("/icons/icon-1284x2778.png"); - expected.add("/icons/icon-2778x1284.png"); - expected.add("/icons/icon-1170x2532.png"); - expected.add("/icons/icon-2532x1170.png"); - expected.add("/icons/icon-1125x2436.png"); - expected.add("/icons/icon-2436x1125.png"); - expected.add("/icons/icon-1242x2688.png"); - expected.add("/icons/icon-2688x1242.png"); - expected.add("/icons/icon-828x1792.png"); - expected.add("/icons/icon-1792x828.png"); - expected.add("/icons/icon-1242x2208.png"); - expected.add("/icons/icon-2208x1242.png"); - expected.add("/icons/icon-750x1334.png"); - expected.add("/icons/icon-1334x750.png"); - expected.add("/icons/icon-640x1136.png"); - expected.add("/icons/icon-1136x640.png"); - expected.add("/themes/**"); - - Set actual = new HashSet<>(); - Collections.addAll(actual, HandlerHelper.getPublicResources()); - Assert.assertEquals(expected, actual); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/HttpStatusCodeTest.java b/flow-server/src/test/java/com/vaadin/flow/server/HttpStatusCodeTest.java deleted file mode 100644 index 0c7c08ed376..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/HttpStatusCodeTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -public class HttpStatusCodeTest { - - @Test - public void isValidStatusCode_invalidCode_returnsFalse() { - Set validCodes = Stream.of(HttpStatusCode.values()) - .map(HttpStatusCode::getCode).collect(Collectors.toSet()); - - IntStream.rangeClosed(-1000, 1000) - .filter(sc -> !validCodes.contains(sc)) - .forEach(sc -> Assert.assertFalse( - sc + " should be invalid, but was not", - HttpStatusCode.isValidStatusCode(sc))); - } - - @Test - public void isValidStatusCode_validCode_returnsTrue() { - Stream.of(HttpStatusCode.values()).mapToInt(HttpStatusCode::getCode) - .forEach(sc -> Assert.assertTrue( - sc + " should be valid, but was not", - HttpStatusCode.isValidStatusCode(sc))); - - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/I18NProviderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/I18NProviderTest.java deleted file mode 100644 index 3ac7a17b114..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/I18NProviderTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; - -import java.util.Locale; -import java.util.concurrent.locks.ReentrantLock; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.di.DefaultInstantiator; -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.i18n.I18NProvider; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -public class I18NProviderTest { - - private VaadinServletService service; - - private MockDeploymentConfiguration config = new MockDeploymentConfiguration(); - - @Test - public void no_property_defined_should_leave_with_default_locale() - throws ServletException, ServiceException { - initServletAndService(config); - - Assert.assertEquals("Locale was not the expected default locale", - Locale.getDefault(), VaadinSession.getCurrent().getLocale()); - } - - @Test - public void property_defined_should_init_registy_with_provider() - throws ServletException, ServiceException { - config.setApplicationOrSystemProperty(InitParameters.I18N_PROVIDER, - TestProvider.class.getName()); - - initServletAndService(config); - - Assert.assertEquals("Found wrong registry", TestProvider.class, - VaadinService.getCurrent().getInstantiator().getI18NProvider() - .getClass()); - } - - @Test - public void with_defined_provider_locale_should_be_the_available_one() - throws ServletException, ServiceException { - config.setApplicationOrSystemProperty(InitParameters.I18N_PROVIDER, - TestProvider.class.getName()); - - initServletAndService(config); - - I18NProvider i18NProvider = VaadinService.getCurrent().getInstantiator() - .getI18NProvider(); - Assert.assertNotNull("No provider for ", i18NProvider); - - Assert.assertEquals("Locale was not the defined locale", - i18NProvider.getProvidedLocales().get(0), - VaadinSession.getCurrent().getLocale()); - - } - - @After - public void clearCurrentInstances() { - CurrentInstance.clearAll(); - } - - private void initServletAndService(DeploymentConfiguration config) - throws ServletException, ServiceException { - service = new MockVaadinServletService(config) { - @Override - public Instantiator getInstantiator() { - return new DefaultInstantiator(service); - } - }; - - HttpServletRequest httpServletRequest = Mockito - .mock(HttpServletRequest.class); - HttpSession mockHttpSession = Mockito.mock(HttpSession.class); - WrappedSession mockWrappedSession = new WrappedHttpSession( - mockHttpSession) { - final ReentrantLock lock = new ReentrantLock(); - { - lock.lock(); - } - - @Override - public Object getAttribute(String name) { - Object res; - String lockAttribute = service.getServiceName() + ".lock"; - if (lockAttribute.equals(name)) { - res = lock; - } else { - res = super.getAttribute(name); - } - return res; - } - }; - - VaadinRequest request = new VaadinServletRequest(httpServletRequest, - service) { - @Override - public String getParameter(String name) { - if (ApplicationConstants.REQUEST_TYPE_PARAMETER.equals(name)) { - return null; - } - return "1"; - } - - @Override - public WrappedSession getWrappedSession( - boolean allowSessionCreation) { - return mockWrappedSession; - } - }; - - try { - service.findVaadinSession(request); - } catch (SessionExpiredException e) { - throw new RuntimeException(e); - } - - VaadinService.setCurrent(service); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/InitParametersTest.java b/flow-server/src/test/java/com/vaadin/flow/server/InitParametersTest.java deleted file mode 100644 index f8b95b6619e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/InitParametersTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - -import org.junit.Assert; -import org.junit.Test; - -public class InitParametersTest { - @Test - public void publicMembersAreStringConstants() { - for (Field field : InitParameters.class.getDeclaredFields()) { - int modifiers = field.getModifiers(); - if (Modifier.isPublic(modifiers)) { - Assert.assertEquals( - String.format("field '%s' expected String", - field.getName()), - String.class, field.getType()); - Assert.assertTrue(String.format("field '%s' expected static", - field.getName()), Modifier.isStatic(modifiers)); - Assert.assertTrue(String.format("field '%s' expected final", - field.getName()), Modifier.isFinal(modifiers)); - } - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockInstantiator.java b/flow-server/src/test/java/com/vaadin/flow/server/MockInstantiator.java deleted file mode 100644 index 8f1f1261af9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockInstantiator.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.stream.Stream; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.internal.ReflectTools; - -public class MockInstantiator implements Instantiator { - - private VaadinServiceInitListener[] serviceInitListeners; - - public MockInstantiator(VaadinServiceInitListener... serviceInitListeners) { - this.serviceInitListeners = serviceInitListeners; - } - - @Override - public boolean init(VaadinService service) { - return true; - } - - @Override - public Stream getServiceInitListeners() { - return Stream.of(serviceInitListeners); - } - - @Override - public T getOrCreate(Class type) { - return ReflectTools.createInstance(type); - } - - @Override - public T createComponent(Class componentClass) { - return ReflectTools.createInstance(componentClass); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockServletConfig.java b/flow-server/src/test/java/com/vaadin/flow/server/MockServletConfig.java deleted file mode 100644 index 1735afdf426..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockServletConfig.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; - -import java.util.Enumeration; -import java.util.Properties; - -/** - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class MockServletConfig implements ServletConfig { - - private ServletContext context = new MockServletContext(); - - private final Properties initParameters; - - public MockServletConfig() { - this(new Properties()); - } - - public MockServletConfig(Properties initParameters) { - this.initParameters = initParameters; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletConfig#getServletName() - */ - @Override - public String getServletName() { - return "Mock Servlet"; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletConfig#getServletContext() - */ - @Override - public ServletContext getServletContext() { - return context; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletConfig#getInitParameter(java.lang.String) - */ - @Override - public String getInitParameter(String name) { - return initParameters.getProperty(name); - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletConfig#getInitParameterNames() - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public Enumeration getInitParameterNames() { - return initParameters.propertyNames(); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockServletContext.java b/flow-server/src/test/java/com/vaadin/flow/server/MockServletContext.java deleted file mode 100644 index a7da9a2230d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockServletContext.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.EventListener; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterRegistration; -import jakarta.servlet.RequestDispatcher; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.ServletRegistration.Dynamic; -import jakarta.servlet.SessionCookieConfig; -import jakarta.servlet.SessionTrackingMode; -import jakarta.servlet.descriptor.JspConfigDescriptor; - -/** - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class MockServletContext implements ServletContext { - - HashMap sessionAttributes = new HashMap<>(); - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getContext(java.lang.String) - */ - @Override - public ServletContext getContext(String uripath) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getMajorVersion() - */ - @Override - public int getMajorVersion() { - return 3; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getMinorVersion() - */ - @Override - public int getMinorVersion() { - return 0; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getMimeType(java.lang.String) - */ - @Override - public String getMimeType(String file) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getResourcePaths(java.lang.String) - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public Set getResourcePaths(String path) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getResource(java.lang.String) - */ - @Override - public URL getResource(String path) throws MalformedURLException { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getResourceAsStream(java.lang.String) - */ - @Override - public InputStream getResourceAsStream(String path) { - return null; - } - - /* - * (non-Javadoc) - * - * @see - * jakarta.servlet.ServletContext#getRequestDispatcher(java.lang.String) - */ - @Override - public RequestDispatcher getRequestDispatcher(String path) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getNamedDispatcher(java.lang.String) - */ - @Override - public RequestDispatcher getNamedDispatcher(String name) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#log(java.lang.String) - */ - @Override - public void log(String msg) { - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#log(java.lang.String, - * java.lang.Throwable) - */ - @Override - public void log(String message, Throwable throwable) { - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getRealPath(java.lang.String) - */ - @Override - public String getRealPath(String path) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getServerInfo() - */ - @Override - public String getServerInfo() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getInitParameter(java.lang.String) - */ - @Override - public String getInitParameter(String name) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getInitParameterNames() - */ - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Enumeration getInitParameterNames() { - return Collections.enumeration(Collections.EMPTY_LIST); - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getAttribute(java.lang.String) - */ - @Override - public Object getAttribute(String name) { - return sessionAttributes.get(name); - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getAttributeNames() - */ - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Enumeration getAttributeNames() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#setAttribute(java.lang.String, - * java.lang.Object) - */ - @Override - public void setAttribute(String name, Object object) { - sessionAttributes.put(name, object); - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#removeAttribute(java.lang.String) - */ - @Override - public void removeAttribute(String name) { - sessionAttributes.remove(name); - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getServletContextName() - */ - @Override - public String getServletContextName() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getContextPath() - */ - @Override - public String getContextPath() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getEffectiveMajorVersion() - */ - @Override - public int getEffectiveMajorVersion() { - return 3; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getEffectiveMinorVersion() - */ - @Override - public int getEffectiveMinorVersion() { - return 0; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#setInitParameter(java.lang.String, - * java.lang.String) - */ - @Override - public boolean setInitParameter(String name, String value) { - return false; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addServlet(java.lang.String, - * java.lang.String) - */ - @Override - public Dynamic addServlet(String servletName, String className) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addServlet(java.lang.String, - * jakarta.servlet.Servlet) - */ - @Override - public Dynamic addServlet(String servletName, Servlet servlet) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addServlet(java.lang.String, - * java.lang.Class) - */ - @Override - public Dynamic addServlet(String servletName, - Class servletClass) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#createServlet(java.lang.Class) - */ - @Override - public T createServlet(Class clazz) - throws ServletException { - return null; - } - - /* - * (non-Javadoc) - * - * @see - * jakarta.servlet.ServletContext#getServletRegistration(java.lang.String) - */ - @Override - public ServletRegistration getServletRegistration(String servletName) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getServletRegistrations() - */ - @Override - public Map getServletRegistrations() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addFilter(java.lang.String, - * java.lang.String) - */ - @Override - public jakarta.servlet.FilterRegistration.Dynamic addFilter( - String filterName, String className) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addFilter(java.lang.String, - * jakarta.servlet.Filter) - */ - @Override - public jakarta.servlet.FilterRegistration.Dynamic addFilter( - String filterName, Filter filter) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addFilter(java.lang.String, - * java.lang.Class) - */ - @Override - public jakarta.servlet.FilterRegistration.Dynamic addFilter( - String filterName, Class filterClass) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#createFilter(java.lang.Class) - */ - @Override - public T createFilter(Class clazz) - throws ServletException { - return null; - } - - /* - * (non-Javadoc) - * - * @see - * jakarta.servlet.ServletContext#getFilterRegistration(java.lang.String) - */ - @Override - public FilterRegistration getFilterRegistration(String filterName) { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getFilterRegistrations() - */ - @Override - public Map getFilterRegistrations() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getSessionCookieConfig() - */ - @Override - public SessionCookieConfig getSessionCookieConfig() { - return null; - } - - /* - * (non-Javadoc) - * - * @see - * jakarta.servlet.ServletContext#setSessionTrackingModes(java.util.Set) - */ - @Override - public void setSessionTrackingModes( - Set sessionTrackingModes) { - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getDefaultSessionTrackingModes() - */ - @Override - public Set getDefaultSessionTrackingModes() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getEffectiveSessionTrackingModes() - */ - @Override - public Set getEffectiveSessionTrackingModes() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addListener(java.lang.String) - */ - @Override - public void addListener(String className) { - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addListener(java.util.EventListener) - */ - @Override - public void addListener(T t) { - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#addListener(java.lang.Class) - */ - @Override - public void addListener(Class listenerClass) { - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#createListener(java.lang.Class) - */ - @Override - public T createListener(Class clazz) - throws ServletException { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getJspConfigDescriptor() - */ - @Override - public JspConfigDescriptor getJspConfigDescriptor() { - return null; - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#getClassLoader() - */ - @Override - public ClassLoader getClassLoader() { - return this.getClass().getClassLoader(); - } - - /* - * (non-Javadoc) - * - * @see jakarta.servlet.ServletContext#declareRoles(java.lang.String[]) - */ - @Override - public void declareRoles(String... roleNames) { - } - - @Override - public String getVirtualServerName() { - return null; - } - - @Override - public Dynamic addJspFile(String servletName, String jspFile) { - return null; - } - - @Override - public int getSessionTimeout() { - return 0; - } - - @Override - public void setSessionTimeout(int sessionTimeout) { - } - - @Override - public String getRequestCharacterEncoding() { - return null; - } - - @Override - public void setRequestCharacterEncoding(String encoding) { - } - - @Override - public String getResponseCharacterEncoding() { - return null; - } - - @Override - public void setResponseCharacterEncoding(String encoding) { - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockServletServiceSessionSetup.java b/flow-server/src/test/java/com/vaadin/flow/server/MockServletServiceSessionSetup.java deleted file mode 100644 index 90dd376ccd0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockServletServiceSessionSetup.java +++ /dev/null @@ -1,469 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletOutputStream; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpSession; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.function.Supplier; - -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.internal.ResponseWriterTest.CapturingServletOutputStream; -import com.vaadin.flow.router.QueryParameters; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.TestRouteRegistry; -import com.vaadin.flow.server.AppShellRegistry.AppShellRegistryWrapper; -import com.vaadin.flow.server.communication.IndexHtmlRequestListener; -import com.vaadin.flow.server.communication.IndexHtmlResponse; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -public class MockServletServiceSessionSetup { - - public class TestVaadinServletService extends VaadinServletService { - - private List dependencyFilterOverride; - private TestRouteRegistry routeRegistry; - private Router router; - private List bootstrapListeners = new ArrayList<>(); - private List indexHtmlRequestListeners = new ArrayList<>(); - private VaadinContext context; - - public TestVaadinServletService(TestVaadinServlet testVaadinServlet, - DeploymentConfiguration deploymentConfiguration) { - super(testVaadinServlet, deploymentConfiguration); - } - - @Override - public Iterable getDependencyFilters() { - if (dependencyFilterOverride != null) { - return dependencyFilterOverride; - } - return super.getDependencyFilters(); - } - - public void setDependencyFilters( - List dependencyFilters) { - dependencyFilterOverride = dependencyFilters; - } - - public void setRouteRegistry(TestRouteRegistry routeRegistry) { - this.routeRegistry = routeRegistry; - } - - @Override - protected RouteRegistry getRouteRegistry() { - if (routeRegistry != null) { - return routeRegistry; - } - return super.getRouteRegistry(); - } - - @Override - public Router getRouter() { - if (router != null) { - return router; - } - return super.getRouter(); - } - - public void setRouter(Router router) { - this.router = router; - } - - public void addBootstrapListener(BootstrapListener listener) { - bootstrapListeners.add(listener); - } - - public void addIndexHtmlRequestListener( - IndexHtmlRequestListener listener) { - indexHtmlRequestListeners.add(listener); - } - - @Override - public void modifyBootstrapPage(BootstrapPageResponse response) { - bootstrapListeners.forEach( - listener -> listener.modifyBootstrapPage(response)); - - super.modifyBootstrapPage(response); - } - - @Override - public void modifyIndexHtmlResponse(IndexHtmlResponse response) { - indexHtmlRequestListeners.forEach( - listener -> listener.modifyIndexHtmlResponse(response)); - - super.modifyIndexHtmlResponse(response); - } - - @Override - public VaadinContext getContext() { - if (context != null) { - return context; - } - return super.getContext(); - } - - public void setContext(VaadinContext context) { - this.context = context; - } - - } - - public class TestVaadinServlet extends VaadinServlet { - - @Override - protected VaadinServletService createServletService() - throws ServletException, ServiceException { - service = new TestVaadinServletService(this, - deploymentConfiguration); - service.init(); - return service; - } - - @Override - public ServletContext getServletContext() { - return servletContext; - } - - public void addServletContextResource(String path) { - addServletContextResource(path, "This is " + path); - } - - public void addServletContextResource(String path, String contents) { - try { - Supplier streamSupplier = new Supplier() { - @Override - public InputStream get() { - return new ByteArrayInputStream( - contents.getBytes(StandardCharsets.UTF_8)); - } - }; - URL url = new URL(null, "file://" + path, - new URLStreamHandler() { - @Override - protected URLConnection openConnection(URL u) - throws IOException { - return new URLConnection(u) { - @Override - public void connect() throws IOException { - } - - @Override - public InputStream getInputStream() - throws IOException { - return streamSupplier.get(); - } - }; - } - }); - Mockito.when(getServletContext().getResource(path)) - .thenReturn(url); - Mockito.when(getServletContext().getResourceAsStream(path)) - .thenAnswer(i -> streamSupplier.get()); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - - public void addWebJarResource(String webjarContent) { - // Webjars map /frontend/bower_components/foo/bar.html to - // /webjars/foo/bar.html - addServletContextResource("/webjars/" + webjarContent); - } - - public void verifyServletContextResourceLoadedOnce(String resource) { - Mockito.verify(servlet.getServletContext()) - .getResourceAsStream(resource); - - } - - public void verifyServletContextResourceNotLoaded(String resource) { - Mockito.verify(servlet.getServletContext(), Mockito.never()) - .getResourceAsStream(resource); - } - } - - public static class TestVaadinServletResponse - extends VaadinServletResponse { - private int errorCode; - private String errorMessage; - - private CapturingServletOutputStream output = new CapturingServletOutputStream(); - - private String type; - - private TestVaadinServletResponse(HttpServletResponse response, - VaadinServletService vaadinService) { - super(response, vaadinService); - } - - @Override - public void sendError(int errorCode, String message) - throws java.io.IOException { - this.errorCode = errorCode; - errorMessage = message; - } - - @Override - public void sendError(int sc) throws IOException { - errorCode = sc; - } - - public int getErrorCode() { - return errorCode; - } - - public String getErrorMessage() { - return errorMessage; - } - - @Override - public void setStatus(int sc) { - errorCode = sc; - } - - @Override - public ServletOutputStream getOutputStream() throws IOException { - return output; - } - - public String getPayload() { - return new String(output.getOutput()); - } - - @Override - public void setContentType(String type) { - this.type = type; - } - - @Override - public String getContentType() { - return type; - } - } - - @Mock - private ServletContext servletContext; - @Mock - private VaadinServletRequest request; - @Mock - private VaadinSession session; - @Mock - private WebBrowser browser; - @Mock - private WrappedHttpSession wrappedSession; - @Mock - private HttpSession httpSession; - @Mock - private ServletConfig servletConfig; - @Mock - private Lookup lookup; - @Mock - private ResourceProvider resourceProvider; - private TestVaadinServlet servlet; - private TestVaadinServletService service; - private MockDeploymentConfiguration deploymentConfiguration = new MockDeploymentConfiguration(); - @Mock - private StaticFileHandlerFactory staticFileHandlerFactory; - - public MockServletServiceSessionSetup() throws Exception { - this(true); - } - - public MockServletServiceSessionSetup(boolean sessionAvailable) - throws Exception { - MockitoAnnotations.initMocks(this); - servlet = new TestVaadinServlet(); - - deploymentConfiguration.setXsrfProtectionEnabled(false); - Mockito.doAnswer( - invocation -> servletContext.getClass().getClassLoader()) - .when(servletContext).getClassLoader(); - Mockito.when(servletConfig.getServletContext()) - .thenReturn(servletContext); - deploymentConfiguration.setEnableDevServer(false); - - Mockito.when(servletContext.getAttribute(Lookup.class.getName())) - .thenReturn(lookup); - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(resourceProvider); - Mockito.when(lookup.lookup(StaticFileHandlerFactory.class)) - .thenReturn(staticFileHandlerFactory); - - Mockito.when(resourceProvider.getClientResourceAsStream( - "META-INF/resources/" + ApplicationConstants.CLIENT_ENGINE_PATH - + "/compile.properties")) - .thenAnswer(invocation -> new ByteArrayInputStream( - "jsFile=foo".getBytes(StandardCharsets.UTF_8))); - - Mockito.when( - resourceProvider.getApplicationResource(Mockito.anyString())) - .thenAnswer(invocation -> { - return MockServletServiceSessionSetup.class - .getResource("/" + invocation.getArgument(0)); - }); - - servlet.init(servletConfig); - - if (sessionAvailable) { - Mockito.when(session.getConfiguration()) - .thenReturn(deploymentConfiguration); - - Mockito.when(session.getBrowser()).thenReturn(browser); - Mockito.when(session.getPushId()).thenReturn("fake push id"); - Mockito.when(session.getLocale()).thenReturn(Locale.ENGLISH); - - Mockito.when(wrappedSession.getHttpSession()) - .thenReturn(httpSession); - - Mockito.when(session.getService()).thenAnswer(i -> service); - Mockito.when(session.hasLock()).thenReturn(true); - Mockito.when(session.getPendingAccessQueue()) - .thenReturn(new LinkedBlockingDeque<>()); - Mockito.when(request.getWrappedSession()) - .thenReturn(wrappedSession); - SessionRouteRegistry sessionRegistry = (SessionRouteRegistry) SessionRouteRegistry - .getSessionRegistry(session); - Mockito.when(session.getAttribute(SessionRouteRegistry.class)) - .thenReturn(sessionRegistry); - } else { - session = null; - } - - CurrentInstance.set(VaadinRequest.class, request); - CurrentInstance.set(VaadinService.class, service); - if (sessionAvailable) { - CurrentInstance.set(VaadinSession.class, session); - } - - Mockito.when(request.getServletPath()).thenReturn(""); - } - - public TestVaadinServletService getService() { - return service; - } - - public TestVaadinServlet getServlet() { - return servlet; - } - - public ServletContext getServletContext() { - return servletContext; - } - - public HttpSession getHttpSession() { - return httpSession; - } - - public WrappedHttpSession getWrappedSession() { - return wrappedSession; - } - - public VaadinSession getSession() { - return session; - } - - public ServletConfig getServletConfig() { - return servletConfig; - } - - public MockDeploymentConfiguration getDeploymentConfiguration() { - return deploymentConfiguration; - } - - public WebBrowser getBrowser() { - return browser; - } - - public void cleanup() { - CurrentInstance.clearAll(); - } - - public void setProductionMode(boolean productionMode) { - deploymentConfiguration.setProductionMode(productionMode); - } - - public void setAppShellRegistry(AppShellRegistry appShellRegistry) { - Mockito.when(servletContext - .getAttribute(AppShellRegistryWrapper.class.getName())) - .thenReturn(new AppShellRegistryWrapper(appShellRegistry)); - } - - public TestVaadinServletResponse createResponse() throws IOException { - HttpServletResponse httpServletResponse = Mockito - .mock(HttpServletResponse.class); - CapturingServletOutputStream out = new CapturingServletOutputStream(); - Mockito.when(httpServletResponse.getOutputStream()).thenReturn(out); - return new TestVaadinServletResponse(httpServletResponse, getService()); - - } - - public VaadinRequest createRequest(MockServletServiceSessionSetup mocks, - String path, String queryString) { - return createRequest(mocks, path, "", queryString); - } - - public VaadinRequest createRequest(MockServletServiceSessionSetup mocks, - String path, String servletPath, String queryString) { - - QueryParameters queryParams = QueryParameters.fromString(queryString); - Map> params = queryParams.getParameters(); - HttpServletRequest httpServletRequest = Mockito - .mock(HttpServletRequest.class); - return new VaadinServletRequest(httpServletRequest, - mocks.getService()) { - @Override - public String getPathInfo() { - return path; - } - - @Override - public String getServletPath() { - return servletPath; - } - - @Override - public ServletContext getServletContext() { - return mocks.getServletContext(); - } - - @Override - public String getParameter(String name) { - if (!params.containsKey(name)) { - return null; - } - return params.get(name).get(0); - } - - @Override - public StringBuffer getRequestURL() { - return new StringBuffer( - "http://localhost:8888" + servletPath + getPathInfo()); - } - }; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockUIContainingServlet.java b/flow-server/src/test/java/com/vaadin/flow/server/MockUIContainingServlet.java deleted file mode 100644 index 30410dd07e2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockUIContainingServlet.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.vaadin.flow.server; - -import com.vaadin.flow.component.UI; - -public class MockUIContainingServlet extends UI { - - public static class ServletInUI extends VaadinServlet { - // This servlet should automatically be configured to use the - // enclosing UI class - } - - @Override - protected void init(VaadinRequest request) { - // Do nothing - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinContext.java b/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinContext.java deleted file mode 100644 index e20411355a6..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinContext.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; - -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RoutePathProvider; - -public class MockVaadinContext extends VaadinServletContext { - - private Lookup lookup = Mockito.mock(Lookup.class); - - public static class RoutePathProviderImpl implements RoutePathProvider { - - @Override - public String getRoutePath(Class navigationTarget) { - Route route = navigationTarget.getAnnotation(Route.class); - return route.value(); - } - - } - - public MockVaadinContext() { - this(new MockServletContext(), new RoutePathProviderImpl()); - } - - public MockVaadinContext(RoutePathProvider provider) { - this(new MockServletContext(), provider); - } - - public MockVaadinContext(ServletContext context) { - this(context, new RoutePathProviderImpl()); - } - - public MockVaadinContext(ServletContext context, - RoutePathProvider provider) { - super(context); - - Mockito.when(lookup.lookup(RoutePathProvider.class)).thenReturn(null); - - Mockito.when(lookup.lookup(RoutePathProvider.class)) - .thenReturn(provider); - - setAttribute(lookup); - } - - @Override - public T getAttribute(Class type) { - if (type.equals(Lookup.class)) { - return type.cast(lookup); - } - return super.getAttribute(type); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinServletService.java b/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinServletService.java deleted file mode 100644 index 7838d46df9f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinServletService.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletException; - -import java.util.Collections; -import java.util.List; - -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.router.Router; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -/** - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class MockVaadinServletService extends VaadinServletService { - - private Instantiator instantiator; - - private Router router; - - private ResourceProvider resourceProvider; - - private static class MockVaadinServlet extends VaadinServlet { - - private final DeploymentConfiguration configuration; - - private VaadinServletService service; - - private MockVaadinServlet(DeploymentConfiguration configuration) { - this.configuration = configuration; - } - - @Override - protected DeploymentConfiguration createDeploymentConfiguration() - throws ServletException { - return configuration; - } - - @Override - protected VaadinServletService createServletService( - DeploymentConfiguration deploymentConfiguration) - throws ServiceException { - return service; - } - - } - - public MockVaadinServletService() { - this(new MockDeploymentConfiguration()); - } - - public MockVaadinServletService( - DeploymentConfiguration deploymentConfiguration) { - super(new MockVaadinServlet(deploymentConfiguration), - deploymentConfiguration); - init(); - } - - public void setRouter(Router router) { - this.router = router; - } - - @Override - public Router getRouter() { - return router != null ? router : super.getRouter(); - } - - @Override - protected List createRequestHandlers() - throws ServiceException { - return Collections.emptyList(); - } - - public void init(Instantiator instantiator) { - this.instantiator = instantiator; - - init(); - } - - @Override - protected Instantiator createInstantiator() throws ServiceException { - if (instantiator != null) { - return instantiator; - } - return super.createInstantiator(); - } - - @Override - public void init() { - try { - MockVaadinServlet servlet = (MockVaadinServlet) getServlet(); - servlet.service = this; - if (getServlet().getServletConfig() == null) { - getServlet().init(new MockServletConfig()); - } - super.init(); - } catch (ServiceException | ServletException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinSession.java b/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinSession.java deleted file mode 100644 index b027ed82163..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/MockVaadinSession.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import com.vaadin.flow.internal.CurrentInstance; - -/** - * - * @author Vaadin Ltd - * @since 1.0 - */ -public class MockVaadinSession extends VaadinSession { - /* - * Used to make sure there's at least one reference to the mock session - * while it's locked. This is used to prevent the session from being eaten - * by GC in tests where @Before creates a session and sets it as the current - * instance without keeping any direct reference to it. This pattern has a - * chance of leaking memory if the session is not unlocked in the right way, - * but it should be acceptable for testing use. - */ - private static final ThreadLocal referenceKeeper = new ThreadLocal<>(); - - public MockVaadinSession(VaadinService service) { - super(service); - } - - public MockVaadinSession() { - this(new MockVaadinServletService()); - } - - @Override - public void close() { - super.close(); - closeCount++; - } - - public int getCloseCount() { - return closeCount; - } - - @Override - public Lock getLockInstance() { - return lock; - } - - @Override - public void lock() { - super.lock(); - referenceKeeper.set(this); - } - - @Override - public void unlock() { - super.unlock(); - referenceKeeper.remove(); - } - - private int closeCount; - - private ReentrantLock lock = new ReentrantLock(); - - public T runWithLock(Callable action) throws Exception { - Map, CurrentInstance> previous = CurrentInstance - .setCurrent(this); - lock(); - try { - return action.call(); - } finally { - unlock(); - CurrentInstance.restoreInstances(previous); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/OSGiVaadinServletTest.java b/flow-server/src/test/java/com/vaadin/flow/server/OSGiVaadinServletTest.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/flow-server/src/test/java/com/vaadin/flow/server/PropertyDeploymentConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/server/PropertyDeploymentConfigurationTest.java deleted file mode 100644 index 1934ebc6181..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/PropertyDeploymentConfigurationTest.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.Properties; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.server.startup.ApplicationConfiguration; - -public class PropertyDeploymentConfigurationTest { - - @Test - public void isProductionMode_modeIsProvidedViaParentOnly_valueFromParentIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.isProductionMode()).thenReturn(true); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - Assert.assertTrue(config.isProductionMode()); - // there is no any property - Assert.assertTrue(config.getInitParameters().isEmpty()); - } - - @Test - public void isProductionMode_modeIsProvidedViaPropertiesAndParent_valueFromPropertiesIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.isProductionMode()).thenReturn(false); - - Properties properties = new Properties(); - properties.put(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, - Boolean.TRUE.toString()); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - properties); - Assert.assertTrue(config.isProductionMode()); - Assert.assertEquals(properties, config.getInitParameters()); - } - - @Test - public void enableDevServer_valueIsProvidedViaParentOnly_valueFromParentIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.enableDevServer()).thenReturn(true); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - Assert.assertTrue(config.enableDevServer()); - // there is no any property - Assert.assertTrue(config.getInitParameters().isEmpty()); - } - - @Test - public void reuseDevServer_valueIsProvidedViaPropertiesAndParent_valueFromPropertiesIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.reuseDevServer()).thenReturn(false); - - Properties properties = new Properties(); - properties.put(InitParameters.SERVLET_PARAMETER_REUSE_DEV_SERVER, - Boolean.TRUE.toString()); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - properties); - Assert.assertTrue(config.reuseDevServer()); - Assert.assertEquals(properties, config.getInitParameters()); - } - - @Test - public void reuseDevServer_valueIsProvidedViaParentOnly_valueFromParentIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.reuseDevServer()).thenReturn(true); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - Assert.assertTrue(config.reuseDevServer()); - // there is no any property - Assert.assertTrue(config.getInitParameters().isEmpty()); - } - - @Test - public void enableDevServer_valueIsProvidedViaPropertiesAndParent_valueFromPropertiesIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.enableDevServer()).thenReturn(false); - - Properties properties = new Properties(); - properties.put(InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER, - Boolean.TRUE.toString()); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - properties); - Assert.assertTrue(config.enableDevServer()); - Assert.assertEquals(properties, config.getInitParameters()); - } - - @Test - public void isPnpmEnabled_valueIsProvidedViaParentOnly_valueFromParentIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.isPnpmEnabled()).thenReturn(true); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - Assert.assertTrue(config.isPnpmEnabled()); - // there is no any property - Assert.assertTrue(config.getInitParameters().isEmpty()); - } - - @Test - public void isPnpmEnabled_valueIsProvidedViaPropertiesAndParent_valueFromPropertiesIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.isPnpmEnabled()).thenReturn(false); - - Properties properties = new Properties(); - properties.put(InitParameters.SERVLET_PARAMETER_ENABLE_PNPM, - Boolean.TRUE.toString()); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - properties); - Assert.assertTrue(config.isPnpmEnabled()); - Assert.assertEquals(properties, config.getInitParameters()); - } - - @Test - public void isXsrfProtectionEnabled_valueIsProvidedViaParentOnly_valueFromParentIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.isXsrfProtectionEnabled()).thenReturn(true); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - Assert.assertTrue(config.isXsrfProtectionEnabled()); - // there is no any property - Assert.assertTrue(config.getInitParameters().isEmpty()); - } - - @Test - public void isXsrfProtectionEnabled_valueIsProvidedViaPropertiesAndParent_valueFromPropertiesIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - Mockito.when(appConfig.isXsrfProtectionEnabled()).thenReturn(false); - - Properties properties = new Properties(); - properties.put(InitParameters.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, - Boolean.FALSE.toString()); - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - properties); - Assert.assertTrue(config.isXsrfProtectionEnabled()); - Assert.assertEquals(properties, config.getInitParameters()); - } - - @Test - public void getApplicationProperty_propertyIsDefinedInParentOnly_valueFromParentIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - - Mockito.when(appConfig.getStringProperty("foo", null)) - .thenReturn("bar"); - - PropertyDeploymentConfiguration configuration = createConfiguration( - appConfig, new Properties()); - - Assert.assertEquals("bar", configuration.getApplicationProperty("foo")); - // there is no any property - Assert.assertTrue(configuration.getInitParameters().isEmpty()); - } - - @Test - public void getApplicationProperty_propertyIsDefinedInPropertiesAndParent_valueFromPropertiesIsReturned() { - ApplicationConfiguration appConfig = mockAppConfig(); - - Mockito.when(appConfig.getStringProperty("foo", null)) - .thenReturn("bar"); - - Properties properties = new Properties(); - properties.put("foo", "baz"); - - PropertyDeploymentConfiguration configuration = createConfiguration( - appConfig, properties); - - Assert.assertEquals("baz", configuration.getApplicationProperty("foo")); - Assert.assertEquals(properties, configuration.getInitParameters()); - } - - @Test - public void isProductionMode_modeIsProvidedViaParentOnly_propertyIsSetToAnotherValue_valueFromParentIsReturnedViaAPI() { - ApplicationConfiguration appConfig = mockAppConfig(); - - // The property value is provided via API - Mockito.when(appConfig.isProductionMode()).thenReturn(true); - - // The property whose value is overridden above via API is different - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.enumeration(Collections.singleton( - InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE))); - - Mockito.when(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, null)) - .thenReturn(Boolean.FALSE.toString()); - - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - // Several things are checked: the value from parent is used via API and - // deployment configuration doesn't read the property directly even - // though its "getInitParameters" method returns the property. Also - // "getApplicationProperty" method checks the parent properties which - // should not be taken into account here - Assert.assertTrue(config.isProductionMode()); - Assert.assertTrue(config.getInitParameters() - .containsKey(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE)); - } - - @Test - public void enableDevServer_valueIsProvidedViaParentOnly_propertyIsSetToAnotherValue_valueFromParentIsReturnedViaAPI() { - ApplicationConfiguration appConfig = mockAppConfig(); - - // The property value is provided via API - Mockito.when(appConfig.enableDevServer()).thenReturn(true); - - // The property whose value is overridden above via API is different - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.enumeration(Collections.singleton( - InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER))); - - Mockito.when(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER, null)) - .thenReturn(Boolean.FALSE.toString()); - - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - // Several things are checked: the value from parent is used via API and - // deployment configuration doesn't read the property directly even - // though its "getInitParameters" method returns the property. Also - // "getApplicationProperty" method checks the parent properties which - // should not be taken into account here - Assert.assertTrue(config.enableDevServer()); - Assert.assertTrue(config.getInitParameters().containsKey( - InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER)); - } - - @Test - public void isPnpmEnabled_valueIsProvidedViaParentOnly_propertyIsSetToAnotherValue_valueFromParentIsReturnedViaAPI() { - ApplicationConfiguration appConfig = mockAppConfig(); - - // The property value is provided via API - Mockito.when(appConfig.isPnpmEnabled()).thenReturn(true); - - // The property whose value is overridden above via API is different - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.enumeration(Collections.singleton( - InitParameters.SERVLET_PARAMETER_ENABLE_PNPM))); - - Mockito.when(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_ENABLE_PNPM, null)) - .thenReturn(Boolean.FALSE.toString()); - - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - // Several things are checked: the value from parent is used via API and - // deployment configuration doesn't read the property directly even - // though its "getInitParameters" method returns the property. Also - // "getApplicationProperty" method checks the parent properties which - // should not be taken into account here - Assert.assertTrue(config.isPnpmEnabled()); - Assert.assertTrue(config.getInitParameters() - .containsKey(InitParameters.SERVLET_PARAMETER_ENABLE_PNPM)); - } - - @Test - public void reuseDevServer_valueIsProvidedViaParentOnly_propertyIsSetToAnotherValue_valueFromParentIsReturnedViaAPI() { - ApplicationConfiguration appConfig = mockAppConfig(); - - // The property value is provided via API - Mockito.when(appConfig.reuseDevServer()).thenReturn(true); - - // The property whose value is overridden above via API is different - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.enumeration(Collections.singleton( - InitParameters.SERVLET_PARAMETER_REUSE_DEV_SERVER))); - - Mockito.when(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_REUSE_DEV_SERVER, null)) - .thenReturn(Boolean.FALSE.toString()); - - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - // Several things are checked: the value from parent is used via API and - // deployment configuration doesn't read the property directly even - // though its "getInitParameters" method returns the property. Also - // "getApplicationProperty" method checks the parent properties which - // should not be taken into account here - Assert.assertTrue(config.reuseDevServer()); - Assert.assertTrue(config.getInitParameters().containsKey( - InitParameters.SERVLET_PARAMETER_REUSE_DEV_SERVER)); - } - - @Test - public void isXsrfProtectionEnabled_valueIsProvidedViaParentOnly_propertyIsSetToAnotherValue_valueFromParentIsReturnedViaAPI() { - ApplicationConfiguration appConfig = mockAppConfig(); - - // The property value is provided via API - Mockito.when(appConfig.isXsrfProtectionEnabled()).thenReturn(true); - - // The property whose value is overridden above via API is different - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.enumeration(Collections.singleton( - InitParameters.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION))); - - Mockito.when(appConfig.getStringProperty( - InitParameters.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION, null)) - .thenReturn(Boolean.TRUE.toString()); - - PropertyDeploymentConfiguration config = createConfiguration(appConfig, - new Properties()); - // Several things are checked: the value from parent is used via API and - // deployment configuration doesn't read the property directly even - // though its "getInitParameters" method returns the property. Also - // "getApplicationProperty" method checks the parent properties which - // should not be taken into account here - Assert.assertTrue(config.isXsrfProtectionEnabled()); - Assert.assertTrue(config.getInitParameters().containsKey( - InitParameters.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION)); - } - - @Test - public void getInitParameters_prorprtiesAreMergedFromParentAndDeploymentConfig() { - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(appConfig.getPropertyNames()).thenReturn( - Collections.enumeration(Collections.singleton("foo"))); - - Mockito.when(appConfig.getStringProperty("foo", null)) - .thenReturn("foobar"); - - Properties properties = new Properties(); - properties.put("bar", "baz"); - PropertyDeploymentConfiguration configuration = createConfiguration( - appConfig, properties); - Properties initParameters = configuration.getInitParameters(); - - Assert.assertEquals("foobar", initParameters.get("foo")); - Assert.assertEquals("baz", initParameters.get("bar")); - } - - @Test - public void allDefaultAbstractConfigurationMethodsAreOverridden() { - Method[] methods = PropertyDeploymentConfiguration.class.getMethods(); - for (Method method : methods) { - Assert.assertNotEquals("There is a method '" + method.getName() - + "' which is declared in " + AbstractConfiguration.class - + " interface but it's not overriden in the " - + PropertyDeploymentConfiguration.class - + ". That's most likely a mistake because every method implementation in " - + PropertyDeploymentConfiguration.class - + " must take into account parent " - + ApplicationConfiguration.class - + " API which shares the same interface " - + AbstractConfiguration.class + " with " - + PropertyDeploymentConfiguration.class - + ", so every API method should call parent config and may not use just default implementation of " - + AbstractConfiguration.class, AbstractConfiguration.class, - method.getDeclaringClass()); - } - } - - private ApplicationConfiguration mockAppConfig() { - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - - return appConfig; - } - - private PropertyDeploymentConfiguration createConfiguration( - ApplicationConfiguration appConfig, Properties properties) { - return new PropertyDeploymentConfiguration(appConfig, Object.class, - properties); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/PwaConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/server/PwaConfigurationTest.java deleted file mode 100644 index e656c2e391c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/PwaConfigurationTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.vaadin.flow.server; - -import org.junit.Assert; -import org.junit.Test; - -public class PwaConfigurationTest { - @Test - // For https://github.com/vaadin/flow/issues/10148 - public void pwaDefaultStartUrl_should_BeDotInsteadOfEmptyString() { - PwaConfiguration pwaConfiguration = new PwaConfiguration(); - Assert.assertEquals(PwaConfiguration.DEFAULT_START_URL, - pwaConfiguration.getStartUrl()); - } - - @PWA(name = "name", shortName = "shortName") - static class App { - } - - @Test - public void pwaOfflinePathEmpty_should_beDisabled() { - PwaConfiguration pwaConfiguration = new PwaConfiguration( - App.class.getAnnotation(PWA.class), false); - Assert.assertFalse(pwaConfiguration.isOfflinePathEnabled()); - Assert.assertEquals("", pwaConfiguration.getOfflinePath()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/PwaRegistryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/PwaRegistryTest.java deleted file mode 100644 index e18a88c8827..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/PwaRegistryTest.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.startup.ApplicationConfiguration; - -@PWA(name = "foo", shortName = "bar") -public class PwaRegistryTest { - - @PWA(name = "Custom Icon Path", shortName = "CIP", iconPath = "icons/splash/foo.png") - private static class PwaWithCustomIconPath { - } - - @PWA(name = "Custom Icon Path", shortName = "COP", offlinePath = "some/path.html") - private static class PwaWithCustomOfflinePath { - } - - private static List splashIconsForAppleDevices; - - @BeforeClass - public static void initPwaWithCustomIconPath() throws IOException { - PwaRegistry registry = preparePwaRegistry( - PwaWithCustomIconPath.class.getAnnotation(PWA.class), false); - splashIconsForAppleDevices = registry.getIcons().stream().filter( - icon -> "apple-touch-startup-image".equals(icon.getRel())) - .collect(Collectors.toList()); - } - - @Test - public void pwaIconIsGeneratedBasedOnClasspathIcon_servletContextHasNoResources() - throws IOException { - // PWA annotation has default value for "iconPath" but servlet context - // has no resource for that path, in that case the ClassPath URL will be - // checked which is "META-INF/resources/icons/icon.png" (this path - // available is in the test resources folder). The icon in this path - // differs from the default icon and set of icons will be generated - // based on it - PwaRegistry registry = preparePwaRegistry( - PwaRegistryTest.class.getAnnotation(PWA.class), false); - List icons = registry.getIcons(); - // This icon has width 32 and it's generated based on a custom icon (see - // above) - PwaIcon pwaIcon = icons.stream().filter(icon -> icon.getWidth() == 32) - .findFirst().get(); - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - pwaIcon.write(stream); - // the default image has 47 on the position 36 - Assert.assertEquals(26, stream.toByteArray()[36]); - } - - private static PwaRegistry preparePwaRegistry(PWA pwa, - boolean webpackEnabled) throws IOException { - try (MockedStatic vaadinService = Mockito - .mockStatic(VaadinService.class); - MockedStatic configuration = Mockito - .mockStatic(ApplicationConfiguration.class); - MockedStatic featureFlags = Mockito - .mockStatic(FeatureFlags.class)) { - - VaadinService vaadinServiceMocked = Mockito - .mock(VaadinService.class); - VaadinContext vaadinContext = Mockito.mock(VaadinContext.class); - ApplicationConfiguration applicationConfiguration = Mockito - .mock(ApplicationConfiguration.class); - - vaadinService.when(VaadinService::getCurrent) - .thenReturn(vaadinServiceMocked); - Mockito.when(vaadinServiceMocked.getContext()) - .thenReturn(vaadinContext); - configuration - .when(() -> ApplicationConfiguration.get(Mockito.any())) - .thenReturn(applicationConfiguration); - - FeatureFlags flags = Mockito.mock(FeatureFlags.class); - Mockito.when(flags.isEnabled(FeatureFlags.WEBPACK)) - .thenReturn(webpackEnabled); - featureFlags.when(() -> FeatureFlags.get(Mockito.any())) - .thenReturn(flags); - - ServletContext context = Mockito.mock(ServletContext.class); - return new PwaRegistry(pwa, context); - } - } - - @Test - public void pwaWithCustomBaseIconPath_splashScreenIconForAllSupportedAppleDevicesAndOrientationsAreGenerated() { - Assert.assertEquals(26, splashIconsForAppleDevices.size()); - } - - @Test - public void pwaWithCustomBaseIconPath_splashScreenIconForAppleDevices_areGeneratedBasedOnIconPath() { - boolean customBaseNameUsedInIconGeneration = splashIconsForAppleDevices - .stream().allMatch( - icon -> icon.getHref().startsWith("icons/splash/foo")); - Assert.assertTrue(customBaseNameUsedInIconGeneration); - } - - @Test - public void pwaWithCustomBaseIconPath_splashScreenIconForIPadDevices_includeBothOrientations() { - // iPad Pro 12.9 - Predicate iPadPro129 = icon -> (icon.getWidth() == 2048 - && icon.getHeight() == 2732) - || (icon.getWidth() == 2732 && icon.getHeight() == 2048); - List mediaQueriesForIPadPro129 = splashIconsForAppleDevices - .stream().filter(iPadPro129) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPadPro129.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPadPro129.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPad Pro 11, 10.5 - Predicate iPadPro11And105 = icon -> (icon.getWidth() == 1668 - && icon.getHeight() == 2388) - || (icon.getWidth() == 2388 && icon.getHeight() == 1668); - List mediaQueriesForIPadPro11And105 = splashIconsForAppleDevices - .stream().filter(iPadPro11And105) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPadPro11And105.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPadPro11And105.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPad Air 10.5 - Predicate iPadAir105 = icon -> (icon.getWidth() == 1668 - && icon.getHeight() == 2224) - || (icon.getWidth() == 2224 && icon.getHeight() == 1668); - List mediaQueriesForIPadAir105 = splashIconsForAppleDevices - .stream().filter(iPadAir105) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPadAir105.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPadAir105.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPad 10.2 - Predicate iPad102 = icon -> (icon.getWidth() == 1620 - && icon.getHeight() == 2160) - || (icon.getWidth() == 2160 && icon.getHeight() == 1620); - List mediaQueriesForIPad102 = splashIconsForAppleDevices - .stream().filter(iPad102) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPad102.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPad102.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPad Pro 9.7, iPad Air 9.7, iPad 9.7, iPad mini 7.9 - Predicate iPad97And79 = icon -> (icon.getWidth() == 1536 - && icon.getHeight() == 2048) - || (icon.getWidth() == 2048 && icon.getHeight() == 1536); - List mediaQueriesForIPad97And79 = splashIconsForAppleDevices - .stream().filter(iPad97And79) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPad97And79.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPad97And79.stream() - .filter(media -> media.contains("landscape")).count()); - } - - @Test - public void pwaWithCustomBaseIconPath_splashScreenIconForIPhoneDevices_includeBothOrientations() { - // iPhone 13 Pro Max, iPhone 12 Pro Max - Predicate iPhone13ProMaxAnd12ProMax = icon -> (icon - .getWidth() == 1284 && icon.getHeight() == 2778) - || (icon.getWidth() == 2778 && icon.getHeight() == 1284); - List mediaQueriesForIPhone13ProMaxAnd12ProMax = splashIconsForAppleDevices - .stream().filter(iPhone13ProMaxAnd12ProMax) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPhone13ProMaxAnd12ProMax.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPhone13ProMaxAnd12ProMax.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPhone 13 Pro, iPhone 13, iPhone 12 Pro, iPhone 12 - Predicate iPhone13ProAnd12ProAnd13And12 = icon -> (icon - .getWidth() == 1170 && icon.getHeight() == 2532) - || (icon.getWidth() == 2532 && icon.getHeight() == 1170); - List mediaQueriesForIPhone13ProAnd12ProAnd13And12 = splashIconsForAppleDevices - .stream().filter(iPhone13ProAnd12ProAnd13And12) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPhone13ProAnd12ProAnd13And12 - .stream().filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPhone13ProAnd12ProAnd13And12 - .stream().filter(media -> media.contains("landscape")).count()); - - // iPhone 13 Mini, iPhone 12 Mini, iPhone 11 Pro, iPhone XS, iPhone X - Predicate iPhone13MiniAnd12MiniAnd11ProAndXSAndX = icon -> (icon - .getWidth() == 1125 && icon.getHeight() == 2436) - || (icon.getWidth() == 2436 && icon.getHeight() == 1125); - List mediaQueriesForIPhone13MiniAnd12MiniAnd11ProAndXSAndX = splashIconsForAppleDevices - .stream().filter(iPhone13MiniAnd12MiniAnd11ProAndXSAndX) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, - mediaQueriesForIPhone13MiniAnd12MiniAnd11ProAndXSAndX.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, - mediaQueriesForIPhone13MiniAnd12MiniAnd11ProAndXSAndX.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPhone 11 Pro Max, iPhone XS Max - Predicate iPhone11ProMaxAndXSMax = icon -> (icon - .getWidth() == 1242 && icon.getHeight() == 2688) - || (icon.getWidth() == 2688 && icon.getHeight() == 1242); - List mediaQueriesForIPhone11ProMaxAndXSMax = splashIconsForAppleDevices - .stream().filter(iPhone11ProMaxAndXSMax) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPhone11ProMaxAndXSMax.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPhone11ProMaxAndXSMax.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPhone 11, iPhone XR - Predicate iPhone11AndXR = icon -> (icon.getWidth() == 828 - && icon.getHeight() == 1792) - || (icon.getWidth() == 1792 && icon.getHeight() == 828); - List mediaQueriesForIPhone11AndXR = splashIconsForAppleDevices - .stream().filter(iPhone11AndXR) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPhone11AndXR.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPhone11AndXR.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPhone 8 Plus, 7 Plus, 6s Plus, 6 Plus - Predicate iPhone8PlusAnd7PlusAnd6sPlusAnd6Plus = icon -> (icon - .getWidth() == 1242 && icon.getHeight() == 2208) - || (icon.getWidth() == 2208 && icon.getHeight() == 1242); - List mediaQueriesForIPhone8PlusAnd7PlusAnd6sPlusAnd6Plus = splashIconsForAppleDevices - .stream().filter(iPhone8PlusAnd7PlusAnd6sPlusAnd6Plus) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, - mediaQueriesForIPhone8PlusAnd7PlusAnd6sPlusAnd6Plus.stream() - .filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, - mediaQueriesForIPhone8PlusAnd7PlusAnd6sPlusAnd6Plus.stream() - .filter(media -> media.contains("landscape")).count()); - - // iPhone 8, 7, 6s, 6, SE 4.7 - Predicate iPhone8And7And6sAnd6AndSE47 = icon -> (icon - .getWidth() == 750 && icon.getHeight() == 1334) - || (icon.getWidth() == 1334 && icon.getHeight() == 750); - List mediaQueriesForIPhone8And7And6sAnd6AndSE47 = splashIconsForAppleDevices - .stream().filter(iPhone8And7And6sAnd6AndSE47) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPhone8And7And6sAnd6AndSE47 - .stream().filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPhone8And7And6sAnd6AndSE47 - .stream().filter(media -> media.contains("landscape")).count()); - - // iPhone 5, SE 4, iPod touch 5th Gen and later - Predicate iPhone5AndSE47AndIPod5AndLater = icon -> (icon - .getWidth() == 640 && icon.getHeight() == 1136) - || (icon.getWidth() == 1136 && icon.getHeight() == 640); - List mediaQueriesForIPhone5AndSE47AndIPod5AndLater = splashIconsForAppleDevices - .stream().filter(iPhone5AndSE47AndIPod5AndLater) - .map(icon -> icon.asElement().attr("media")) - .collect(Collectors.toList()); - Assert.assertEquals(1, mediaQueriesForIPhone5AndSE47AndIPod5AndLater - .stream().filter(media -> media.contains("portrait")).count()); - Assert.assertEquals(1, mediaQueriesForIPhone5AndSE47AndIPod5AndLater - .stream().filter(media -> media.contains("landscape")).count()); - } - - @Test - public void pwaWithCustomOfflinePath_getRuntimeServiceWorkerJsContainsCustomOfflinePath() - throws IOException { - PwaRegistry registry = preparePwaRegistry( - PwaWithCustomOfflinePath.class.getAnnotation(PWA.class), false); - Assert.assertTrue(registry.getRuntimeServiceWorkerJs() - .contains("some/path.html")); - Assert.assertFalse(registry.getRuntimeServiceWorkerJs() - .contains("{ url: '.', revision:")); - } - - @Test - public void pwaWithCustomOfflinePath_webpackEnabled_getRuntimeServiceWorkerJsContainsCustomOfflinePath() - throws IOException { - PwaRegistry registry = preparePwaRegistry( - PwaWithCustomOfflinePath.class.getAnnotation(PWA.class), true); - Assert.assertTrue(registry.getRuntimeServiceWorkerJs() - .contains("some/path.html")); - Assert.assertFalse(registry.getRuntimeServiceWorkerJs() - .contains("{ url: '.', revision:")); - } - - @Test - public void pwaWithoutCustomOfflinePath_getRuntimeServiceWorkerJsContainsCustomOfflinePath() - throws IOException { - PwaRegistry registry = preparePwaRegistry( - PwaRegistryTest.class.getAnnotation(PWA.class), false); - Assert.assertTrue(registry.getRuntimeServiceWorkerJs() - .contains("{ url: '.', revision:")); - } - - @Test - public void pwaWithoutCustomOfflinePath_webpackEnabled_getRuntimeServiceWorkerJsDoesNotContainsRoot() - throws IOException { - PwaRegistry registry = preparePwaRegistry( - PwaRegistryTest.class.getAnnotation(PWA.class), true); - Assert.assertFalse(registry.getRuntimeServiceWorkerJs() - .contains("{ url: '.', revision:")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/SessionRouteRegistryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/SessionRouteRegistryTest.java deleted file mode 100644 index eb32068d5aa..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/SessionRouteRegistryTest.java +++ /dev/null @@ -1,1242 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HtmlContainer; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.BeforeEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.HasUrlParameter; -import com.vaadin.flow.router.NotFoundException; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteAlias; -import com.vaadin.flow.router.RouteBaseData; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RouteData; -import com.vaadin.flow.router.RouteParameters; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.RoutesChangedEvent; -import com.vaadin.flow.router.internal.HasUrlParameterFormat; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.flow.server.startup.ApplicationRouteRegistry; -import com.vaadin.flow.shared.Registration; - -public class SessionRouteRegistryTest { - - private ApplicationRouteRegistry registry; - private MockService vaadinService; - private VaadinSession session; - - @Before - public void init() { - registry = ApplicationRouteRegistry.getInstance( - new VaadinServletContext(Mockito.mock(ServletContext.class))); - - vaadinService = Mockito.mock(MockService.class); - Mockito.when(vaadinService.getRouteRegistry()).thenReturn(registry); - VaadinServletContext context = new MockVaadinContext(); - - ApplicationConfiguration applicationConfiguration = Mockito - .mock(ApplicationConfiguration.class); - - context.setAttribute(ApplicationConfiguration.class, - applicationConfiguration); - - Mockito.when(vaadinService.getContext()).thenReturn(context); - Mockito.when(applicationConfiguration.isProductionMode()) - .thenReturn(true); - - VaadinService.setCurrent(vaadinService); - - session = new MockVaadinSession(vaadinService) { - @Override - public VaadinService getService() { - return vaadinService; - } - }; - } - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - /** - * Get registry by handing the session lock correctly. - * - * @param session - * target vaadin session - * @return session route registry for session if exists or new. - */ - private SessionRouteRegistry getRegistry(VaadinSession session) { - try { - session.lock(); - return (SessionRouteRegistry) SessionRouteRegistry - .getSessionRegistry(session); - } finally { - session.unlock(); - } - } - - @Test - public void addSameClassForMultipleRoutes_removalOfRouteClassClearsRegisttry() { - SessionRouteRegistry registry = getRegistry(session); - - registry.setRoute("home", MyRoute.class, Collections.emptyList()); - registry.setRoute("info", MyRoute.class, Collections.emptyList()); - registry.setRoute("path", MyRoute.class, Collections.emptyList()); - registry.setRoute("palace", MyRoute.class, Collections.emptyList()); - - Assert.assertTrue( - "Registry didn't contain navigation targets even though some were registered", - !registry.getRegisteredRoutes().isEmpty()); - - registry.removeRoute(MyRoute.class); - - Assert.assertFalse( - "Registry should be empty as only one class was registered", - !registry.getRegisteredRoutes().isEmpty()); - } - - @Test - public void addMultipleClassesToSameRoute_removeClassLeavesRoute() { - SessionRouteRegistry registry = getRegistry(session); - - registry.setRoute("home", MyRoute.class, Collections.emptyList()); - registry.setRoute("home", Parameter.class, Collections.emptyList()); - - Assert.assertTrue( - "Registry didn't contain navigation targets even though some were registered", - !registry.getRegisteredRoutes().isEmpty()); - - Assert.assertEquals( - "No parameters route class was expected for only path String.", - MyRoute.class, registry.getNavigationTarget("home").get()); - Assert.assertEquals( - "No parameters route class was expected for empty segments.", - MyRoute.class, - registry.getNavigationTarget("home", Collections.emptyList()) - .get()); - Assert.assertEquals( - "Expected HasRouteParameters class for request with segments.", - Parameter.class, - registry.getNavigationTarget("home", Arrays.asList("param")) - .get()); - - registry.removeRoute(MyRoute.class); - - Assert.assertTrue( - "Registry is empty even though we should have one route available", - !registry.getRegisteredRoutes().isEmpty()); - Assert.assertFalse( - "MyRoute should have been removed from the registry.", - registry.getTargetUrl(MyRoute.class).isPresent()); - Assert.assertTrue( - "Parameter class should have been available from the registry", - registry.getTargetUrl(Parameter.class, - HasUrlParameterFormat.getParameters("foo")) - .isPresent()); - Assert.assertTrue( - "Parameter class should have been available from the registry", - registry.getTemplate(Parameter.class).isPresent()); - Assert.assertEquals("Parameter route should have been available.", - Parameter.class, - registry.getNavigationTarget("home", Arrays.asList("param")) - .get()); - } - - @Test - public void sessionRegistryOverridesParentRegistryForGetTargetUrl_globalRouteStillAccessible() { - registry.setRoute("MyRoute", MyRoute.class, Collections.emptyList()); - SessionRouteRegistry sessionRegistry = getRegistry(session); - sessionRegistry.setRoute("alternate", MyRoute.class, - Collections.emptyList()); - - Assert.assertEquals("Expected session registry route to be returned", - "alternate", sessionRegistry.getTargetUrl(MyRoute.class).get()); - - Assert.assertTrue("Route 'alternate' should be available.", - sessionRegistry.getNavigationTarget("alternate").isPresent()); - Assert.assertTrue("Route 'MyRoute' should be available.", - sessionRegistry.getNavigationTarget("MyRoute").isPresent()); - } - - @Test - public void sessionRegistryOverridesParentRegistryWithOwnClass_globalRouteReturnedAfterClassRemoval() { - registry.setRoute("MyRoute", MyRoute.class, Collections.emptyList()); - SessionRouteRegistry sessionRegistry = getRegistry(session); - sessionRegistry.setRoute("MyRoute", Secondary.class, - Collections.emptyList()); - - Assert.assertEquals( - "Route 'MyRoute' should return Secondary as registered to SessionRegistry.", - Secondary.class, - sessionRegistry.getNavigationTarget("MyRoute").get()); - - sessionRegistry.removeRoute(Secondary.class); - - Assert.assertEquals( - "Route 'MyRoute' should return MyRoute as registered to GlobalRegistry.", - MyRoute.class, - sessionRegistry.getNavigationTarget("MyRoute").get()); - } - - @Test - public void registerRouteWithAliases_routeAliasesRegisteredAsExpected() { - - SessionRouteRegistry sessionRegistry = getRegistry(session); - - // register route and have default path "MyRoute" - // also should also register "info" and "version" - sessionRegistry.setRoute("MyRoute", MyRouteWithAliases.class, - Collections.emptyList()); - sessionRegistry.setRoute("info", MyRouteWithAliases.class, - Collections.emptyList()); - sessionRegistry.setRoute("version", MyRouteWithAliases.class, - Collections.emptyList()); - - Assert.assertTrue("Main route was not registered for given Class.", - sessionRegistry.getNavigationTarget("MyRoute").isPresent()); - Assert.assertTrue( - "RouteAlias 'info' was not registered for given Class.", - sessionRegistry.getNavigationTarget("info").isPresent()); - Assert.assertTrue( - "RouteAlias 'version' was not registered for given Class.", - sessionRegistry.getNavigationTarget("version").isPresent()); - } - - @Test - public void routesWithParentLayouts_parentLayoutReturnsAsExpected() { - SessionRouteRegistry sessionRegistry = getRegistry(session); - - sessionRegistry.setRoute("MyRoute", MyRouteWithAliases.class, - Collections.singletonList(MainLayout.class)); - sessionRegistry.setRoute("info", MyRouteWithAliases.class, - Collections.emptyList()); - sessionRegistry.setRoute("version", MyRouteWithAliases.class, - Arrays.asList(MiddleLayout.class, MainLayout.class)); - - Assert.assertFalse("'MyRoute' should have a single parent", - sessionRegistry - .getRouteLayouts("MyRoute", MyRouteWithAliases.class) - .isEmpty()); - Assert.assertTrue("'info' should have no parents.", sessionRegistry - .getRouteLayouts("info", MyRouteWithAliases.class).isEmpty()); - Assert.assertEquals("'version' should return two parents", 2, - sessionRegistry - .getRouteLayouts("version", MyRouteWithAliases.class) - .size()); - } - - @Test - public void registeredParentLayouts_changingListDoesntChangeRegistration() { - SessionRouteRegistry registry = getRegistry(session); - - List> parentChain = new ArrayList<>( - Arrays.asList(MiddleLayout.class, MainLayout.class)); - - registry.setRoute("version", MyRoute.class, parentChain); - - parentChain.remove(MainLayout.class); - - Assert.assertEquals( - "'version' should return two parents even when original list is changed", - 2, registry.getRouteLayouts("version", MyRoute.class).size()); - } - - @Test - public void registeredParentLayouts_returnedListInSameOrder() { - SessionRouteRegistry registry = getRegistry(session); - - List> parentChain = new ArrayList<>( - Arrays.asList(MiddleLayout.class, MainLayout.class)); - - registry.setRoute("version", MyRoute.class, parentChain); - - Assert.assertArrayEquals( - "Registry should return parent layouts in the same order as set.", - parentChain.toArray(), - registry.getRouteLayouts("version", MyRoute.class).toArray()); - } - - @Test - public void routeRegisteredOnMultiplePaths_removalOfDefaultPathUpdatesDefaultPath() { - SessionRouteRegistry sessionRegistry = getRegistry(session); - - // register route and have default path "MyRoute" - // also should also register "info" and "version" - sessionRegistry.setRoute("MyRoute", MyRouteWithAliases.class, - Collections.emptyList()); - sessionRegistry.setRoute("info", MyRouteWithAliases.class, - Collections.emptyList()); - sessionRegistry.setRoute("version", MyRouteWithAliases.class, - Collections.emptyList()); - - Assert.assertTrue("Main route was not registered for given Class.", - sessionRegistry.getNavigationTarget("MyRoute").isPresent()); - Assert.assertTrue( - "RouteAlias 'info' was not registered for given Class.", - sessionRegistry.getNavigationTarget("info").isPresent()); - Assert.assertTrue( - "RouteAlias 'version' was not registered for given Class.", - sessionRegistry.getNavigationTarget("version").isPresent()); - - Assert.assertEquals("MyRoute", - sessionRegistry.getTargetUrl(MyRouteWithAliases.class).get()); - - sessionRegistry.removeRoute("MyRoute"); - - Assert.assertFalse( - "Route 'MyRoute' was still available even though it should have been removed.", - sessionRegistry.getNavigationTarget("MyRoute").isPresent()); - Assert.assertTrue( - "Route 'info' has been removed eve though it should still be available", - sessionRegistry.getNavigationTarget("info").isPresent()); - Assert.assertTrue( - "Route 'version' has been removed eve though it should still be available", - sessionRegistry.getNavigationTarget("version").isPresent()); - - Assert.assertTrue( - "Route was not found from the registry anymore even though it should be available.", - sessionRegistry.getTargetUrl(MyRouteWithAliases.class) - .isPresent()); - - // Either or is expected as the new default as first match is picked - // from the map - Assert.assertTrue( - "Route didn't return a url matching either of the expected aliases.", - Arrays.asList("info", "version").contains(sessionRegistry - .getTargetUrl(MyRouteWithAliases.class).get())); - } - - @Test - public void manuallyRegisteredAliases_RouteDataIsReturnedCorrectly() { - - SessionRouteRegistry sessionRegistry = getRegistry(session); - sessionRegistry.setRoute("main", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias1", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - - List registeredRoutes = sessionRegistry - .getRegisteredRoutes(); - Assert.assertTrue( - "Registry didn't contain routes even though 3 should have been registered", - !registeredRoutes.isEmpty()); - - Assert.assertTrue("Path for main route 'main' returned empty", - sessionRegistry.getNavigationTarget("main").isPresent()); - Assert.assertTrue("RouteAlias 'Alias1' returned empty.", - sessionRegistry.getNavigationTarget("Alias1").isPresent()); - Assert.assertTrue("RouteAlias 'Alias2' returned empty.", - sessionRegistry.getNavigationTarget("Alias2").isPresent()); - - Assert.assertEquals( - "Two 'RouteAlias'es should be registered in the collected route data.", - 2, registeredRoutes.get(0).getRouteAliases().size()); - - sessionRegistry.removeRoute("main"); - - registeredRoutes = sessionRegistry.getRegisteredRoutes(); - - Assert.assertTrue("Registry should still contain the alias routes", - !registeredRoutes.isEmpty()); - - Assert.assertEquals( - "One RouteAlias should be the main url so only 1 route alias should be marked as an alias", - 1, registeredRoutes.get(0).getRouteAliases().size()); - } - - @Test - public void registeredRouteWithAliasGlobally_sessionRegistryReturnsFromGlobal() { - registry.setRoute("MyRoute", MyRouteWithAliases.class, - Collections.emptyList()); - registry.setRoute("info", MyRouteWithAliases.class, - Collections.emptyList()); - registry.setRoute("version", MyRouteWithAliases.class, - Collections.emptyList()); - - SessionRouteRegistry sessionRegistry = getRegistry(session); - - List registeredRoutes = sessionRegistry - .getRegisteredRoutes(); - Assert.assertTrue( - "Registry didn't contain routes even though 3 should have been registered", - !registeredRoutes.isEmpty()); - - Assert.assertTrue("Path for main route 'MyRoute' returned empty", - sessionRegistry.getNavigationTarget("MyRoute").isPresent()); - Assert.assertTrue("RouteAlias 'info' returned empty.", - sessionRegistry.getNavigationTarget("info").isPresent()); - Assert.assertTrue("RouteAlias 'version' returned empty.", - sessionRegistry.getNavigationTarget("version").isPresent()); - - Assert.assertEquals("Both route aliases should be found for Route", 2, - registeredRoutes.get(0).getRouteAliases().size()); - } - - @Test - public void registeredRouteWithAliasGlobally_sessionRegistryOverridesMainUrl() { - registry.setRoute("MyRoute", MyRouteWithAliases.class, - Collections.emptyList()); - registry.setRoute("info", MyRouteWithAliases.class, - Collections.emptyList()); - registry.setRoute("version", MyRouteWithAliases.class, - Collections.emptyList()); - - SessionRouteRegistry sessionRegistry = getRegistry(session); - - sessionRegistry.setRoute("MyRoute", Secondary.class, - Collections.emptyList()); - - Assert.assertTrue("Registry didn't contain routes.", - !sessionRegistry.getRegisteredRoutes().isEmpty()); - - Assert.assertTrue("Path for main route 'MyRoute' returned empty", - sessionRegistry.getNavigationTarget("MyRoute").isPresent()); - Assert.assertEquals( - "Navigation target for route 'MyRoute' was not the expected one.", - Secondary.class, - sessionRegistry.getNavigationTarget("MyRoute").get()); - - Assert.assertTrue("RouteAlias 'info' returned empty.", - sessionRegistry.getNavigationTarget("info").isPresent()); - Assert.assertTrue("RouteAlias 'version' returned empty.", - sessionRegistry.getNavigationTarget("version").isPresent()); - - Assert.assertTrue("Both route aliases should be found for Route", - sessionRegistry.getRegisteredRoutes().get(0).getRouteAliases() - .isEmpty()); - } - - @Test - public void setSameRouteValueFromDifferentThreads_ConcurrencyTest() - throws InterruptedException, ExecutionException { - final int THREADS = 5; - - ExecutorService executorService = Executors.newFixedThreadPool(THREADS); - - List> callables = IntStream.range(0, THREADS) - .mapToObj(i -> { - Callable callable = () -> { - try { - SessionRouteRegistry sessionRegistry = getRegistry( - session); - sessionRegistry.setRoute("MyRoute", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }; - return callable; - }).collect(Collectors.toList()); - - List> futures = executorService.invokeAll(callables); - List exceptions = new ArrayList<>(); - - executorService.shutdown(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.value != null) { - exceptions.add(result.value); - } - } - - Assert.assertEquals( - "Expected 4 route already exists exceptions due to route target validation", - THREADS - 1, exceptions.size()); - String expected = String.format( - "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with the same route.", - MyRoute.class.getName(), MyRoute.class.getName()); - for (String exception : exceptions) { - Assert.assertEquals(expected, exception); - } - Optional> myRoute = getRegistry(session) - .getNavigationTarget("MyRoute"); - Assert.assertTrue( - "MyRoute was missing from the session scope registry.", - myRoute.isPresent()); - - } - - @Test - public void useRouteResolutionFromDifferentThreads_ConcurrencyTest() - throws InterruptedException, ExecutionException { - final int THREADS = 5; - - ExecutorService executorService = Executors.newFixedThreadPool(THREADS); - - List> callables = IntStream.range(0, THREADS) - .mapToObj(i -> { - Callable callable = () -> { - try { - SessionRouteRegistry sessionRegistry = getRegistry( - session); - sessionRegistry.setRoute("MyRoute", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }; - return callable; - }).collect(Collectors.toList()); - - List> futures = executorService.invokeAll(callables); - List exceptions = new ArrayList<>(); - - executorService.shutdown(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.value != null) { - exceptions.add(result.value); - } - } - - Assert.assertEquals( - "Expected 4 route already exists exceptions due to route target validation", - THREADS - 1, exceptions.size()); - String expected = String.format( - "Navigation targets must have unique routes, found navigation targets '%s' and '%s' with the same route.", - MyRoute.class.getName(), MyRoute.class.getName()); - for (String exception : exceptions) { - Assert.assertEquals(expected, exception); - } - Optional> myRoute = getRegistry(session) - .getNavigationTarget("MyRoute"); - Assert.assertTrue( - "MyRoute was missing from the session scope registry.", - myRoute.isPresent()); - - } - - @Test - public void updateRoutesFromMultipleThreads_allRoutesAreRegistered() - throws InterruptedException, ExecutionException { - - List> callables = new ArrayList<>(); - callables.add(() -> { - try { - getRegistry(session).setRoute("home", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getRegistry(session).setRoute("info", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getRegistry(session).setRoute("palace", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - ExecutorService executorService = Executors.newFixedThreadPool(5); - List> futures = executorService.invokeAll(callables); - - executorService.shutdown(); - - List exceptions = new ArrayList<>(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.value != null) { - exceptions.add(result.value); - } - } - - Assert.assertEquals( - "No exceptions should have been thrown for threaded updates.", - 0, exceptions.size()); - - Assert.assertTrue("Route 'home' was not registered into the scope.", - getRegistry(session).getNavigationTarget("home").isPresent()); - Assert.assertTrue("Route 'info' was not registered into the scope.", - getRegistry(session).getNavigationTarget("info").isPresent()); - Assert.assertTrue("Route 'palace' was not registered into the scope.", - getRegistry(session).getNavigationTarget("palace").isPresent()); - } - - @Test - public void updateAndRemoveFromMultipleThreads_endResultAsExpected() - throws InterruptedException, ExecutionException { - - getRegistry(session).setRoute("home", MyRoute.class, - Collections.emptyList()); - getRegistry(session).setRoute("info", MyRoute.class, - Collections.emptyList()); - - List> callables = new ArrayList<>(); - callables.add(() -> { - try { - getRegistry(session).removeRoute("info"); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getRegistry(session).setRoute("modular", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getRegistry(session).setRoute("palace", MyRoute.class, - Collections.emptyList()); - getRegistry(session).removeRoute("home"); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - ExecutorService executorService = Executors.newFixedThreadPool(5); - List> futures = executorService.invokeAll(callables); - - executorService.shutdown(); - - List exceptions = new ArrayList<>(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.value != null) { - exceptions.add(result.value); - } - } - - Assert.assertEquals( - "No exceptions should have been thrown for threaded updates.", - 0, exceptions.size()); - - Assert.assertFalse( - "Route 'home' was still registered even though it should have been removed.", - getRegistry(session).getNavigationTarget("home").isPresent()); - - Assert.assertFalse( - "Route 'info' was still registered even though it should have been removed.", - getRegistry(session).getNavigationTarget("info").isPresent()); - - Assert.assertTrue("Route 'modular' was not registered into the scope.", - getRegistry(session).getNavigationTarget("modular") - .isPresent()); - Assert.assertTrue("Route 'palace' was not registered into the scope.", - getRegistry(session).getNavigationTarget("palace").isPresent()); - } - - @Test(expected = IllegalStateException.class) - public void settingSessionRouteRegistryOfAnotherSession_getRegistryFails() { - SessionRouteRegistry registry = getRegistry(session); - - VaadinSession anotherSession = new MockVaadinSession(vaadinService) { - @Override - public VaadinService getService() { - return vaadinService; - } - }; - - SessionRouteRegistry anotherRegistry = getRegistry(anotherSession); - Assert.assertNotEquals("Another session should receive another session", - registry, anotherRegistry); - - session.lock(); - try { - session.setAttribute(SessionRouteRegistry.class, anotherRegistry); - } finally { - session.unlock(); - } - - getRegistry(session); - - Assert.fail( - "Setting anotherRegistry to session should fail when getting the registry!"); - } - - private static class Result { - final String value; - - Result(String value) { - this.value = value; - } - } - - @Test - public void lockingConfiguration_configurationIsUpdatedOnlyAfterUnlockk() { - CountDownLatch waitReaderThread = new CountDownLatch(1); - CountDownLatch waitUpdaterThread = new CountDownLatch(2); - - SessionRouteRegistry registry = getRegistry(session); - - Thread readerThread = new Thread() { - @Override - public void run() { - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - getRegistry(session).getRegisteredRoutes().isEmpty()); - - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - getRegistry(session).getRegisteredRoutes().isEmpty()); - - waitReaderThread.countDown(); - } - }; - - readerThread.start(); - - registry.update(() -> { - registry.setRoute("", MyRoute.class, Collections.emptyList()); - - waitUpdaterThread.countDown(); - - registry.setRoute("path", Secondary.class, Collections.emptyList()); - - waitUpdaterThread.countDown(); - awaitCountDown(waitReaderThread); - }); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 2, getRegistry(session).getRegisteredRoutes().size()); - } - - @Test - public void routeChangeListener_correctChangesAreReturned() { - SessionRouteRegistry registry = getRegistry(session); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - registry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - registry.setRoute("", MyRoute.class, Collections.emptyList()); - - Assert.assertFalse("Added should contain data for one entry", - added.isEmpty()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - Assert.assertEquals(MyRoute.class, added.get(0).getNavigationTarget()); - Assert.assertEquals("", added.get(0).getUrl()); - - registry.setRoute("home", Secondary.class, Collections.emptyList()); - - Assert.assertFalse("Added should contain data for one entry", - added.isEmpty()); - Assert.assertEquals("Only latest change should be available", 1, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - Assert.assertEquals(Secondary.class, - added.get(0).getNavigationTarget()); - Assert.assertEquals("home", added.get(0).getUrl()); - - registry.removeRoute("home"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertEquals("One route should have gotten removed", 1, - removed.size()); - - Assert.assertEquals(Secondary.class, - removed.get(0).getNavigationTarget()); - Assert.assertEquals("The 'home' route should have been removed", "home", - removed.get(0).getUrl()); - } - - @Test - public void routeChangeListener_blockChangesAreGivenCorrectlyInEvent() { - SessionRouteRegistry registry = getRegistry(session); - - registry.setRoute("", MyRoute.class, Collections.emptyList()); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - registry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - registry.update(() -> { - registry.removeRoute(""); - registry.setRoute("path", Secondary.class, Collections.emptyList()); - registry.setRoute("", MyRoute.class, - Collections.singletonList(MainLayout.class)); - }); - - Assert.assertEquals("Two ne paths should have been added", 2, - added.size()); - Assert.assertEquals("One path should have been removed", 1, - removed.size()); - - for (RouteBaseData data : added) { - if (data.getUrl().equals("")) { - Assert.assertEquals("MyRoute should have been added", - MyRoute.class, data.getNavigationTarget()); - Assert.assertEquals( - "MyRoute should have been seen as a update as the parent layouts changed.", - MainLayout.class, data.getParentLayout()); - } else { - Assert.assertEquals("", Secondary.class, - data.getNavigationTarget()); - } - } - - Assert.assertEquals("One MyRoute should have been removed", - MyRoute.class, removed.get(0).getNavigationTarget()); - Assert.assertEquals("Removed version should not have a parent layout", - Collections.emptyList(), removed.get(0).getParentLayouts()); - } - - @Test - public void routeWithAliases_eventShowsCorrectlyAsRemoved() { - SessionRouteRegistry sessionRegistry = getRegistry(session); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - sessionRegistry.addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - sessionRegistry.update(() -> { - sessionRegistry.setRoute("main", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias1", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - }); - - Assert.assertEquals( - "Main route and aliases should all be seen as added.", 3, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - sessionRegistry.removeRoute("Alias2"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertEquals( - "Removing the alias route should be seen in the event", 1, - removed.size()); - } - - @Test - public void maskedPathsInParent_eventContainsOnlyChangesVisibleForSession() { - registry.setRoute("main", MyRoute.class, Collections.emptyList()); - - SessionRouteRegistry sessionRegistry = getRegistry(session); - - List events = new ArrayList<>(); - - sessionRegistry.update(() -> { - sessionRegistry.setRoute("main", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias1", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - }); - - sessionRegistry.addRoutesChangeListener(events::add); - - registry.removeRoute(MyRoute.class); - - Assert.assertTrue("No event for masked path should have been received.", - events.isEmpty()); - - registry.setRoute("main", MyRoute.class, Collections.emptyList()); - - Assert.assertTrue("No event for masked path should have been received.", - events.isEmpty()); - - registry.setRoute("home", Secondary.class, Collections.emptyList()); - - Assert.assertEquals( - "Addition of non masked path should have fired an event.", 1, - events.size()); - Assert.assertEquals("Source should have been ApplicationRouteRegistry", - registry, events.get(0).getSource()); - Assert.assertEquals("One route should have been added", 1, - events.get(0).getAddedRoutes().size()); - Assert.assertEquals("No routes should have been removed", 0, - events.get(0).getRemovedRoutes().size()); - } - - @Test - public void removeListener_noEventsAreGottenForAnyRegistry() { - - SessionRouteRegistry sessionRegistry = getRegistry(session); - - List events = new ArrayList<>(); - - Registration registration = sessionRegistry - .addRoutesChangeListener(events::add); - - registry.setRoute("main", MyRoute.class, Collections.emptyList()); - sessionRegistry.update(() -> { - sessionRegistry.setRoute("main", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias1", Secondary.class, - Collections.emptyList()); - sessionRegistry.setRoute("Alias2", Secondary.class, - Collections.emptyList()); - }); - - Assert.assertEquals( - "One event for both registries should have been fired.", 2, - events.size()); - - registration.remove(); - - sessionRegistry.removeRoute("main"); - - Assert.assertEquals( - "No new event should have been received for session scope", 2, - events.size()); - - registry.removeRoute("main"); - - Assert.assertEquals( - "No new event should have been received for application scope", - 2, events.size()); - - } - - @Test - public void serialize_deserialize_parentRegistryIsANewOne() - throws Throwable { - session = new MockVaadinSession(vaadinService); - - TestSessionRouteRegistry registry = new TestSessionRouteRegistry( - session); - - TestSessionRouteRegistry deserialized = serializeAndDeserialize( - registry); - - VaadinService service = new TestService(); - RouteRegistry newAppRegistry = service.getRouteRegistry(); - - Mockito.when(newAppRegistry.getNavigationTarget("foo", - Collections.emptyList())) - .thenReturn(Optional.of(HtmlContainer.class)); - - WrappedSession wrappedSession = Mockito.mock(WrappedSession.class); - deserialized.session.refreshTransients(wrappedSession, service); - - // The original registry doesn't contain "foo" navigation target - Assert.assertEquals(Optional.empty(), - registry.getNavigationTarget("foo", Collections.emptyList())); - // The deserialized one (after refreshing transients) contains "foo" - // navigation target - Assert.assertEquals(Optional.of(HtmlContainer.class), deserialized - .getNavigationTarget("foo", Collections.emptyList())); - - } - - @Test - public void getTargetUrl_annotatedRoute_rootIsAlias_mainRouteIsNotRoot_mainRouteIsReturned() { - SessionRouteRegistry registry = getRegistry(session); - RouteConfiguration configuration = RouteConfiguration - .forRegistry(registry); - - configuration.setAnnotatedRoute(RouteWithRootAlias.class); - - Optional url = registry.getTargetUrl(RouteWithRootAlias.class, - RouteParameters.empty()); - - Assert.assertTrue(url.isPresent()); - Assert.assertEquals("foo", url.get()); - } - - @Test - public void getTargetUrl_annotatedRoute_rootIsAlias_mainRouteIsParamerterized_routeAliasIsReturned() { - SessionRouteRegistry registry = getRegistry(session); - RouteConfiguration configuration = RouteConfiguration - .forRegistry(registry); - - configuration.setAnnotatedRoute(ParameterizedRouteWithRootAlias.class); - - Optional url = registry.getTargetUrl( - ParameterizedRouteWithRootAlias.class, RouteParameters.empty()); - - Assert.assertTrue(url.isPresent()); - Assert.assertEquals("", url.get()); - } - - @Test - public void sessionScopeContainsTemplateRoute_applicationRegistryExactMatchIsReturned() { - registry.setRoute(":first/:second", Templated.class, - Collections.emptyList()); - registry.setRoute("other/view", NonTemplated.class, - Collections.emptyList()); - - SessionRouteRegistry sessionRegistry = getRegistry(session); - Assert.assertEquals("ApplicationRegisty Templated should be found.", - Templated.class, - sessionRegistry.getNavigationTarget("oh/my").get()); - Assert.assertEquals("ApplicationRegistry NonTemplated should be found", - NonTemplated.class, - sessionRegistry.getNavigationTarget("other/view").get()); - - sessionRegistry.setRoute(":one/:two", Secondary.class, - Collections.emptyList()); - - Assert.assertEquals( - "SessionRegistry should override ApplicationRegistry Templated", - Secondary.class, - sessionRegistry.getNavigationTarget("oh/my").get()); - - Assert.assertEquals( - "ApplicationRegistry exact match should be returned instead of SessionRegistry wildcard match", - NonTemplated.class, - sessionRegistry.getNavigationTarget("other/view").get()); - - sessionRegistry.setRoute("other/:one", MyRoute.class, - Collections.emptyList()); - - Assert.assertEquals( - "ApplicationRegistry exact match should be returned instead of any SessionRegistry wildcard match", - NonTemplated.class, - sessionRegistry.getNavigationTarget("other/view").get()); - Assert.assertEquals( - "SessionRegistry best match with least wildcards should be returned", - MyRoute.class, - sessionRegistry.getNavigationTarget("other/plank").get()); - - } - - @Test - public void sessionScopeContainsTemplateRoute_applicationRegistryBetterMatchIsReturned() { - registry.setRoute("other/view/parent", NonTemplated.class, - Collections.emptyList()); - registry.setRoute("other/alias/:extra?", Templated.class, - Collections.emptyList()); - - SessionRouteRegistry sessionRegistry = getRegistry(session); - sessionRegistry.setRoute("other/view/:session", MyRoute.class, - Collections.emptyList()); - sessionRegistry.setRoute("other/:match/:session?", Secondary.class, - Collections.emptyList()); - - Assert.assertEquals( - "MyRoute should be selected as the matching parts are equal", - MyRoute.class, - sessionRegistry.getNavigationTarget("other/view/offset").get()); - Assert.assertEquals( - "Exact macth in ApplicationRegistry should be selected", - NonTemplated.class, - sessionRegistry.getNavigationTarget("other/view/parent").get()); - Assert.assertEquals( - "Closer macth in ApplicationRegistry should be selected", - Templated.class, - sessionRegistry.getNavigationTarget("other/alias").get()); - Assert.assertEquals( - "Closer macth in ApplicationRegistry should be selected", - Templated.class, - sessionRegistry.getNavigationTarget("other/alias/extra").get()); - - } - - private T serializeAndDeserialize(T instance) throws Throwable { - ByteArrayOutputStream bs = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(bs); - out.writeObject(instance); - byte[] data = bs.toByteArray(); - ObjectInputStream in = new ObjectInputStream( - new ByteArrayInputStream(data)); - - @SuppressWarnings("unchecked") - T readObject = (T) in.readObject(); - - return readObject; - } - - private void awaitCountDown(CountDownLatch countDownLatch) { - try { - countDownLatch.await(); - } catch (InterruptedException e) { - Assert.fail(); - } - } - - @Tag("div") - @Route("MyRoute") - private static class MyRoute extends Component { - } - - @Tag("div") - @Route("MyRoute") - @RouteAlias("info") - @RouteAlias("version") - private static class MyRouteWithAliases extends Component { - } - - @Tag("div") - private static class Secondary extends Component { - } - - @Tag("div") - private static class MainLayout extends Component implements RouterLayout { - } - - @Tag("div") - private static class MiddleLayout extends Component - implements RouterLayout { - } - - @Tag("div") - private static class Parameter extends Component - implements HasUrlParameter { - @Override - public void setParameter(BeforeEvent event, String parameter) { - } - } - - @Tag("div") - private static class ErrorView extends Component - implements HasErrorParameter { - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 404; - } - } - - @Tag("div") - @Route("foo") - @RouteAlias("") - private static class RouteWithRootAlias extends Component { - - } - - @Tag("div") - @Route(":foo") - @RouteAlias("") - private static class ParameterizedRouteWithRootAlias extends Component { - - } - - @Route(":first/:second") - @Tag("div") - public static class Templated extends Component { - } - - @Route("other/view") - @Tag("div") - public static class NonTemplated extends Component { - } - - /** - * Extending class to let us mock the getRouteRegistry method for testing. - */ - private static class MockService extends VaadinServletService { - - @Override - public RouteRegistry getRouteRegistry() { - return super.getRouteRegistry(); - } - } - - private static class TestSessionRouteRegistry extends SessionRouteRegistry { - - private final VaadinSession session; - - TestSessionRouteRegistry(VaadinSession session) { - super(session); - this.session = session; - } - - } - - private static class TestService extends VaadinServletService { - - private ReentrantLock lock = Mockito.mock(ReentrantLock.class); - - private RouteRegistry appRegistry = Mockito - .mock(ApplicationRouteRegistry.class); - - { - Mockito.when(lock.isHeldByCurrentThread()).thenReturn(true); - } - - @Override - protected Lock getSessionLock(WrappedSession wrappedSession) { - return lock; - } - - @Override - protected RouteRegistry getRouteRegistry() { - return appRegistry; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/StaticFileServerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/StaticFileServerTest.java deleted file mode 100644 index 91777ba1bda..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/StaticFileServerTest.java +++ /dev/null @@ -1,1253 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletOutputStream; -import jakarta.servlet.WriteListener; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.Field; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -import com.vaadin.flow.WarURLStreamHandlerFactory; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.internal.ResponseWriter; - -import static com.vaadin.flow.server.Constants.POLYFILLS_DEFAULT_VALUE; -import static com.vaadin.flow.server.Constants.STATISTICS_JSON_DEFAULT; -import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES; -import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_STATISTICS_JSON; - -@NotThreadSafe -public class StaticFileServerTest implements Serializable { - - private OverrideableStaticFileServer fileServer; - private HttpServletRequest request; - private HttpServletResponse response; - private Map headers; - private Map dateHeaders; - private AtomicInteger responseCode; - private AtomicLong responseContentLength; - private VaadinServletService servletService = Mockito - .mock(VaadinServletService.class); - private DeploymentConfiguration configuration; - private ServletContext servletContext; - - private static final String WEBAPP_RESOURCE_PREFIX = "META-INF/VAADIN/webapp"; - private CapturingServletOutputStream out; - - private static URL createFileURLWithDataAndLength(String name, String data) - throws MalformedURLException { - return createFileURLWithDataAndLength(name, data, -1); - } - - private static URL createFileURLWithDataAndLength(String name, String data, - long lastModificationTime) throws MalformedURLException { - return new URL("file", "", -1, name, new URLStreamHandler() { - - @Override - protected URLConnection openConnection(URL u) throws IOException { - byte[] bytes = data.getBytes(StandardCharsets.UTF_8); - URLConnection connection = Mockito.mock(URLConnection.class); - Mockito.when(connection.getInputStream()) - .thenReturn(new ByteArrayInputStream(bytes)); - Mockito.when(connection.getContentLengthLong()) - .thenReturn((long) bytes.length); - Mockito.when(connection.getLastModified()) - .thenReturn(lastModificationTime); - return connection; - } - }); - - } - - @BeforeClass - public static void beforeClass() { - // must be cleared before running this class - CurrentInstance.clearAll(); - } - - @Before - public void setUp() throws IOException { - request = Mockito.mock(HttpServletRequest.class); - response = Mockito.mock(HttpServletResponse.class); - // No header == getDateHeader returns -1 (Mockito default is 0) - Mockito.when(request.getDateHeader(ArgumentMatchers.anyString())) - .thenReturn(-1L); - - responseCode = new AtomicInteger(-1); - responseContentLength = new AtomicLong(-1L); - headers = new HashMap<>(); - dateHeaders = new HashMap<>(); - - Mockito.doAnswer(invocation -> { - headers.put((String) invocation.getArguments()[0], - (String) invocation.getArguments()[1]); - return null; - }).when(response).setHeader(ArgumentMatchers.anyString(), - ArgumentMatchers.anyString()); - Mockito.doAnswer(invocation -> { - dateHeaders.put((String) invocation.getArguments()[0], - (Long) invocation.getArguments()[1]); - return null; - }).when(response).setDateHeader(ArgumentMatchers.anyString(), - ArgumentMatchers.anyLong()); - Mockito.doAnswer(invocation -> { - responseCode.set((int) invocation.getArguments()[0]); - return null; - }).when(response).setStatus(ArgumentMatchers.anyInt()); - Mockito.doAnswer(invocation -> { - responseCode.set((int) invocation.getArguments()[0]); - return null; - }).when(response).sendError(ArgumentMatchers.anyInt()); - Mockito.doAnswer(invocation -> { - responseContentLength.set((long) invocation.getArguments()[0]); - return null; - }).when(response).setContentLengthLong(ArgumentMatchers.anyLong()); - - configuration = Mockito.mock(DeploymentConfiguration.class); - Mockito.when(configuration.isProductionMode()).thenReturn(true); - - Mockito.when(servletService.getDeploymentConfiguration()) - .thenReturn(configuration); - - // Use test class loader to enable reading `manifest.json` resource - Mockito.doAnswer( - invocationOnMock -> servletService.getClass().getClassLoader()) - .when(servletService).getClassLoader(); - - fileServer = new OverrideableStaticFileServer(servletService, - configuration); - - // Required by the ResponseWriter - servletContext = Mockito.mock(ServletContext.class); - Mockito.when(request.getServletContext()).thenReturn(servletContext); - - out = new CapturingServletOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(out); - } - - @Test - public void getRequestFilename() { - // Context path should not affect the filename in any way - for (String contextPath : new String[] { "", "/foo", "/foo/bar" }) { - // /* servlet - Assert.assertEquals("", getRequestFilename(contextPath, "", null)); - Assert.assertEquals("/bar.js", - getRequestFilename(contextPath, "", "/bar.js")); - Assert.assertEquals("/foo/bar.js", - getRequestFilename(contextPath, "", "/foo/bar.js")); - - // /foo servlet - Assert.assertEquals("/foo", - getRequestFilename(contextPath, "/foo", null)); - Assert.assertEquals("/foo/bar.js", - getRequestFilename(contextPath, "/foo", "/bar.js")); - Assert.assertEquals("/foo/bar/baz.js", - getRequestFilename(contextPath, "/foo", "/bar/baz.js")); - - // /foo/bar servlet - Assert.assertEquals("/foo/bar", - getRequestFilename(contextPath, "/foo/bar", null)); - Assert.assertEquals("/foo/bar/baz.js", - getRequestFilename(contextPath, "/foo/bar", "/baz.js")); - Assert.assertEquals("/foo/bar/baz/baz.js", - getRequestFilename(contextPath, "/foo/bar", "/baz/baz.js")); - } - } - - @Test - public void getRequestFilename_shouldAlwaysBeResolvedAsRootResourceForServiceWorkerRequest() { - for (String swFile : new String[] { "/sw.js", "/sw.js.gz" }) { - Assert.assertEquals(swFile, getRequestFilename("", "", swFile)); - Assert.assertEquals(swFile, getRequestFilename("", "/foo", swFile)); - Assert.assertEquals(swFile, - getRequestFilename("", "/foo/bar", swFile)); - Assert.assertEquals(swFile, getRequestFilename("/ctx", "", swFile)); - Assert.assertEquals(swFile, - getRequestFilename("/ctx", "/foo", swFile)); - Assert.assertEquals(swFile, - getRequestFilename("/ctx", "/foo/bar", swFile)); - Assert.assertEquals(swFile, - getRequestFilename("/ctx/sub", "", swFile)); - Assert.assertEquals(swFile, - getRequestFilename("/ctx/sub", "/foo", swFile)); - Assert.assertEquals(swFile, - getRequestFilename("/ctx/sub", "/foo/bar", swFile)); - } - } - - private String getRequestFilename(String encodedContextPath, - String servletPath, String pathInfo) { - setupRequestURI(encodedContextPath, servletPath, pathInfo); - return fileServer.getRequestFilename(request); - } - - private void setupRequestURI(String encodedContextPath, String servletPath, - String pathInfo) { - assert !encodedContextPath.equals("/") : "root context is always \"\""; - assert encodedContextPath.equals("") - || encodedContextPath.startsWith("/") - : "context always starts with /"; - assert !encodedContextPath.endsWith("/") - : "context path should start with / but not end with /"; - assert !servletPath.equals("/") : "a /* mapped servlet has path \"\""; - assert servletPath.equals("") || servletPath.startsWith("/") - : "servlet path always starts with /"; - assert !servletPath.endsWith("/") - : "servlet path should start with / but not end with /"; - assert pathInfo == null || pathInfo.startsWith("/"); - - String requestURI = ""; - if (!encodedContextPath.isEmpty()) { - requestURI += encodedContextPath; - } - if (!servletPath.isEmpty()) { - requestURI += servletPath; - } - if (pathInfo != null) { - requestURI += pathInfo; - } - - Mockito.when(request.getContextPath()).thenReturn(encodedContextPath); - Mockito.when(request.getServletPath()).thenReturn(servletPath); - Mockito.when(request.getPathInfo()).thenReturn(pathInfo); - Mockito.when(request.getRequestURI()).thenReturn(requestURI); - } - - @Test - public void isResourceRequest() throws Exception { - fileServer.writeResponse = false; - setupRequestURI("", "/static", "/file.png"); - Mockito.when(servletService.getStaticResource("/static/file.png")) - .thenReturn(new URL("file:///static/file.png")); - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - } - - @Test - public void isResourceRequestWithContextPath() throws Exception { - fileServer.writeResponse = false; - setupRequestURI("/foo", "/static", "/file.png"); - Mockito.when(servletService.getStaticResource("/static/file.png")) - .thenReturn(new URL("file:///static/file.png")); - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - } - - @Test - public void isNotResourceRequest() throws Exception { - setupRequestURI("", "", null); - Mockito.when(servletContext.getResource("/")).thenReturn(null); - Assert.assertFalse(fileServer.serveStaticResource(request, response)); - } - - @Test - public void directoryIsNotResourceRequest() throws Exception { - fileServer.writeResponse = false; - final TemporaryFolder folder = TemporaryFolder.builder().build(); - folder.create(); - - setupRequestURI("", "", "/frontend"); - // generate URL so it is not ending with / so that we test the correct - // method - String rootAbsolutePath = folder.getRoot().getAbsolutePath() - .replaceAll("\\\\", "/"); - if (rootAbsolutePath.endsWith("/")) { - rootAbsolutePath = rootAbsolutePath.substring(0, - rootAbsolutePath.length() - 1); - } - final URL folderPath = new URL("file:///" + rootAbsolutePath); - - Mockito.when(servletService.getStaticResource("/frontend")) - .thenReturn(folderPath); - Assert.assertFalse("Folder on disk should not be a static resource.", - fileServer.serveStaticResource(request, response)); - - // Test any path ending with / to be seen as a directory - setupRequestURI("", "", "/fake"); - Mockito.when(servletService.getStaticResource("/fake")) - .thenReturn(new URL("file:///fake/")); - Assert.assertFalse( - "Fake should not check the file system nor be a static resource.", - fileServer.serveStaticResource(request, response)); - - Path tempArchive = generateZipArchive(folder); - - setupRequestURI("", "", "/frontend/."); - Mockito.when(servletService.getStaticResource("/frontend/.")) - .thenReturn(new URL("jar:file:///" - + tempArchive.toString().replaceAll("\\\\", "/") - + "!/frontend")); - Assert.assertFalse( - "Folder 'frontend' in jar should not be a static resource.", - fileServer.serveStaticResource(request, response)); - setupRequestURI("", "", "/file.txt"); - Mockito.when(servletService.getStaticResource("/file.txt")) - .thenReturn(new URL("jar:file:///" - + tempArchive.toString().replaceAll("\\\\", "/") - + "!/file.txt")); - Assert.assertTrue( - "File 'file.txt' inside jar should be a static resource.", - fileServer.serveStaticResource(request, response)); - - folder.delete(); - } - - @Test - public void isStaticResource_jarWarFileScheme_detectsAsStaticResources() - throws IOException { - fileServer.writeResponse = false; - Assert.assertTrue("Can not run concurrently with other test", - StaticFileServer.openFileSystems.isEmpty()); - - final TemporaryFolder folder = TemporaryFolder.builder().build(); - folder.create(); - - File archiveFile = new File(folder.getRoot(), "fake.jar"); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - File warFile = new File(folder.getRoot(), "war.jar"); - warFile.createNewFile(); - Path warArchive = warFile.toPath(); - - generateJarInJar(archiveFile, tempArchive, warArchive); - - // Instantiate URL stream handler factory to be able to handle war: - WarURLStreamHandlerFactory.getInstance(); - - final URL folderResourceURL = new URL( - "jar:war:" + warFile.toURI().toURL() + "!/" - + archiveFile.getName() + "!/frontend"); - - setupRequestURI("", "", "/frontend/."); - Mockito.when(servletService.getStaticResource("/frontend/.")) - .thenReturn(folderResourceURL); - - Assert.assertTrue( - "Request should return as static request as we can not determine non file resources in jar files.", - fileServer.serveStaticResource(request, response)); - - folder.delete(); - } - - @Test - public void isStaticResource_jarInAJar_detectsAsStaticResources() - throws IOException { - fileServer.writeResponse = false; - Assert.assertTrue("Can not run concurrently with other test", - StaticFileServer.openFileSystems.isEmpty()); - - final TemporaryFolder folder = TemporaryFolder.builder().build(); - folder.create(); - - File archiveFile = new File(folder.getRoot(), "fake.jar"); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - File warFile = new File(folder.getRoot(), "war.jar"); - warFile.createNewFile(); - Path warArchive = warFile.toPath(); - - generateJarInJar(archiveFile, tempArchive, warArchive); - - setupRequestURI("", "", "/frontend/."); - Mockito.when(servletService.getStaticResource("/frontend/.")) - .thenReturn(new URL("jar:" + warFile.toURI().toURL() + "!/" - + archiveFile.getName() + "!/frontend")); - Assert.assertTrue( - "Request should return as static request as we can not determine non file resources in jar files.", - fileServer.serveStaticResource(request, response)); - setupRequestURI("", "", "/file.txt"); - Mockito.when(servletService.getStaticResource("/file.txt")) - .thenReturn(new URL("jar:" + warFile.toURI().toURL() + "!/" - + archiveFile.getName() + "!/file.txt")); - Assert.assertTrue( - "Request should return as static request as we can not determine non file resources in jar files.", - fileServer.serveStaticResource(request, response)); - - folder.delete(); - } - - private Path generateZipArchive(TemporaryFolder folder) throws IOException { - File archiveFile = new File(folder.getRoot(), "fake.jar"); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - try (ZipOutputStream zipOutputStream = new ZipOutputStream( - Files.newOutputStream(tempArchive))) { - // Create a file to the zip - zipOutputStream.putNextEntry(new ZipEntry("/file")); - zipOutputStream.closeEntry(); - // Create a directory to the zip - zipOutputStream.putNextEntry(new ZipEntry("frontend/")); - zipOutputStream.closeEntry(); - } - return tempArchive; - } - - private void generateJarInJar(File archiveFile, Path tempArchive, - Path warArchive) throws IOException { - try (ZipOutputStream zipOutputStream = new ZipOutputStream( - Files.newOutputStream(tempArchive))) { - // Create a file to the zip - zipOutputStream.putNextEntry(new ZipEntry("/file")); - zipOutputStream.closeEntry(); - // Create a directory to the zip - zipOutputStream.putNextEntry(new ZipEntry("frontend/")); - zipOutputStream.closeEntry(); - } - - try (ZipOutputStream warOutputStream = new ZipOutputStream( - Files.newOutputStream(warArchive))) { - // Create a file to the zip - warOutputStream.putNextEntry(new ZipEntry(archiveFile.getName())); - warOutputStream.write(Files.readAllBytes(tempArchive)); - - warOutputStream.closeEntry(); - } - } - - @Test - public void openFileServerExistsForZip_openingNewDoesNotFail() - throws IOException, URISyntaxException { - Assert.assertTrue("Can not run concurrently with other test", - StaticFileServer.openFileSystems.isEmpty()); - - final TemporaryFolder folder = TemporaryFolder.builder().build(); - folder.create(); - - Path tempArchive = generateZipArchive(folder); - - final FileSystem fileSystem = FileSystems - .newFileSystem(new URL("jar:file:///" - + tempArchive.toString().replaceAll("\\\\", "/") + "!/") - .toURI(), Collections.emptyMap()); - - final URL folderResourceURL = new URL( - "jar:file:///" + tempArchive.toString().replaceAll("\\\\", "/") - + "!/frontend"); - - try { - fileServer.getFileSystem(folderResourceURL.toURI()); - } finally { - fileServer.closeFileSystem(folderResourceURL.toURI()); - fileSystem.close(); - } - - } - - @Test - public void openingJarFileSystemForDifferentFilesInSameJar_existingFileSystemIsUsed() - throws IOException, URISyntaxException { - Assert.assertTrue("Can not run concurrently with other test", - StaticFileServer.openFileSystems.isEmpty()); - - final TemporaryFolder folder = TemporaryFolder.builder().build(); - folder.create(); - - Path tempArchive = generateZipArchive(folder); - - final URL folderResourceURL = new URL( - "jar:file:///" + tempArchive.toString().replaceAll("\\\\", "/") - + "!/frontend"); - - final URL fileResourceURL = new URL( - "jar:file:///" + tempArchive.toString().replaceAll("\\\\", "/") - + "!/file.txt"); - - fileServer.getFileSystem(folderResourceURL.toURI()); - fileServer.getFileSystem(fileResourceURL.toURI()); - - Assert.assertEquals("Same file should be marked for both resources", - (Integer) 2, StaticFileServer.openFileSystems.entrySet() - .iterator().next().getValue()); - fileServer.closeFileSystem(folderResourceURL.toURI()); - Assert.assertEquals("Closing resource should be removed from jar uri", - (Integer) 1, StaticFileServer.openFileSystems.entrySet() - .iterator().next().getValue()); - fileServer.closeFileSystem(fileResourceURL.toURI()); - Assert.assertTrue("Closing last resource should clear marking", - StaticFileServer.openFileSystems.isEmpty()); - - try { - FileSystems.getFileSystem(folderResourceURL.toURI()); - Assert.fail("Jar FileSystem should have been closed"); - } catch (FileSystemNotFoundException fsnfe) { - // This should happen as we should not have an open FileSystem here. - } - } - - @Test - public void concurrentRequestsToJarResources_checksAreCorrect() - throws IOException, InterruptedException, ExecutionException, - URISyntaxException { - fileServer.writeResponse = false; - Assert.assertTrue("Can not run concurrently with other test", - StaticFileServer.openFileSystems.isEmpty()); - - final TemporaryFolder folder = TemporaryFolder.builder().build(); - folder.create(); - - Path tempArchive = generateZipArchive(folder); - - setupRequestURI("", "", "/frontend/."); - final URL folderResourceURL = new URL( - "jar:file:///" + tempArchive.toString().replaceAll("\\\\", "/") - + "!/frontend"); - Mockito.when(servletService.getStaticResource("/frontend/.")) - .thenReturn(folderResourceURL); - - int THREADS = 5; - - List> folderNotResource = IntStream.range(0, THREADS) - .mapToObj(i -> { - Callable callable = () -> { - try { - if (fileServer.serveStaticResource(request, - response)) { - throw new IllegalArgumentException( - "Folder 'frontend' in jar should not be a static resource."); - } - } catch (Exception e) { - return new Result(e); - } - return new Result(null); - }; - return callable; - }).collect(Collectors.toList()); - - ExecutorService executor = Executors.newFixedThreadPool(THREADS); - List> futures = executor.invokeAll(folderNotResource); - List exceptions = new ArrayList<>(); - - executor.shutdown(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.exception != null) { - exceptions.add(result.exception.getMessage()); - } - } - - Assert.assertTrue("There were exceptions in concurrent requests {" - + exceptions + "}", exceptions.isEmpty()); - - Assert.assertFalse("Folder URI should have been cleared", - StaticFileServer.openFileSystems - .containsKey(folderResourceURL.toURI())); - try { - FileSystems.getFileSystem(folderResourceURL.toURI()); - Assert.fail("FileSystem for folder resource should be closed"); - } catch (FileSystemNotFoundException fsnfe) { - // This should happen as we should not have an open FileSystem here. - } - - setupRequestURI("", "", "/file.txt"); - final URL fileResourceURL = new URL( - "jar:file:///" + tempArchive.toString().replaceAll("\\\\", "/") - + "!/file.txt"); - Mockito.when(servletService.getStaticResource("/file.txt")) - .thenReturn(fileResourceURL); - - List> fileIsResource = IntStream.range(0, THREADS) - .mapToObj(i -> { - Callable callable = () -> { - try { - if (!fileServer.serveStaticResource(request, - response)) { - throw new IllegalArgumentException( - "File 'file.txt' inside jar should be a static resource."); - } - } catch (Exception e) { - return new Result(e); - } - return new Result(null); - }; - return callable; - }).collect(Collectors.toList()); - - executor = Executors.newFixedThreadPool(THREADS); - futures = executor.invokeAll(fileIsResource); - exceptions = new ArrayList<>(); - - executor.shutdown(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.exception != null) { - exceptions.add(result.exception.getMessage()); - } - } - - Assert.assertTrue("There were exceptions in concurrent requests {" - + exceptions + "}", exceptions.isEmpty()); - - Assert.assertFalse("URI should have been cleared", - fileServer.openFileSystems - .containsKey(fileResourceURL.toURI())); - try { - FileSystems.getFileSystem(fileResourceURL.toURI()); - Assert.fail("FileSystem for file resource should be closed"); - } catch (FileSystemNotFoundException fsnfe) { - // This should happen as we should not have an open FileSystem here. - } - - folder.delete(); - } - - private static class Result { - final Exception exception; - - Result(Exception exception) { - this.exception = exception; - } - } - - @Test - public void isNotResourceRequestWithContextPath() throws Exception { - setupRequestURI("/context", "", "/"); - Mockito.when(servletContext.getResource("/")).thenReturn(new URL("file", - "", -1, - "flow/flow-tests/non-root-context-test/src/main/webapp/", - new URLStreamHandler() { - - @Override - protected URLConnection openConnection(URL u) - throws IOException { - URLConnection mock = Mockito.mock(URLConnection.class); - return mock; - } - })); - - Assert.assertFalse(fileServer.serveStaticResource(request, response)); - } - - @Test - public void writeModificationTimestampBrowserHasLatest() - throws MalformedURLException { - fileServer.overrideBrowserHasNewestVersion = true; - Long modificationTimestamp = writeModificationTime(); - Assert.assertEquals(modificationTimestamp, - dateHeaders.get("Last-Modified")); - } - - @Test - public void writeModificationTimestampBrowserDoesNotHaveLatest() - throws MalformedURLException { - fileServer.overrideBrowserHasNewestVersion = false; - Long modificationTimestamp = writeModificationTime(); - Assert.assertEquals(modificationTimestamp, - dateHeaders.get("Last-Modified")); - - } - - private Long writeModificationTime() throws MalformedURLException { - LocalDateTime modificationTime = LocalDateTime.of(2016, 2, 2, 0, 0, 0); - Long modificationTimestamp = modificationTime - .toEpochSecond(ZoneOffset.UTC) * 1000; - String filename = "modified-1d-ago.txt"; - URL resourceUrl = new URL("file", "", -1, filename, - new URLStreamHandler() { - @Override - protected URLConnection openConnection(URL u) - throws IOException { - URLConnection mock = Mockito.mock(URLConnection.class); - Mockito.when(mock.getLastModified()) - .thenReturn(modificationTimestamp); - return mock; - } - }); - - fileServer.writeModificationTimestamp(resourceUrl, request, response); - return modificationTimestamp; - } - - @Test - public void browserHasNewestVersionUnknownModificiationTime() { - Assert.assertFalse(fileServer.browserHasNewestVersion(request, -1)); - } - - @Test(expected = AssertionError.class) - public void browserHasNewestVersionInvalidModificiationTime() { - fileServer.browserHasNewestVersion(request, -2); - } - - @Test - public void browserHasNewestVersionNoIfModifiedSinceHeader() { - long fileModifiedTime = 0; - - Assert.assertFalse( - fileServer.browserHasNewestVersion(request, fileModifiedTime)); - } - - @Test - public void browserHasNewestVersionOlderIfModifiedSinceHeader() { - long browserIfModifiedSince = 123L; - long fileModifiedTime = 124L; - Mockito.when(request.getDateHeader("If-Modified-Since")) - .thenReturn(browserIfModifiedSince); - - Assert.assertFalse( - fileServer.browserHasNewestVersion(request, fileModifiedTime)); - } - - @Test - public void browserHasNewestVersionNewerIfModifiedSinceHeader() { - long browserIfModifiedSince = 125L; - long fileModifiedTime = 124L; - Mockito.when(request.getDateHeader("If-Modified-Since")) - .thenReturn(browserIfModifiedSince); - - Assert.assertTrue( - fileServer.browserHasNewestVersion(request, fileModifiedTime)); - } - - @Test - public void writeCacheHeadersCacheResource() { - fileServer.overrideCacheTime = 12; - fileServer.writeCacheHeaders("/folder/myfile.txt", response); - Assert.assertTrue(headers.get("Cache-Control").contains("max-age=12")); - } - - @Test - public void nonProductionMode_writeCacheHeadersCacheResource_noCache() { - Mockito.when(configuration.isProductionMode()).thenReturn(false); - - fileServer.overrideCacheTime = 12; - fileServer.writeCacheHeaders("/folder/myfile.txt", response); - Assert.assertTrue(headers.get("Cache-Control").equals("no-cache")); - } - - @Test - public void writeCacheHeadersDoNotCacheResource() { - fileServer.overrideCacheTime = 0; - fileServer.writeCacheHeaders("/folder/myfile.txt", response); - Assert.assertTrue(headers.get("Cache-Control").contains("max-age=0")); - Assert.assertTrue( - headers.get("Cache-Control").contains("must-revalidate")); - } - - @Test - public void nonProductionMode_writeCacheHeadersDoNotCacheResource() { - Mockito.when(configuration.isProductionMode()).thenReturn(false); - - fileServer.overrideCacheTime = 0; - fileServer.writeCacheHeaders("/folder/myfile.txt", response); - Assert.assertTrue(headers.get("Cache-Control").equals("no-cache")); - } - - @Test - public void getCacheTime() { - int oneYear = 60 * 60 * 24 * 365; - Assert.assertEquals(oneYear, - fileServer.getCacheTime("somefile.cache.js")); - Assert.assertEquals(oneYear, - fileServer.getCacheTime("folder/somefile.cache.js")); - Assert.assertEquals(0, fileServer.getCacheTime("somefile.nocache.js")); - Assert.assertEquals(0, - fileServer.getCacheTime("folder/somefile.nocache.js")); - Assert.assertEquals(3600, fileServer.getCacheTime("randomfile.js")); - Assert.assertEquals(3600, - fileServer.getCacheTime("folder/randomfile.js")); - } - - @Test - public void serveNonExistingStaticResource() throws IOException { - setupRequestURI("", "", "/nonexisting/file.js"); - - Assert.assertFalse(fileServer.serveStaticResource(request, response)); - } - - @Test - public void serveStaticResource() throws IOException { - setupRequestURI("", "/some", "/file.js"); - String fileData = "function() {eval('foo');};"; - - Mockito.when(servletService.getStaticResource("/some/file.js")) - .thenReturn(createFileURLWithDataAndLength("/some/file.js", - fileData)); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(fileData, out.getOutputString()); - } - - @Test - public void contextAndServletPath_serveStaticBundleBuildResource() - throws IOException { - String pathInfo = "/VAADIN/build/vaadin-bundle-1234.cache.js"; - setupRequestURI("/context", "/servlet", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void ServletPath_serveStaticBundleBuildResource() - throws IOException { - String pathInfo = "/VAADIN/build/vaadin-bundle-1234.cache.js"; - setupRequestURI("", "/servlet", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void contextPath_serveStaticBundleBuildResource() - throws IOException { - String pathInfo = "/VAADIN/build/vaadin-bundle-1234.cache.js"; - setupRequestURI("/context", "", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void serveStaticBundleBuildResource() throws IOException { - String pathInfo = "/VAADIN/build/vaadin-bundle-1234.cache.js"; - setupRequestURI("", "", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void contextAndServletPath_serveStaticFileResource() - throws IOException { - String pathInfo = "/VAADIN/static/img/bg.jpg"; - setupRequestURI("/context", "/servlet", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void ServletPath_serveStaticFileResource() throws IOException { - String pathInfo = "/VAADIN/static/img/bg.jpg"; - setupRequestURI("", "/servlet", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void contextPath_serveStaticFileResource() throws IOException { - String pathInfo = "/VAADIN/static/img/bg.jpg"; - setupRequestURI("/context", "", pathInfo); - assertBundleBuildResource(pathInfo); - } - - @Test - public void serveStaticFileResource() throws IOException { - String pathInfo = "/VAADIN/static/img/bg.jpg"; - setupRequestURI("", "", pathInfo); - assertBundleBuildResource(pathInfo); - } - - public void assertBundleBuildResource(String pathInfo) throws IOException { - String fileData = "function() {eval('foo');};"; - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - - Mockito.when(mockLoader.getResource(WEBAPP_RESOURCE_PREFIX + pathInfo)) - .thenReturn(createFileURLWithDataAndLength( - "/" + WEBAPP_RESOURCE_PREFIX + pathInfo, fileData)); - - mockStatsBundles(mockLoader); - mockConfigurationPolyfills(); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(fileData, out.getOutputString()); - } - - private void staticBuildResourceWithDirectoryChange_nothingServed( - String pathInfo) throws IOException { - setupRequestURI("/context", "/servlet", pathInfo); - String fileData = "function() {eval('foo');};"; - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - - Mockito.when(mockLoader.getResource(WEBAPP_RESOURCE_PREFIX + pathInfo)) - .thenReturn(createFileURLWithDataAndLength( - "/" + WEBAPP_RESOURCE_PREFIX + pathInfo, fileData)); - - // have data available for /VAADIN/vaadin-bundle-1234.cache.js - Mockito.when(mockLoader.getResource( - WEBAPP_RESOURCE_PREFIX + pathInfo.replace("build/../", ""))) - .thenReturn( - createFileURLWithDataAndLength( - WEBAPP_RESOURCE_PREFIX - + pathInfo.replace("build/../", ""), - fileData)); - - mockStatsBundles(mockLoader); - mockConfigurationPolyfills(); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(0, out.getOutput().length); - Assert.assertEquals(HttpStatusCode.BAD_REQUEST.getCode(), - responseCode.get()); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeWithSlash_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/../vaadin-bundle-1234.cache.js"); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeWithBackslash_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/something\\..\\vaadin-bundle-1234.cache.js"); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeWithEncodedBackslashUpperCase_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/something%5C..%5Cvaadin-bundle-1234.cache.js"); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeWithEncodedBackslashLowerCase_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/something%5c..%5cvaadin-bundle-1234.cache.js"); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeInTheEndWithSlash_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/.."); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeInTheEndWithBackslash_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/something\\.."); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeInTheEndWithEncodedBackslashUpperCase_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/something%5C.."); - } - - @Test - public void serveStaticResource_uriWithDirectoryChangeInTheEndWithEncodedBackslashLowerCase_returnsImmediatelyAndSetsBadRequestStatus() - throws IOException { - staticBuildResourceWithDirectoryChange_nothingServed( - "/VAADIN/build/something%5c.."); - } - - @Test - public void customStaticBuildResource_isServed() throws IOException { - String pathInfo = "/VAADIN/build/my-text.txt"; - setupRequestURI("", "", pathInfo); - String fileData = "function() {eval('foo');};"; - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - - Mockito.when(mockLoader.getResource(WEBAPP_RESOURCE_PREFIX + pathInfo)) - .thenReturn(createFileURLWithDataAndLength( - "/" + WEBAPP_RESOURCE_PREFIX + pathInfo, fileData)); - - mockStatsBundles(mockLoader); - mockConfigurationPolyfills(); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(fileData, out.getOutputString()); - } - - @Test - public void nonexistingStaticBuildResource_notServed() throws IOException { - String pathInfo = "/VAADIN/build/my-text.txt"; - setupRequestURI("", "", pathInfo); - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - - mockStatsBundles(mockLoader); - mockConfigurationPolyfills(); - - Assert.assertFalse(fileServer.serveStaticResource(request, response)); - } - - @Test - public void staticManifestPathResource_isServed() throws IOException { - String pathInfo = "/sw.js"; - setupRequestURI("", "", pathInfo); - String fileData = "function() {eval('foo');};"; - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - - Mockito.when(mockLoader.getResource(WEBAPP_RESOURCE_PREFIX + pathInfo)) - .thenReturn(createFileURLWithDataAndLength( - "/" + WEBAPP_RESOURCE_PREFIX + pathInfo, fileData)); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(fileData, out.getOutputString()); - } - - @Test - public void staticManifestPathIndexHtmlResource_notServed() - throws IOException { - String pathInfo = "/index.html"; - setupRequestURI("", "", pathInfo); - String fileData = "function() {eval('foo');};"; - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - - Mockito.when(mockLoader.getResource(WEBAPP_RESOURCE_PREFIX + pathInfo)) - .thenReturn(createFileURLWithDataAndLength( - "/" + WEBAPP_RESOURCE_PREFIX + pathInfo, fileData)); - - Assert.assertFalse(fileServer.serveStaticResource(request, response)); - } - - @Test - public void customStatsJson_isServedFromServlet() throws IOException { - String pathInfo = "/VAADIN/build/stats.json"; - setupRequestURI("", "/servlet", pathInfo); - String fileData = "function() {eval('foo');};"; - - ClassLoader mockLoader = Mockito.mock(ClassLoader.class); - Mockito.when(servletService.getClassLoader()).thenReturn(mockLoader); - mockStatsBundles(mockLoader); - mockConfigurationPolyfills(); - - Mockito.when(servletService.getStaticResource(pathInfo)) - .thenReturn(createFileURLWithDataAndLength(pathInfo, fileData)); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(fileData, out.getOutputString()); - } - - public void mockConfigurationPolyfills() { - Mockito.when(configuration.getPolyfills()).thenReturn( - Arrays.asList(POLYFILLS_DEFAULT_VALUE.split("[, ]+"))); - } - - public void mockStatsBundles(ClassLoader mockLoader) { - Mockito.when(configuration.getStringProperty( - SERVLET_PARAMETER_STATISTICS_JSON, - VAADIN_SERVLET_RESOURCES + STATISTICS_JSON_DEFAULT)) - .thenReturn("META-INF/VAADIN/config/stats.json"); - Mockito.when(mockLoader - .getResourceAsStream("META-INF/VAADIN/config/stats.json")) - .thenReturn(new ByteArrayInputStream(getStatsData())); - } - - /** - * Returns a byte array for a valid stats.json containing only chunks - * - * @return - */ - public byte[] getStatsData() { - return ("{ " + "\"assetsByChunkName\" :{ " - + "\"index\": \"build/vaadin-bundle-1234.cache.js\"} }") - .getBytes(StandardCharsets.UTF_8); - } - - @Test - public void serveStaticResourceBrowserHasLatest() throws IOException { - long browserLatest = 123L; - long fileModified = 123L; - - setupRequestURI("", "/some", "/file.js"); - Mockito.when(request.getDateHeader("If-Modified-Since")) - .thenReturn(browserLatest); - - String fileData = "function() {eval('foo');};"; - Mockito.when(servletService.getStaticResource("/some/file.js")) - .thenReturn(createFileURLWithDataAndLength("/some/file.js", - fileData, fileModified)); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(0, out.getOutput().length); - Assert.assertEquals(HttpStatusCode.NOT_MODIFIED.getCode(), - responseCode.get()); - } - - @Test - public void serveStaticResourceFromWebjarWithIncorrectPath() - throws IOException { - Mockito.when(configuration.getBooleanProperty( - StaticFileServer.PROPERTY_FIX_INCORRECT_WEBJAR_PATHS, false)) - .thenReturn(true); - String fileData = "function() {eval('foo');};"; - Mockito.when(servletService.getStaticResource("/webjars/foo/bar.js")) - .thenReturn(createFileURLWithDataAndLength( - "/webjars/foo/bar.js", fileData)); - - setupRequestURI("", "", "/frontend/src/webjars/foo/bar.js"); - - Assert.assertTrue(fileServer.serveStaticResource(request, response)); - Assert.assertEquals(fileData, out.getOutputString()); - } - - @Test - public void serveStaticResourceFromWebjarWithIncorrectPathAndFixingDisabled() - throws IOException { - Mockito.when(configuration.getBooleanProperty( - StaticFileServer.PROPERTY_FIX_INCORRECT_WEBJAR_PATHS, false)) - .thenReturn(false); - - Mockito.when(servletService - .getStaticResource("/frontend/src/webjars/foo/bar.js")) - .thenReturn(null); - - setupRequestURI("", "", "/frontend/src/webjars/foo/bar.js"); - - Assert.assertFalse(fileServer.serveStaticResource(request, response)); - } - - @Test - public void getStaticResource_delegateToVaadinService() - throws MalformedURLException { - URL url = new URL("http://bar"); - Mockito.when(servletService.getStaticResource("foo")).thenReturn(url); - URL result = fileServer.getStaticResource("foo"); - - Mockito.verify(servletService).getStaticResource("foo"); - Assert.assertSame(url, result); - } - - private static class CapturingServletOutputStream - extends ServletOutputStream { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - @Override - public void write(int b) throws IOException { - baos.write(b); - } - - @Override - public void setWriteListener(WriteListener writeListener) { - } - - @Override - public boolean isReady() { - return true; - } - - public byte[] getOutput() { - return baos.toByteArray(); - } - - public String getOutputString() { - return new String(getOutput(), StandardCharsets.UTF_8); - } - } - - private static class OverrideableStaticFileServer extends StaticFileServer { - public boolean writeResponse = true; - private Boolean overrideBrowserHasNewestVersion; - private Integer overrideCacheTime; - private DeploymentConfiguration configuration; - - OverrideableStaticFileServer(VaadinServletService servletService, - DeploymentConfiguration configuration) { - super(servletService); - this.configuration = configuration; - } - - @Override - protected boolean browserHasNewestVersion(HttpServletRequest request, - long resourceLastModifiedTimestamp) { - if (overrideBrowserHasNewestVersion != null) { - return overrideBrowserHasNewestVersion; - } - - return super.browserHasNewestVersion(request, - resourceLastModifiedTimestamp); - } - - @Override - protected int getCacheTime(String filenameWithPath) { - if (overrideCacheTime != null) { - return overrideCacheTime; - } - return super.getCacheTime(filenameWithPath); - } - - @Override - public boolean serveStaticResource(HttpServletRequest request, - HttpServletResponse response) throws IOException { - if (!writeResponse) - try { - { - ResponseWriter fakeWriter = new ResponseWriter( - configuration) { - @Override - public void writeResponseContents( - String filenameWithPath, URL resourceUrl, - HttpServletRequest request, - HttpServletResponse response) - throws IOException { - return; - } - }; - Field f = StaticFileServer.class - .getDeclaredField("responseWriter"); - f.setAccessible(true); - f.set(this, fakeWriter); - } - } catch (IllegalArgumentException | IllegalAccessException - | NoSuchFieldException | SecurityException e) { - throw new RuntimeException(e); - } - return super.serveStaticResource(request, response); - } - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/StreamResourceRegistryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/StreamResourceRegistryTest.java deleted file mode 100644 index 7845bab1dc9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/StreamResourceRegistryTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletException; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.net.URI; -import java.util.Optional; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.CurrentInstance; - -public class StreamResourceRegistryTest { - - private UI ui; - private VaadinServletService service; - private VaadinSession session; - - @Before - public void setUp() throws ServletException, ServiceException { - service = new MockVaadinServletService(); - session = new VaadinSession(service) { - @Override - public boolean hasLock() { - return true; - } - }; - - ui = Mockito.mock(UI.class); - Mockito.when(ui.getUIId()).thenReturn(1); - UI.setCurrent(ui); - } - - @After - public void tearDown() { - CurrentInstance.clearAll(); - } - - @Test - public void registerResource_registrationResultCanBeFound() { - StreamResourceRegistry registry = new StreamResourceRegistry(session); - - StreamResource resource = new StreamResource("name", - () -> makeEmptyStream()); - StreamRegistration registration = registry.registerResource(resource); - Assert.assertNotNull(registration); - - URI uri = registration.getResourceUri(); - - Optional stored = registry - .getResource(StreamResource.class, uri); - Assert.assertSame( - "Unexpected stored resource is returned for registered URI", - resource, stored.get()); - - Assert.assertSame( - "Unexpected resource is returned by the registration instance", - resource, registration.getResource()); - } - - @Test - public void unregisterResource_resourceIsRemoved() { - StreamResourceRegistry registry = new StreamResourceRegistry(session); - - StreamResource resource = new StreamResource("name", - () -> makeEmptyStream()); - StreamRegistration registration = registry.registerResource(resource); - Assert.assertNotNull(registration); - - URI uri = registration.getResourceUri(); - - registration.unregister(); - - Optional stored = registry - .getResource(StreamResource.class, uri); - Assert.assertFalse( - "Unexpected stored resource is found after unregister()", - stored.isPresent()); - Assert.assertFalse( - "Unexpected resource is returned by the registration instance", - registration.getResource() != null); - } - - @Test - public void registerTwoResourcesWithSameName_resourcesHasDifferentURI() { - StreamResourceRegistry registry = new StreamResourceRegistry(session); - - StreamResource resource1 = new StreamResource("name", - () -> makeEmptyStream()); - StreamRegistration registration1 = registry.registerResource(resource1); - - StreamResource resource2 = new StreamResource("name", - () -> makeEmptyStream()); - StreamRegistration registration2 = registry.registerResource(resource2); - - Assert.assertNotEquals( - "Two different resource are registered to the same URI", - registration1.getResourceUri(), registration2.getResourceUri()); - - registration1.unregister(); - - Assert.assertTrue( - "Second resource is not found after first resource has been unregistered", - registry.getResource(registration2.getResourceUri()) - .isPresent()); - } - - @Test - public void getResourceUriIsEncoded_withQueryParams() { - assertResourceUriIsEncoded("a?b=c d&e", "a%3Fb%3Dc%20d%26e"); - } - - @Test - public void getResourceUriIsEncoded_withContainingPlus() { - assertResourceUriIsEncoded("image++.svg", "image%2B%2B.svg"); - } - - @Test - public void getResourceUriIsEncoded_withSimpleSpace() { - assertResourceUriIsEncoded("my file.png", "my%20file.png"); - } - - private void assertResourceUriIsEncoded(String resourceName, - String suffix) { - StreamResourceRegistry registry = new StreamResourceRegistry(session); - - StreamResource resource = new StreamResource(resourceName, - this::makeEmptyStream); - StreamRegistration registration = registry.registerResource(resource); - - URI uri = registration.getResourceUri(); - Assert.assertTrue("Resource URI is not properly encoded", - uri.toString().endsWith(suffix)); - } - - private InputStream makeEmptyStream() { - return new ByteArrayInputStream(new byte[0]); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/StreamResourceTest.java b/flow-server/src/test/java/com/vaadin/flow/server/StreamResourceTest.java deleted file mode 100644 index ce924f8007d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/StreamResourceTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.function.ContentTypeResolver; - -public class StreamResourceTest { - - @Test - public void getDefaultContentTypeResolver() { - StreamResource resource = new StreamResource("foo", - () -> makeEmptyStream()); - ContentTypeResolver resolver = resource.getContentTypeResolver(); - - Assert.assertNotNull(resolver); - - assertContentType(resource, resolver); - } - - @Test - public void setContentTypeResolver() { - StreamResource resource = new StreamResource("foo", - () -> makeEmptyStream()); - resource.setContentTypeResolver((res, context) -> "bar"); - - Assert.assertNotNull(resource.getContentTypeResolver()); - - assertContentType(resource, resource.getContentTypeResolver()); - } - - @Test - public void setContentType() { - StreamResource resource = new StreamResource("foo", - () -> makeEmptyStream()); - resource.setContentType("bar"); - - Assert.assertNotNull(resource.getContentTypeResolver()); - - assertContentType(resource, resource.getContentTypeResolver()); - } - - @Test - public void setHeader_headerIsInHeadersListAndGetterReturnsTheValue() { - StreamResource resource = new StreamResource("foo", - () -> makeEmptyStream()); - - resource.setHeader("foo", "bar"); - - Assert.assertEquals("bar", resource.getHeader("foo").get()); - - Map headers = resource.getHeaders(); - Assert.assertEquals(1, headers.size()); - Assert.assertEquals("bar", headers.get("foo")); - } - - private void assertContentType(StreamResource resource, - ContentTypeResolver resolver) { - ServletContext context = Mockito.mock(ServletContext.class); - Mockito.when(context.getMimeType("foo")).thenReturn("bar"); - String mimeType = resolver.apply(resource, context); - - Assert.assertEquals("bar", mimeType); - } - - private InputStream makeEmptyStream() { - return new ByteArrayInputStream(new byte[0]); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/TestProvider.java b/flow-server/src/test/java/com/vaadin/flow/server/TestProvider.java deleted file mode 100644 index ac971973052..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/TestProvider.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -import com.vaadin.flow.i18n.I18NProvider; - -/** - * Translation provider test class. - */ -public class TestProvider implements I18NProvider { - - @Override - public List getProvidedLocales() { - return Arrays.asList(Locale.ENGLISH); - } - - @Override - public String getTranslation(String key, Locale locale, Object... params) { - return "!" + key + "!"; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/UnsupportedBrowserHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/UnsupportedBrowserHandlerTest.java deleted file mode 100644 index 8d819841c0c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/UnsupportedBrowserHandlerTest.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.vaadin.flow.server; - -import java.io.IOException; -import java.io.PrintWriter; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -public class UnsupportedBrowserHandlerTest { - - private VaadinRequest request; - private VaadinResponse response; - private VaadinSession session; - private UnsupportedBrowserHandler handler = new UnsupportedBrowserHandler(); - private ArgumentCaptor pageCapture = ArgumentCaptor - .forClass(String.class); - private PrintWriter writer; - private MockDeploymentConfiguration configuration; - - private void initMocks(boolean forceReloadCookie, - boolean isTooOldToFunctionProperly) throws IOException { - - configuration = new MockDeploymentConfiguration(); - - request = Mockito.mock(VaadinRequest.class); - Mockito.when(request.getHeader("Cookie")) - .thenReturn(forceReloadCookie - ? UnsupportedBrowserHandler.FORCE_LOAD_COOKIE - : null); - - writer = Mockito.mock(PrintWriter.class); - - response = Mockito.mock(VaadinServletResponse.class); - Mockito.when(response.getWriter()).thenReturn(writer); - - WebBrowser webBrowser = Mockito.mock(WebBrowser.class); - Mockito.when(webBrowser.isTooOldToFunctionProperly()) - .thenReturn(isTooOldToFunctionProperly); - - session = Mockito.mock(VaadinSession.class); - Mockito.when(session.getBrowser()).thenReturn(webBrowser); - Mockito.when(session.getConfiguration()).thenReturn(configuration); - - VaadinSession.setCurrent(session); - } - - @Test - public void testUnsupportedBrowserHandler_validBrowser_doesntHandleRequest() - throws IOException { - initMocks(false, false); - - Assert.assertFalse("Should not handle the request", - handler.synchronizedHandleRequest(session, request, response)); - Mockito.verify(writer, Mockito.never()).write(Mockito.anyString()); - } - - @Test - public void testUnsupportedBrowserHandler_tooOldBrowser_returnsUnsupportedBrowserPage() - throws IOException { - initMocks(false, true); - - Assert.assertTrue("Request should have been handled", - handler.synchronizedHandleRequest(session, request, response)); - - Mockito.verify(writer).write(pageCapture.capture()); - - Assert.assertTrue("Unsupported browser page not used", - pageCapture.getValue().contains( - "I'm sorry, but your browser is not supported")); - - Mockito.verify(response).setContentType( - ApplicationConstants.CONTENT_TYPE_TEXT_HTML_UTF_8); - } - - @Test - public void testUnsupportedBrowserHandler_tooOldBrowserWithForceReloadCookie_doesntHandleRequest() - throws IOException { - initMocks(true, true); - - Assert.assertFalse("Should not handle the request", - handler.synchronizedHandleRequest(session, request, response)); - Mockito.verify(writer, Mockito.never()).write(Mockito.anyString()); - } - - @Test - public void testUnsupportedBrowserHandler_validBrowserWithForceReloadCookie_doesntHandleRequest() - throws IOException { - initMocks(true, false); - - Assert.assertFalse("Should not handle the request", - handler.synchronizedHandleRequest(session, request, response)); - Mockito.verify(writer, Mockito.never()).write(Mockito.anyString()); - } - - @Test - public void writeBrowserTooOldPage_setContentType() throws IOException { - initMocks(true, true); - handler.writeBrowserTooOldPage(request, response); - - Mockito.verify(response).setContentType( - ApplicationConstants.CONTENT_TYPE_TEXT_HTML_UTF_8); - } - - @After - public void tearDown() { - VaadinSession.setCurrent(null); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinRequestTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinRequestTest.java deleted file mode 100644 index eb052cc2346..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinRequestTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import org.junit.Test; -import org.mockito.Mockito; - -public class VaadinRequestTest { - - public static abstract class TestVaadinRequest implements VaadinRequest { - - } - - @Test - public void getContentLengthLong_delegateToGetContentLength() { - TestVaadinRequest request = Mockito.spy(TestVaadinRequest.class); - request.getContentLengthLong(); - Mockito.verify(request).getContentLength(); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServiceTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServiceTest.java deleted file mode 100644 index 39ac11dcc0b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServiceTest.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import net.jcip.annotations.NotThreadSafe; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpSessionBindingEvent; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.di.InstantiatorFactory; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.internal.UsageStatistics; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RouteData; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.server.communication.PwaHandler; -import com.vaadin.flow.server.communication.StreamRequestHandler; -import com.vaadin.flow.server.communication.WebComponentBootstrapHandler; -import com.vaadin.flow.server.communication.WebComponentProvider; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; - -/** - * - * @author Vaadin Ltd - * @since 1.0 - */ -@NotThreadSafe -public class VaadinServiceTest { - - @Tag("div") - public static class TestView extends Component { - - } - - private class TestSessionDestroyListener implements SessionDestroyListener { - - int callCount = 0; - - @Override - public void sessionDestroy(SessionDestroyEvent event) { - callCount++; - } - } - - private String createCriticalNotification(String caption, String message, - String details, String url) { - return VaadinService.createCriticalNotificationJSON(caption, message, - details, url); - } - - private static abstract class TestVaadinService extends VaadinService { - - @Override - protected List createRequestHandlers() - throws ServiceException { - return super.createRequestHandlers(); - } - } - - @Test - public void should_reported_routing_server() { - - // this test needs a fresh empty statistics, so we need to clear - // them for resusing forks for unit tests - UsageStatistics.resetEntries(); - - VaadinServiceInitListener initListener = event -> { - RouteConfiguration.forApplicationScope().setRoute("test", - TestView.class); - }; - MockInstantiator instantiator = new MockInstantiator(initListener); - - MockVaadinServletService service = new MockVaadinServletService(); - - service.init(instantiator); - - Assert.assertTrue(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_SERVER.equals(e.getName()))); - } - - @Test - public void should_reported_routing_hybrid() { - VaadinServiceInitListener initListener = event -> { - RouteConfiguration.forApplicationScope().setRoute("test", - TestView.class); - }; - UsageStatistics.markAsUsed(Constants.STATISTIC_ROUTING_CLIENT, - Version.getFullVersion()); - MockInstantiator instantiator = new MockInstantiator(initListener); - - MockVaadinServletService service = new MockVaadinServletService(); - - service.init(instantiator); - - Assert.assertTrue(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_HYBRID.equals(e.getName()))); - Assert.assertFalse(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_CLIENT.equals(e.getName()))); - Assert.assertFalse(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_SERVER.equals(e.getName()))); - } - - @Test - public void testFireSessionDestroy() - throws ServletException, ServiceException { - VaadinService service = createService(); - - TestSessionDestroyListener listener = new TestSessionDestroyListener(); - - service.addSessionDestroyListener(listener); - - MockVaadinSession vaadinSession = new MockVaadinSession(service); - service.fireSessionDestroy(vaadinSession); - Assert.assertEquals( - "'fireSessionDestroy' method doesn't call 'close' for the session", - 1, vaadinSession.getCloseCount()); - - vaadinSession.valueUnbound(Mockito.mock(HttpSessionBindingEvent.class)); - - Assert.assertEquals( - "'fireSessionDestroy' method may not call 'close' " - + "method for closing session", - 1, vaadinSession.getCloseCount()); - - Assert.assertEquals("SessionDestroyListeners not called exactly once", - 1, listener.callCount); - } - - @Test - public void captionIsSetToACriticalNotification() { - String notification = createCriticalNotification("foobar", "message", - "details", "url"); - - assertThat(notification, containsString("\"caption\":\"foobar\"")); - } - - @Test - public void nullCaptionIsSetToACriticalNotification() { - String notification = createCriticalNotification(null, "message", - "details", "url"); - - assertThat(notification, containsString("\"caption\":null")); - } - - @Test - public void messageWithDetailsIsSetToACriticalNotification() { - String notification = createCriticalNotification("caption", "foo", - "bar", "url"); - - assertThat(notification, containsString("\"details\":\"bar\"")); - } - - @Test - public void nullMessageSentAsNullInACriticalNotification() { - String notification = createCriticalNotification("caption", null, - "foobar", "url"); - - assertThat(notification, containsString("\"message\":null")); - } - - @Test - public void nullMessageIsSetToACriticalNotification() { - String notification = createCriticalNotification("caption", null, null, - "url"); - - assertThat(notification, containsString("\"message\":null")); - } - - @Test - public void messageSetToACriticalNotification() { - String notification = createCriticalNotification("caption", "foobar", - null, "url"); - - assertThat(notification, containsString("\"message\":\"foobar\"")); - } - - @Test - public void urlIsSetToACriticalNotification() { - String notification = createCriticalNotification("caption", "message", - "details", "foobar"); - - assertThat(notification, containsString("\"url\":\"foobar\"")); - } - - @Test - public void nullUrlIsSetToACriticalNotification() { - String notification = createCriticalNotification("caption", "message", - "details", null); - - assertThat(notification, containsString("\"url\":null")); - } - - @Test - public void serviceContainsStreamRequestHandler() - throws ServiceException, ServletException { - ServletConfig servletConfig = new MockServletConfig(); - Lookup lookup = Mockito.mock(Lookup.class); - servletConfig.getServletContext().setAttribute(Lookup.class.getName(), - lookup); - StaticFileHandlerFactory factory = Mockito - .mock(StaticFileHandlerFactory.class); - Mockito.when(lookup.lookup(StaticFileHandlerFactory.class)) - .thenReturn(factory); - VaadinServlet servlet = new VaadinServlet() { - @Override - protected DeploymentConfiguration createDeploymentConfiguration() - throws ServletException { - return new MockDeploymentConfiguration(); - } - }; - servlet.init(servletConfig); - VaadinService service = servlet.getService(); - Assert.assertTrue(service.createRequestHandlers().stream() - .filter(StreamRequestHandler.class::isInstance).findAny() - .isPresent()); - } - - @Test - public void currentInstancesAfterPendingAccessTasks() - throws ServiceException { - VaadinService service = createService(); - - MockVaadinSession session = new MockVaadinSession(service); - session.lock(); - service.accessSession(session, () -> { - CurrentInstance.set(String.class, "Set in task"); - }); - - CurrentInstance.set(String.class, "Original value"); - service.runPendingAccessTasks(session); - Assert.assertEquals( - "Original CurrentInstance should be set after the task has been run", - "Original value", CurrentInstance.get(String.class)); - } - - @Test - public void testServiceInitListener_accessApplicationRouteRegistry_registryAvailable() { - - VaadinServiceInitListener initListener = event -> { - Assert.assertNotNull("service init should have set thread local", - VaadinService.getCurrent()); - - Router router = event.getSource().getRouter(); - Assert.assertNotNull("Router should be initialized", router); - - Assert.assertNotNull("registry should be initialized", - router.getRegistry()); - - RouteConfiguration.forApplicationScope().setRoute("test", - TestView.class); - }; - MockInstantiator instantiator = new MockInstantiator(initListener); - - MockVaadinServletService service = new MockVaadinServletService(); - - service.init(instantiator); - - // the following will allow the route configuration call to work - VaadinService.setCurrent(service); - List availableRoutes = RouteConfiguration - .forApplicationScope().getAvailableRoutes(); - VaadinService.setCurrent(null); - - Assert.assertEquals(1, availableRoutes.size()); - Assert.assertEquals(availableRoutes.get(0).getUrl(), "test"); - } - - @Test - public void dependencyFilterOrder_bundeFiltersAfterApplicationFilters() { - DependencyFilter applicationFilter = (dependencies, - service) -> dependencies; - - MockDeploymentConfiguration configuration = new MockDeploymentConfiguration(); - - // Service that pretends to have a proper bundle - MockVaadinServletService service = new MockVaadinServletService( - configuration); - - service.init(new MockInstantiator(evt -> { - evt.addDependencyFilter(applicationFilter); - })); - - List filters = new ArrayList<>(); - service.getDependencyFilters().forEach(filters::add); - - Assert.assertEquals(1, filters.size()); - - Assert.assertSame(applicationFilter, filters.get(0)); - } - - @Test - public void loadInstantiators_instantiatorIsLoadedUsingFactoryFromLookup() - throws ServiceException { - VaadinService service = createService(); - - Lookup lookup = Mockito.mock(Lookup.class); - - service.getContext().setAttribute(Lookup.class, lookup); - - InstantiatorFactory factory = createInstantiatorFactory(lookup); - - Mockito.when(lookup.lookupAll(InstantiatorFactory.class)) - .thenReturn(Collections.singletonList(factory)); - - Optional loadedInstantiator = service.loadInstantiators(); - - Instantiator instantiator = factory.createInstantitor(null); - - Assert.assertSame(instantiator, loadedInstantiator.get()); - } - - @Test(expected = ServiceException.class) - public void loadInstantiators_twoFactoriesInLookup_throws() - throws ServiceException { - VaadinService service = createService(); - - Lookup lookup = Mockito.mock(Lookup.class); - - service.getContext().setAttribute(Lookup.class, lookup); - - InstantiatorFactory factory1 = createInstantiatorFactory(lookup); - InstantiatorFactory factory2 = createInstantiatorFactory(lookup); - - Mockito.when(lookup.lookupAll(InstantiatorFactory.class)) - .thenReturn(Arrays.asList(factory1, factory2)); - - service.loadInstantiators(); - } - - @Test - public void createRequestHandlers_pwaHandlerIsInList_webComponentHandlersAreInList() - throws ServiceException { - TestVaadinService service = Mockito.mock(TestVaadinService.class); - Mockito.doCallRealMethod().when(service).createRequestHandlers(); - - List handlers = service.createRequestHandlers(); - Set set = handlers.stream().map(Object::getClass) - .collect(Collectors.toSet()); - Assert.assertTrue(set.contains(PwaHandler.class)); - Assert.assertTrue(set.contains(WebComponentProvider.class)); - Assert.assertTrue(set.contains(WebComponentBootstrapHandler.class)); - } - - @Test - public void fireSessionDestroy_sessionStateIsSetToClosed() - throws ServletException, ServiceException { - VaadinService service = createService(); - - AtomicReference stateRef = new AtomicReference<>(); - MockVaadinSession vaadinSession = new MockVaadinSession(service) { - @Override - protected void setState(VaadinSessionState state) { - stateRef.set(state); - } - }; - - service.fireSessionDestroy(vaadinSession); - - Assert.assertEquals(VaadinSessionState.CLOSED, stateRef.get()); - } - - @Test - public void removeFromHttpSession_setExplicitSessionCloseAttribute() - throws ServiceException { - WrappedSession httpSession = Mockito.mock(WrappedSession.class); - VaadinSession session = Mockito.mock(VaadinSession.class); - VaadinService service = new MockVaadinServletService() { - - @Override - protected VaadinSession readFromHttpSession( - WrappedSession wrappedSession) { - return session; - } - }; - - service.init(); - - service.removeFromHttpSession(httpSession); - - Assert.assertTrue(session.sessionClosedExplicitly); - } - - @Test - public void reinitializeSession_setVaadinSessionAttriuteWithLock() { - VaadinRequest request = Mockito.mock(VaadinRequest.class); - - VaadinSession vaadinSession = Mockito.mock(VaadinSession.class); - VaadinSession newVaadinSession = Mockito.mock(VaadinSession.class); - - WrappedSession session = mockSession(request, vaadinSession, "foo"); - - Mockito.doAnswer(invocation -> { - mockSession(request, newVaadinSession, "bar"); - return null; - }).when(session).invalidate(); - - VaadinService.reinitializeSession(request); - - Mockito.verify(vaadinSession, Mockito.times(2)).lock(); - Mockito.verify(vaadinSession).setAttribute( - VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE, Boolean.TRUE); - Mockito.verify(vaadinSession).setAttribute( - VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE, null); - Mockito.verify(vaadinSession, Mockito.times(2)).unlock(); - } - - private WrappedSession mockSession(VaadinRequest request, - VaadinSession vaadinSession, String attributeName) { - WrappedSession session = Mockito.mock(WrappedSession.class); - Mockito.when(request.getWrappedSession()).thenReturn(session); - - Mockito.when(session.getAttributeNames()) - .thenReturn(Collections.singleton(attributeName)); - - Mockito.when(session.getAttribute(attributeName)) - .thenReturn(vaadinSession); - - VaadinService service = Mockito.mock(VaadinService.class); - - Mockito.when(vaadinSession.getService()).thenReturn(service); - return session; - } - - private InstantiatorFactory createInstantiatorFactory(Lookup lookup) { - InstantiatorFactory factory = Mockito.mock(InstantiatorFactory.class); - - Instantiator instantiator = Mockito.mock(Instantiator.class); - Mockito.when((factory.createInstantitor(Mockito.any()))) - .thenReturn(instantiator); - - Mockito.when(instantiator.init(Mockito.any())).thenReturn(true); - return factory; - } - - private static VaadinService createService() throws ServiceException { - VaadinService service = new MockVaadinServletService(); - return service; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletConfigTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletConfigTest.java deleted file mode 100644 index 1ec3987ce52..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletConfigTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -/** - * Test VaadinServletConfig property handling and function with VaadinContext. - */ -public class VaadinServletConfigTest { - - private VaadinServletConfig config; - - private ServletContext servletContext; - private final Map attributeMap = new HashMap<>(); - private Map properties; - - @Before - public void setup() { - ServletConfig servletConfig = Mockito.mock(ServletConfig.class); - servletContext = Mockito.mock(ServletContext.class); - - Mockito.when(servletConfig.getServletContext()) - .thenReturn(servletContext); - - Mockito.when(servletContext.getAttribute(Mockito.anyString())) - .then(invocationOnMock -> attributeMap - .get(invocationOnMock.getArguments()[0].toString())); - Mockito.doAnswer(invocationOnMock -> attributeMap.put( - invocationOnMock.getArguments()[0].toString(), - invocationOnMock.getArguments()[1])).when(servletContext) - .setAttribute(Mockito.anyString(), Mockito.any()); - - properties = new HashMap<>(); - properties.put(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, - "true"); - properties.put(InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER, - "false"); - - Mockito.when(servletConfig.getInitParameterNames()) - .thenReturn(Collections.enumeration(properties.keySet())); - Mockito.when(servletConfig.getInitParameter(Mockito.anyString())).then( - invocation -> properties.get(invocation.getArguments()[0])); - config = new VaadinServletConfig(servletConfig); - } - - @Test - public void getPropertyNames_returnsExpectedProperties() { - List list = Collections.list(config.getConfigParameterNames()); - Assert.assertEquals( - "Context should return only keys defined in ServletContext", - properties.size(), list.size()); - for (String key : properties.keySet()) { - Assert.assertEquals(String.format( - "Value should be same from context for key '%s'", key), - properties.get(key), config.getConfigParameter(key)); - } - } - - @Test - public void vaadinContextThroughConfig_setAndGetAttribute() { - String value = "my-attribute"; - config.getVaadinContext().setAttribute(value); - String result = config.getVaadinContext().getAttribute(String.class); - Assert.assertEquals(value, result); - // overwrite - String newValue = "this is a new value"; - config.getVaadinContext().setAttribute(newValue); - result = config.getVaadinContext().getAttribute(String.class); - Assert.assertEquals(newValue, result); - // now the provider should not be called, so value should be still there - result = config.getVaadinContext().getAttribute(String.class, () -> { - throw new AssertionError("Should not be called"); - }); - Assert.assertEquals(newValue, result); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletContextTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletContextTest.java deleted file mode 100644 index 1e4a0fb5128..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletContextTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -/** - * Tests for VaadinServletContext attribute storage and property delegation. - * - * @since 2.0.0 - */ -public class VaadinServletContextTest { - - private static String testAttributeProvider() { - return "RELAX_THIS_IS_A_TEST"; - } - - private VaadinServletContext context; - - private final Map attributeMap = new HashMap<>(); - private Map properties; - - @Before - public void setup() { - ServletContext servletContext = Mockito.mock(ServletContext.class); - Mockito.when(servletContext.getAttribute(Mockito.anyString())) - .then(invocationOnMock -> attributeMap - .get(invocationOnMock.getArguments()[0].toString())); - Mockito.doAnswer(invocationOnMock -> { - attributeMap.remove(invocationOnMock.getArguments()[0].toString()); - return null; - }).when(servletContext).removeAttribute(Mockito.anyString()); - - Mockito.doAnswer(invocationOnMock -> attributeMap.put( - invocationOnMock.getArguments()[0].toString(), - invocationOnMock.getArguments()[1])).when(servletContext) - .setAttribute(Mockito.anyString(), Mockito.any()); - - properties = new HashMap<>(); - properties.put(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, - "true"); - properties.put(InitParameters.SERVLET_PARAMETER_ENABLE_DEV_SERVER, - "false"); - - Mockito.when(servletContext.getInitParameterNames()) - .thenReturn(Collections.enumeration(properties.keySet())); - Mockito.when(servletContext.getInitParameter(Mockito.anyString())).then( - invocation -> properties.get(invocation.getArguments()[0])); - context = new VaadinServletContext(servletContext); - } - - @Test - public void getAttributeWithProvider() { - Assert.assertNull(context.getAttribute(String.class)); - - String value = context.getAttribute(String.class, - VaadinServletContextTest::testAttributeProvider); - Assert.assertEquals(testAttributeProvider(), value); - - Assert.assertEquals("Value from provider should be persisted", - testAttributeProvider(), context.getAttribute(String.class)); - } - - @Test(expected = AssertionError.class) - public void setNullAttributeNotAllowed() { - context.setAttribute(null); - } - - @Test - public void getMissingAttributeWithoutProvider() { - String value = context.getAttribute(String.class); - Assert.assertNull(value); - } - - @Test - public void setAndGetAttribute() { - String value = testAttributeProvider(); - context.setAttribute(value); - String result = context.getAttribute(String.class); - Assert.assertEquals(value, result); - // overwrite - String newValue = "this is a new value"; - context.setAttribute(newValue); - result = context.getAttribute(String.class); - Assert.assertEquals(newValue, result); - // now the provider should not be called, so value should be still there - result = context.getAttribute(String.class, () -> { - throw new AssertionError("Should not be called"); - }); - Assert.assertEquals(newValue, result); - } - - @Test - public void setValueBasedOnSuperType_implicitClass_notFound() { - String value = testAttributeProvider(); - context.setAttribute(value); - - CharSequence retrieved = context.getAttribute(CharSequence.class); - Assert.assertNull( - "Value set base on its own type should not be found based on a super type", - retrieved); - } - - @Test - public void setValueBasedOnSuperType_explicitClass_found() { - String value = testAttributeProvider(); - context.setAttribute(CharSequence.class, value); - - CharSequence retrieved = context.getAttribute(CharSequence.class); - Assert.assertSame( - "Value should be found based on the type used when setting", - value, retrieved); - } - - @Test - public void removeValue_removeMethod_valueIsRemoved() { - context.setAttribute(testAttributeProvider()); - context.removeAttribute(String.class); - - Assert.assertNull("Value should be removed", - context.getAttribute(String.class)); - } - - @Test - public void removeValue_setWithClass_valueIsRemoved() { - context.setAttribute(testAttributeProvider()); - context.setAttribute(String.class, null); - - Assert.assertNull("Value should be removed", - context.getAttribute(String.class)); - } - - @Test - public void getPropertyNames_returnsExpectedProperties() { - List list = Collections - .list(context.getContextParameterNames()); - Assert.assertEquals( - "Context should return only keys defined in ServletContext", - properties.size(), list.size()); - for (String key : properties.keySet()) { - Assert.assertEquals(String.format( - "Value should be same from context for key '%s'", key), - properties.get(key), context.getContextParameter(key)); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletRequestTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletRequestTest.java deleted file mode 100644 index fe8e32a14b0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletRequestTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.http.HttpServletRequest; - -import org.junit.Test; -import org.mockito.Mockito; - -public class VaadinServletRequestTest { - - @Test - public void getContentLengthLong_delegateToServletRequestGetContentLengthLong() { - HttpServletRequest servletRequest = Mockito - .mock(HttpServletRequest.class); - - VaadinServletRequest request = new VaadinServletRequest(servletRequest, - null); - request.getContentLengthLong(); - Mockito.verify(servletRequest).getContentLengthLong(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletServiceTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletServiceTest.java deleted file mode 100644 index 06bb1d5ab4f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletServiceTest.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.http.HttpServletRequest; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collections; -import java.util.List; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.internal.UsageStatistics; -import com.vaadin.flow.server.MockServletServiceSessionSetup.TestVaadinServletService; -import com.vaadin.flow.theme.AbstractTheme; - -/** - * Test class for testing es6 resolution by browser capability. This is valid - * only for bower mode where we need to decide ourselves. - */ -public class VaadinServletServiceTest { - - private final class TestTheme implements AbstractTheme { - @Override - public String getBaseUrl() { - return "/raw/"; - } - - @Override - public String getThemeUrl() { - return "/theme/"; - } - } - - private MockServletServiceSessionSetup mocks; - private TestVaadinServletService service; - private VaadinServlet servlet; - - @Before - public void setup() throws Exception { - mocks = new MockServletServiceSessionSetup(); - service = mocks.getService(); - - servlet = mocks.getServlet(); - } - - @After - public void tearDown() { - mocks.cleanup(); - } - - @Test - public void resolveNullThrows() { - try { - service.resolveResource(null); - Assert.fail("null should not resolve"); - } catch (NullPointerException e) { - Assert.assertEquals("Url cannot be null", e.getMessage()); - } - } - - @Test - public void resolveResource() { - Assert.assertEquals("", service.resolveResource("")); - Assert.assertEquals("foo", service.resolveResource("foo")); - Assert.assertEquals("/foo", service.resolveResource("context://foo")); - } - - @Test - public void resolveResourceNPM_production() { - mocks.setProductionMode(true); - - Assert.assertEquals("", service.resolveResource("")); - Assert.assertEquals("foo", service.resolveResource("foo")); - Assert.assertEquals("/foo", service.resolveResource("context://foo")); - } - - @Test - public void getContextRootRelativePath_useVariousContextPathAndServletPathsAndPathInfo() - throws Exception { - String location; - - /* SERVLETS */ - // http://dummy.host:8080/contextpath/servlet - // should return . (relative url resolving to /contextpath) - location = testLocation("http://dummy.host:8080", "/contextpath", - "/servlet", ""); - Assert.assertEquals("./../", location); - - // http://dummy.host:8080/contextpath/servlet/ - // should return ./.. (relative url resolving to /contextpath) - location = testLocation("http://dummy.host:8080", "/contextpath", - "/servlet", "/"); - Assert.assertEquals("./../", location); - - // http://dummy.host:8080/servlet - // should return "." - location = testLocation("http://dummy.host:8080", "", "/servlet", ""); - Assert.assertEquals("./../", location); - - // http://dummy.host/contextpath/servlet/extra/stuff - // should return ./../.. (relative url resolving to /contextpath) - location = testLocation("http://dummy.host", "/contextpath", "/servlet", - "/extra/stuff"); - Assert.assertEquals("./../", location); - - // http://dummy.host/context/path/servlet/extra/stuff - // should return ./../.. (relative url resolving to /context/path) - location = testLocation("http://dummy.host", "/context/path", - "/servlet", "/extra/stuff"); - Assert.assertEquals("./../", location); - - } - - @Test - public void init_classLoaderIsSetUsingServletContext() - throws ServiceException { - VaadinServlet servlet = Mockito.mock(VaadinServlet.class); - ServletContext context = Mockito.mock(ServletContext.class); - Mockito.when(servlet.getServletContext()).thenReturn(context); - - ClassLoader loader = Mockito.mock(ClassLoader.class); - Mockito.when(context.getClassLoader()).thenReturn(loader); - - VaadinServletService service = new VaadinServletService(servlet, - mocks.getDeploymentConfiguration()) { - @Override - protected Instantiator createInstantiator() - throws ServiceException { - return Mockito.mock(Instantiator.class); - } - - @Override - protected List createRequestHandlers() - throws ServiceException { - return Collections.emptyList(); - } - }; - - service.init(); - - Assert.assertSame(loader, service.getClassLoader()); - } - - private String testLocation(String base, String contextPath, - String servletPath, String pathInfo) throws Exception { - - HttpServletRequest request = createNonIncludeRequest(base, contextPath, - servletPath, pathInfo); - - VaadinServletService service = Mockito.mock(VaadinServletService.class); - Mockito.doCallRealMethod().when(service) - .getContextRootRelativePath(Mockito.any()); - String location = service.getContextRootRelativePath( - servlet.createVaadinRequest(request)); - return location; - } - - private HttpServletRequest createNonIncludeRequest(String base, - String realContextPath, String realServletPath, String pathInfo) - throws Exception { - HttpServletRequest request = createRequest(base, realContextPath, - realServletPath, pathInfo); - Mockito.when( - request.getAttribute("jakarta.servlet.include.context_path")) - .thenReturn(null); - Mockito.when( - request.getAttribute("jakarta.servlet.include.servlet_path")) - .thenReturn(null); - - return request; - } - - /** - * Creates a HttpServletRequest mock using the supplied parameters. - * - * @param base - * The base url, e.g. http://localhost:8080 - * @param contextPath - * The context path where the application is deployed, e.g. - * /mycontext - * @param servletPath - * The servlet path to the servlet we are testing, e.g. /myapp - * @param pathInfo - * Any text following the servlet path in the request, not - * including query parameters, e.g. /UIDL/ - * @return A mock HttpServletRequest object useful for testing - * @throws MalformedURLException - */ - private HttpServletRequest createRequest(String base, String contextPath, - String servletPath, String pathInfo) throws MalformedURLException { - URL url = new URL(base + contextPath + pathInfo); - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Mockito.when(request.isSecure()) - .thenReturn(url.getProtocol().equalsIgnoreCase("https")); - Mockito.when(request.getServerName()).thenReturn(url.getHost()); - Mockito.when(request.getServerPort()).thenReturn(url.getPort()); - Mockito.when(request.getRequestURI()).thenReturn(url.getPath()); - Mockito.when(request.getContextPath()).thenReturn(contextPath); - Mockito.when(request.getPathInfo()).thenReturn(pathInfo); - Mockito.when(request.getServletPath()).thenReturn(servletPath); - - return request; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java deleted file mode 100644 index df2d7053d38..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinServletTest.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.internal.ApplicationClassLoaderAccess; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.internal.VaadinContextInitializer; - -@NotThreadSafe -public class VaadinServletTest { - - @Test - public void testGetLastPathParameter() { - Assert.assertEquals("", - VaadinServlet.getLastPathParameter("http://myhost.com")); - Assert.assertEquals(";a", - VaadinServlet.getLastPathParameter("http://myhost.com;a")); - Assert.assertEquals("", - VaadinServlet.getLastPathParameter("http://myhost.com/hello")); - Assert.assertEquals(";b=c", VaadinServlet - .getLastPathParameter("http://myhost.com/hello;b=c")); - Assert.assertEquals("", - VaadinServlet.getLastPathParameter("http://myhost.com/hello/")); - Assert.assertEquals("", VaadinServlet - .getLastPathParameter("http://myhost.com/hello;a/")); - Assert.assertEquals("", VaadinServlet - .getLastPathParameter("http://myhost.com/hello;a=1/")); - Assert.assertEquals(";b", VaadinServlet - .getLastPathParameter("http://myhost.com/hello/;b")); - Assert.assertEquals(";b=1", VaadinServlet - .getLastPathParameter("http://myhost.com/hello/;b=1")); - Assert.assertEquals(";b=1,c=2", VaadinServlet - .getLastPathParameter("http://myhost.com/hello/;b=1,c=2")); - Assert.assertEquals("", VaadinServlet - .getLastPathParameter("http://myhost.com/hello/;b=1,c=2/")); - Assert.assertEquals("", VaadinServlet - .getLastPathParameter("http://myhost.com/a;hello/;a/")); - Assert.assertEquals("", VaadinServlet - .getLastPathParameter("http://myhost.com/a;hello/;a=1/")); - Assert.assertEquals(";b", VaadinServlet - .getLastPathParameter("http://myhost.com/a;hello/;b")); - Assert.assertEquals(";b=1", VaadinServlet - .getLastPathParameter("http://myhost.com/a;hello/;b=1")); - Assert.assertEquals(";b=1,c=2", VaadinServlet - .getLastPathParameter("http://myhost.com/a;hello/;b=1,c=2")); - Assert.assertEquals("", VaadinServlet - .getLastPathParameter("http://myhost.com/a;hello/;b=1,c=2/")); - } - - @Test - public void init_superInitCalledOnce() throws ServletException { - AtomicBoolean called = new AtomicBoolean(); - VaadinServlet servlet = new VaadinServlet() { - - @Override - public void init() throws ServletException { - Assert.assertFalse(called.get()); - called.set(true); - } - }; - - ServletConfig config = mockConfig(); - servlet.init(config); - - Assert.assertTrue(called.get()); - - servlet.init(config); - - Assert.assertSame(config, servlet.getServletConfig()); - } - - @Test(expected = IllegalArgumentException.class) - public void init_passDifferentConfigInstance_throws() - throws ServletException { - VaadinServlet servlet = new VaadinServlet(); - - ServletConfig config = mockConfig(); - servlet.init(config); - - servlet.init(mockConfig()); - } - - @Test - public void init_noLookup_servletIsNotInitialized() - throws ServletException { - AtomicBoolean called = new AtomicBoolean(); - VaadinServlet servlet = new VaadinServlet() { - - @Override - protected void servletInitialized() throws ServletException { - called.set(true); - } - }; - - ServletConfig config = mockConfig(); - servlet.init(config); - - Assert.assertFalse(called.get()); - } - - @Test - public void init_contextHasLookup_servletIsInitialized() - throws ServletException { - AtomicBoolean called = new AtomicBoolean(); - VaadinServlet servlet = new VaadinServlet() { - - @Override - protected VaadinServletService createServletService() - throws ServletException, ServiceException { - return Mockito.mock(VaadinServletService.class); - } - - @Override - protected StaticFileHandler createStaticFileHandler( - VaadinService servletService) { - return Mockito.mock(StaticFileHandler.class); - } - - @Override - protected void servletInitialized() throws ServletException { - called.set(true); - } - }; - - ServletConfig config = mockConfig(); - ServletContext servletContext = config.getServletContext(); - Mockito.when(servletContext.getAttribute(Lookup.class.getName())) - .thenReturn(Mockito.mock(Lookup.class)); - servlet.init(config); - - Assert.assertTrue(called.get()); - } - - @Test - public void init_initServlet_CurrentInstanceClearAllIsCalled() - throws ServletException { - try { - VaadinServlet servlet = new VaadinServlet() { - - @Override - public void init() throws ServletException { - VaadinSession.setCurrent(Mockito.mock(VaadinSession.class)); - } - - @Override - protected VaadinServletService createServletService() - throws ServletException, ServiceException { - VaadinService.setCurrent(Mockito.mock(VaadinService.class)); - return Mockito.mock(VaadinServletService.class); - } - - @Override - protected StaticFileHandler createStaticFileHandler( - VaadinService servletService) { - return Mockito.mock(StaticFileHandler.class); - } - - @Override - protected void servletInitialized() throws ServletException { - UI.setCurrent(new UI()); - } - }; - - ServletConfig config = mockConfig(); - ServletContext servletContext = config.getServletContext(); - Mockito.when(servletContext.getAttribute(Lookup.class.getName())) - .thenReturn(Mockito.mock(Lookup.class)); - servlet.init(config); - - Assert.assertNull(VaadinService.getCurrent()); - Assert.assertNull(UI.getCurrent()); - Assert.assertNull(VaadinSession.getCurrent()); - } finally { - CurrentInstance.clearAll(); - } - } - - @Test - public void init_initOnlyConfig_CurrentInstanceClearAllIsCalled() - throws ServletException { - try { - VaadinServlet servlet = new VaadinServlet() { - - @Override - public void init() throws ServletException { - VaadinService.setCurrent(Mockito.mock(VaadinService.class)); - } - - }; - - ServletConfig config = mockConfig(); - servlet.init(config); - - Assert.assertNull(VaadinService.getCurrent()); - } finally { - CurrentInstance.clearAll(); - } - } - - @Test - public void init_appClassLoaderIsSet() throws ServletException { - VaadinServlet servlet = new VaadinServlet(); - - ServletConfig config = mockConfig(); - ServletContext servletContext = config.getServletContext(); - ClassLoader loader = Mockito.mock(ClassLoader.class); - Mockito.when(servletContext.getClassLoader()).thenReturn(loader); - servlet.init(config); - - ArgumentCaptor captor = ArgumentCaptor - .forClass(ApplicationClassLoaderAccess.class); - Mockito.verify(servletContext).setAttribute( - Mockito.eq(ApplicationClassLoaderAccess.class.getName()), - captor.capture()); - - ApplicationClassLoaderAccess access = captor.getValue(); - Assert.assertSame(loader, access.getClassloader()); - } - - @Test - public void init_contextInitializationIsExecuted() throws ServletException { - VaadinServlet servlet = new VaadinServlet(); - - ServletConfig config = mockConfig(); - ServletContext servletContext = config.getServletContext(); - ClassLoader loader = Mockito.mock(ClassLoader.class); - - VaadinContextInitializer initializer = Mockito - .mock(VaadinContextInitializer.class); - - Mockito.when(servletContext - .getAttribute(VaadinContextInitializer.class.getName())) - .thenReturn(initializer); - - Mockito.when(servletContext.getClassLoader()).thenReturn(loader); - servlet.init(config); - - Mockito.verify(initializer) - .initialize(Mockito.any(VaadinContext.class)); - } - - @Test - public void init_initIsCalledAfterDestroy_passDifferentConfigInstance_servletIsInitialized() - throws ServletException { - VaadinServlet servlet = new VaadinServlet(); - - ServletConfig config = mockConfig(); - - servlet.init(config); - - Assert.assertSame(config, servlet.getServletConfig()); - - servlet.destroy(); - - ServletConfig newConfig = mockConfig(); - servlet.init(newConfig); - Assert.assertSame(newConfig, servlet.getServletConfig()); - } - - @Test - public void destroy_servletIsInitializedBeforeDestroy_servletConfigIsNullAfterDestroy() - throws ServletException { - VaadinServlet servlet = new VaadinServlet(); - - ServletConfig config = mockConfig(); - - servlet.init(config); - - servlet.destroy(); - - Assert.assertNull(servlet.getServletConfig()); - } - - @Test - public void createStaticFileHandler_delegateToStaticFileHandlerFactory() { - VaadinServlet servlet = new VaadinServlet(); - VaadinService service = Mockito.mock(VaadinService.class); - VaadinContext context = Mockito.mock(VaadinContext.class); - Mockito.when(service.getContext()).thenReturn(context); - Lookup lookup = Mockito.mock(Lookup.class); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(lookup); - - StaticFileHandlerFactory factory = Mockito - .mock(StaticFileHandlerFactory.class); - - Mockito.when(lookup.lookup(StaticFileHandlerFactory.class)) - .thenReturn(factory); - - StaticFileHandler handler = Mockito.mock(StaticFileHandler.class); - Mockito.when(factory.createHandler(service)).thenReturn(handler); - - StaticFileHandler result = servlet.createStaticFileHandler(service); - - Mockito.verify(factory).createHandler(service); - Assert.assertSame(handler, result); - } - - @Test - public void destroy_servletConfigAvailableInServbiceDestroy() - throws ServletException { - VaadinServletService service = Mockito.mock(VaadinServletService.class); - VaadinServlet servlet = new VaadinServlet() { - @Override - public VaadinServletService getService() { - return service; - } - }; - - AtomicReference configDuringDestroy = new AtomicReference<>(); - Mockito.doAnswer(invocation -> { - configDuringDestroy.set(servlet.getServletConfig()); - return null; - }).when(service).destroy(); - - ServletConfig config = mockConfig(); - - servlet.init(config); - - servlet.destroy(); - - Assert.assertSame(config, configDuringDestroy.get()); - } - - private ServletConfig mockConfig() { - ServletConfig config = Mockito.mock(ServletConfig.class); - ServletContext context = Mockito.mock(ServletContext.class); - Mockito.when(config.getServletContext()).thenReturn(context); - return config; - } - - private HttpServletRequest createRequest( - MockServletServiceSessionSetup mocks, String path) { - HttpServletRequest httpServletRequest = Mockito - .mock(HttpServletRequest.class); - return new VaadinServletRequest(httpServletRequest, - mocks.getService()) { - @Override - public String getPathInfo() { - return path; - } - - @Override - public String getServletPath() { - return ""; - } - - @Override - public ServletContext getServletContext() { - return mocks.getServletContext(); - } - }; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/VaadinSessionTest.java b/flow-server/src/test/java/com/vaadin/flow/server/VaadinSessionTest.java deleted file mode 100644 index ad07efa8013..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/VaadinSessionTest.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.EventObject; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; -import jakarta.servlet.http.HttpSessionBindingEvent; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.communication.AtmospherePushConnection; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.flow.shared.communication.PushMode; -import com.vaadin.flow.testcategory.SlowTests; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -public class VaadinSessionTest { - - /** - * Event fired before a connector is detached from the application. - */ - public static class UIDetachEvent extends EventObject { - public UIDetachEvent(UI source) { - super(source); - } - } - - private VaadinSession session; - private VaadinServlet mockServlet; - private VaadinServletService mockService; - private HttpSession mockHttpSession; - private WrappedSession mockWrappedSession; - private VaadinServletRequest vaadinRequest; - private UI ui; - private Lock httpSessionLock; - - @Before - public void setup() throws Exception { - httpSessionLock = new ReentrantLock(); - mockService = new MockVaadinServletService(); - mockServlet = mockService.getServlet(); - - mockHttpSession = Mockito.mock(HttpSession.class); - mockWrappedSession = new WrappedHttpSession(mockHttpSession) { - final ReentrantLock lock = new ReentrantLock(); - - { - lock.lock(); - } - - @Override - public Object getAttribute(String name) { - Object res; - try { - Thread.sleep(100); // for deadlock testing - org.junit.Assert.assertTrue("Deadlock detected", - httpSessionLock.tryLock(5, TimeUnit.SECONDS)); // simulates - // servlet - // container's - // session - // locking - String lockAttribute = mockService.getServiceName() - + ".lock"; - if (lockAttribute.equals(name)) { - res = lock; - } else if ((VaadinSession.class.getName() + ".Mock Servlet") - .equals(name)) { - res = session; - } else { - res = super.getAttribute(name); - } - httpSessionLock.unlock(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - return res; - } - }; - - session = new VaadinSession(mockService); - mockService.storeSession(session, mockWrappedSession); - - MockDeploymentConfiguration configuration = new MockDeploymentConfiguration(); - session.lock(); - session.setConfiguration(configuration); - session.unlock(); - - ui = new UI(); - vaadinRequest = new VaadinServletRequest( - Mockito.mock(HttpServletRequest.class), mockService) { - @Override - public String getParameter(String name) { - if ("restartApplication".equals(name) - || "ignoreRestart".equals(name) - || "closeApplication".equals(name)) { - return null; - } - return "1"; - } - - @Override - public String getPathInfo() { - return "/APP/"; - } - - @Override - public String getMethod() { - return "POST"; - } - - @Override - public WrappedSession getWrappedSession( - boolean allowSessionCreation) { - return mockWrappedSession; - } - - @Override - public Map getParameterMap() { - return new HashMap<>(); - } - - }; - - ui.getInternals().setSession(session); - - ui.doInit(vaadinRequest, session.getNextUIid()); - - session.addUI(ui); - - } - - /** - * This reproduces #14452 situation with deadlock - see diagram - */ - @Test - @Category(SlowTests.class) - public void testInvalidationDeadlock() { - - // this simulates servlet container's session invalidation from another - // thread - new Thread(() -> { - try { - Thread.sleep(150); // delay selected so that VaadinSession - // will be already locked by the main - // thread - // when we get here - httpSessionLock.lock();// simulating servlet container's - // session lock - mockService.fireSessionDestroy(session); - httpSessionLock.unlock(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - }).start(); - - try { - mockService.findVaadinSession(vaadinRequest); - } catch (Exception e) { - throw new RuntimeException(e); - } - - } - - @Test - public void threadLocalsAfterUnderlyingSessionTimeout() - throws InterruptedException { - - final AtomicBoolean detachCalled = new AtomicBoolean(false); - ui.addDetachListener(e -> { - detachCalled.set(true); - Assert.assertEquals(ui, UI.getCurrent()); - Assert.assertEquals(session, VaadinSession.getCurrent()); - Assert.assertEquals(mockService, VaadinService.getCurrent()); - Assert.assertEquals(mockServlet, VaadinServlet.getCurrent()); - }); - - session.valueUnbound(Mockito.mock(HttpSessionBindingEvent.class)); - mockService.runPendingAccessTasks(session); // as soon as we changed - // session.accessSynchronously - // to session.access in - // VaadinService.fireSessionDestroy, - // we need to run the - // pending task ourselves - Assert.assertTrue(detachCalled.get()); - } - - @Test - @Category(SlowTests.class) - public void threadLocalsAfterSessionDestroy() throws InterruptedException { - final AtomicBoolean detachCalled = new AtomicBoolean(false); - ui.addDetachListener(e -> { - detachCalled.set(true); - Assert.assertEquals(ui, UI.getCurrent()); - Assert.assertEquals(session, VaadinSession.getCurrent()); - Assert.assertEquals(mockService, VaadinService.getCurrent()); - Assert.assertEquals(mockServlet, VaadinServlet.getCurrent()); - }); - CurrentInstance.clearAll(); - session.close(); - mockService.cleanupSession(session); - mockService.runPendingAccessTasks(session); // as soon as we changed - // session.accessSynchronously - // to session.access in - // VaadinService.fireSessionDestroy, - // we need to run the - // pending task ourselves - Assert.assertTrue(detachCalled.get()); - } - - @Test - public void testValueUnbound() { - MockVaadinSession vaadinSession = new MockVaadinSession(mockService); - - vaadinSession.valueUnbound(Mockito.mock(HttpSessionBindingEvent.class)); - org.junit.Assert.assertEquals( - "'valueUnbound' method doesn't call 'close' for the session", 1, - vaadinSession.getCloseCount()); - - vaadinSession.valueUnbound(Mockito.mock(HttpSessionBindingEvent.class)); - - org.junit.Assert.assertEquals( - "'valueUnbound' method may not call 'close' " - + "method for closing session", - 1, vaadinSession.getCloseCount()); - } - - private static class SerializationPushConnection - extends AtmospherePushConnection { - - private transient VaadinSession session = VaadinSession.getCurrent(); - - public SerializationPushConnection(UI ui) { - super(ui); - } - - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException { - in.defaultReadObject(); - session = VaadinSession.getCurrent(); - } - } - - @Test - @Category(SlowTests.class) - public void threadLocalsWhenDeserializing() throws Exception { - ApplicationConfiguration configuration = Mockito - .mock(ApplicationConfiguration.class); - - Mockito.when(configuration.isDevModeSessionSerializationEnabled()) - .thenReturn(true); - - mockServlet.getServletContext().setAttribute( - ApplicationConfiguration.class.getName(), configuration); - - VaadinSession.setCurrent(session); - session.lock(); - SerializationPushConnection pc = new SerializationPushConnection(ui); - Assert.assertEquals("Session should be set when instance is created", - session, pc.session); - ui.getPushConfiguration().setPushMode(PushMode.MANUAL); - ui.getInternals().setPushConnection(pc); - int uiId = ui.getUIId(); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(bos); - out.writeObject(session); - out.close(); - - session.unlock(); - - CurrentInstance.clearAll(); - - ObjectInputStream in = new ObjectInputStream( - new ByteArrayInputStream(bos.toByteArray())); - - VaadinSession deserializedSession = (VaadinSession) in.readObject(); - - Assert.assertNull("Current session shouldn't leak from deserialisation", - VaadinSession.getCurrent()); - - Assert.assertNotSame("Should get a new session", session, - deserializedSession); - - // Restore http session and service instance so the session can be - // locked - deserializedSession.refreshTransients(mockWrappedSession, mockService); - deserializedSession.lock(); - - UI deserializedUi = deserializedSession.getUIById(uiId); - SerializationPushConnection deserializedPc = (SerializationPushConnection) deserializedUi - .getInternals().getPushConnection(); - - Assert.assertEquals( - "Current session should be available in SerializationTestLabel.readObject", - deserializedSession, deserializedPc.session); - deserializedSession.unlock(); - } - - @Test - public void setLocale_setLocaleForAllUIs() { - UI anotherUI = new UI(); - - anotherUI.getInternals().setSession(session); - - anotherUI.doInit(vaadinRequest, session.getNextUIid()); - - session.addUI(anotherUI); - - Assert.assertEquals(2, session.getUIs().size()); - - Set locales = session.getUIs().stream().map(UI::getLocale) - .collect(Collectors.toSet()); - - Optional newLocale = Stream.of(Locale.getAvailableLocales()) - .filter(locale -> !locales.contains(locale) - && !locale.toString().trim().isEmpty()) - .findFirst(); - - session.setLocale(newLocale.get()); - - Locale expectedlocale = newLocale.get(); - - Iterator uis = session.getUIs().iterator(); - Assert.assertEquals(expectedlocale, uis.next().getLocale()); - Assert.assertEquals(expectedlocale, uis.next().getLocale()); - } - - @Test - public void valueUnbound_explicitVaadinSessionClose_wrappedSessionIsNotCleanedUp() { - ReentrantLock lock = Mockito.mock(ReentrantLock.class); - Mockito.when(lock.isHeldByCurrentThread()).thenReturn(true); - mockService = new MockVaadinServletService() { - @Override - protected Lock getSessionLock(WrappedSession wrappedSession) { - return lock; - } - - }; - - VaadinSession vaadinSession = new VaadinSession(mockService) { - @Override - public boolean hasLock() { - return true; - } - }; - - vaadinSession.sessionClosedExplicitly = true; - - WrappedSession httpSession = Mockito.mock(WrappedSession.class); - vaadinSession.refreshTransients(httpSession, mockService); - - VaadinSession.setCurrent(vaadinSession); - mockService.setCurrentInstances(Mockito.mock(VaadinRequest.class), - Mockito.mock(VaadinResponse.class)); - - try { - vaadinSession - .valueUnbound(Mockito.mock(HttpSessionBindingEvent.class)); - - Assert.assertNotNull(vaadinSession.getSession()); - } finally { - CurrentInstance.clearAll(); - } - } - - @Test - public void valueUnbound_implicitVaadinSessionClose_wrappedSessionIsCleanedUp() { - ReentrantLock lock = Mockito.mock(ReentrantLock.class); - Mockito.when(lock.isHeldByCurrentThread()).thenReturn(true); - mockService = new MockVaadinServletService() { - @Override - protected Lock getSessionLock(WrappedSession wrappedSession) { - return lock; - } - }; - - VaadinSession vaadinSession = new VaadinSession(mockService) { - @Override - public boolean hasLock() { - return true; - } - }; - - WrappedSession httpSession = Mockito.mock(WrappedSession.class); - vaadinSession.refreshTransients(httpSession, mockService); - - VaadinSession.setCurrent(vaadinSession); - mockService.setCurrentInstances(Mockito.mock(VaadinRequest.class), - Mockito.mock(VaadinResponse.class)); - - try { - vaadinSession - .valueUnbound(Mockito.mock(HttpSessionBindingEvent.class)); - - Assert.assertNull(vaadinSession.getSession()); - } finally { - CurrentInstance.clearAll(); - } - } - - @Test - public void setState_closedState_sessionFieldIsCleanedUp() { - ReentrantLock lock = Mockito.mock(ReentrantLock.class); - Mockito.when(lock.isHeldByCurrentThread()).thenReturn(true); - mockService = new MockVaadinServletService() { - @Override - protected Lock getSessionLock(WrappedSession wrappedSession) { - return lock; - } - }; - - VaadinSession vaadinSession = new VaadinSession(mockService); - WrappedSession httpSession = Mockito.mock(WrappedSession.class); - vaadinSession.refreshTransients(httpSession, mockService); - - vaadinSession.setState(VaadinSessionState.CLOSING); - vaadinSession.setState(VaadinSessionState.CLOSED); - - Assert.assertNull(vaadinSession.getSession()); - } - - @Test - public void valueUnbound_sessionIsNotInitialized_noAnyInteractions() { - VaadinSession session = Mockito.spy(TestVaadinSession.class); - - HttpSessionBindingEvent event = Mockito - .mock(HttpSessionBindingEvent.class); - session.valueUnbound(null); - - Mockito.verify(session).valueUnbound(null); - Mockito.verifyNoInteractions(event); - Mockito.verifyNoMoreInteractions(session); - } - - public static class TestVaadinSession extends VaadinSession { - - public TestVaadinSession() { - super(null); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/WebBrowserTest.java b/flow-server/src/test/java/com/vaadin/flow/server/WebBrowserTest.java deleted file mode 100644 index 377f046768f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/WebBrowserTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server; - -import org.junit.Assert; -import org.junit.Test; - -public class WebBrowserTest { - - private WebBrowser browser = new WebBrowser(); - - @Test - public void isLinux_noDetails_returnsFalse() { - Assert.assertFalse(browser.isLinux()); - } - - @Test - public void isMacOSX_noDetails_returnsFalse() { - Assert.assertFalse(browser.isMacOSX()); - } - - @Test - public void isWindows_noDetails_returnsFalse() { - Assert.assertFalse(browser.isWindows()); - } - - @Test - public void isWindowsPhone_noDetails_returnsFalse() { - Assert.assertFalse(browser.isWindowsPhone()); - } - - @Test - public void isAndroid_noDetails_returnsFalse() { - Assert.assertFalse(browser.isAndroid()); - } - - @Test - public void isIPhone_noDetails_returnsFalse() { - Assert.assertFalse(browser.isIPhone()); - } - - @Test - public void isChromeOS_noDetails_returnsFalse() { - Assert.assertFalse(browser.isChromeOS()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/auth/AccessAnnotationCheckerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/auth/AccessAnnotationCheckerTest.java deleted file mode 100644 index b9ba5f72a13..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/auth/AccessAnnotationCheckerTest.java +++ /dev/null @@ -1,399 +0,0 @@ -package com.vaadin.flow.server.auth; - -import static org.junit.Assert.assertEquals; - -import java.lang.reflect.Method; -import java.security.Principal; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.stream.Stream; - -import jakarta.servlet.http.HttpServletRequest; - -import com.vaadin.flow.component.internal.JavaScriptBootstrapUI.ClientViewPlaceholder; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.router.InternalServerError; -import com.vaadin.flow.router.RouteNotFoundError; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.auth.AccessControlTestClasses.AnonymousAllowedClass; -import com.vaadin.flow.server.auth.AccessControlTestClasses.DenyAllClass; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationClass; -import com.vaadin.flow.server.auth.AccessControlTestClasses.PermitAllClass; -import com.vaadin.flow.server.auth.AccessControlTestClasses.RolesAllowedAdminClass; -import com.vaadin.flow.server.auth.AccessControlTestClasses.RolesAllowedUserClass; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -public class AccessAnnotationCheckerTest { - public static final Class[] ENDPOINT_CLASSES = new Class[] { - AccessControlTestClasses.AnonymousAllowedClass.class, - AccessControlTestClasses.DenyAllClass.class, - AccessControlTestClasses.NoAnnotationClass.class, - AccessControlTestClasses.PermitAllClass.class, - AccessControlTestClasses.RolesAllowedAdminClass.class, - AccessControlTestClasses.RolesAllowedUserClass.class }; - - public static final String[] ENDPOINT_METHODS = new String[] { - "noAnnotation", "anonymousAllowed", "permitAll", "denyAll", - "rolesAllowedUser", "rolesAllowedAdmin", "rolesAllowedUserAdmin" }; - - public static final String[] ENDPOINT_NAMES = Stream.of(ENDPOINT_CLASSES) - .map(cls -> cls.getSimpleName().toLowerCase(Locale.ENGLISH)) - .toArray(String[]::new); - - static final Principal USER_PRINCIPAL = new Principal() { - @Override - public String getName() { - return "John Doe"; - } - }; - static final String REQUEST_URL = "http://localhost:8080/myapp/"; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private AccessAnnotationChecker accessAnnotationChecker; - - @Before - public void before() { - accessAnnotationChecker = new AccessAnnotationChecker(); - } - - @Test - public void should_Throw_When_PrivateMethodIsPassed() throws Exception { - class Test { - private void test() { - } - } - - Method method = Test.class.getDeclaredMethod("test"); - exception.expect(IllegalArgumentException.class); - exception.expectMessage(method.toString()); - accessAnnotationChecker.getSecurityTarget(method); - } - - @Test - public void should_ReturnEnclosingClassAsSecurityTarget_When_NoSecurityAnnotationsPresent() - throws Exception { - class Test { - public void test() { - } - } - assertEquals(Test.class, accessAnnotationChecker - .getSecurityTarget(Test.class.getMethod("test"))); - } - - @Test - public void should_ReturnEnclosingClassAsSecurityTarget_When_OnlyClassHasSecurityAnnotations() - throws Exception { - @AnonymousAllowed - class Test { - public void test() { - } - } - assertEquals(Test.class, accessAnnotationChecker - .getSecurityTarget(Test.class.getMethod("test"))); - } - - @Test - public void should_ReturnMethodAsSecurityTarget_When_OnlyMethodHasSecurityAnnotations() - throws Exception { - class Test { - @AnonymousAllowed - public void test() { - } - } - Method securityMethod = Test.class.getMethod("test"); - assertEquals(securityMethod, - accessAnnotationChecker.getSecurityTarget(securityMethod)); - } - - @Test - public void should_ReturnMethodAsSecurityTarget_When_BothClassAndMethodHaveSecurityAnnotations() - throws Exception { - @AnonymousAllowed - class Test { - @AnonymousAllowed - public void test() { - } - } - Method securityMethod = Test.class.getMethod("test"); - assertEquals(securityMethod, - accessAnnotationChecker.getSecurityTarget(securityMethod)); - } - - @Test - public void specialViewsMustBeAccessible() { - CurrentInstance.set(VaadinRequest.class, - new VaadinServletRequest(createRequest(null), null)); - Assert.assertTrue( - accessAnnotationChecker.hasAccess(ClientViewPlaceholder.class)); - Assert.assertTrue( - accessAnnotationChecker.hasAccess(InternalServerError.class)); - Assert.assertTrue( - accessAnnotationChecker.hasAccess(RouteNotFoundError.class)); - } - - @Test - public void anonymousAccessAllowed() throws Exception { - HttpServletRequest anonRequest = createRequest(null); - - verifyMethodAccessAllowed(AnonymousAllowedClass.class, anonRequest, - "noAnnotation", "anonymousAllowed"); - verifyMethodAccessAllowed(DenyAllClass.class, anonRequest, - "anonymousAllowed"); - verifyMethodAccessAllowed(NoAnnotationClass.class, anonRequest, - "anonymousAllowed"); - verifyMethodAccessAllowed(PermitAllClass.class, anonRequest, - "anonymousAllowed"); - verifyMethodAccessAllowed(RolesAllowedAdminClass.class, anonRequest, - "anonymousAllowed"); - verifyMethodAccessAllowed(RolesAllowedUserClass.class, anonRequest, - "anonymousAllowed"); - // Class level access - verifyClassAccessAllowed(AnonymousAllowedClass.class, anonRequest, - true); - verifyClassAccessAllowed(DenyAllClass.class, anonRequest, false); - verifyClassAccessAllowed(NoAnnotationClass.class, anonRequest, false); - verifyClassAccessAllowed(PermitAllClass.class, anonRequest, false); - verifyClassAccessAllowed(RolesAllowedAdminClass.class, anonRequest, - false); - verifyClassAccessAllowed(RolesAllowedUserClass.class, anonRequest, - false); - } - - @Test - public void loggedInUserAccessAllowed() throws Exception { - HttpServletRequest loggedInURequest = createRequest(USER_PRINCIPAL); - - verifyMethodAccessAllowed(AnonymousAllowedClass.class, loggedInURequest, - "noAnnotation", "anonymousAllowed", "permitAll"); - verifyMethodAccessAllowed(DenyAllClass.class, loggedInURequest, - "anonymousAllowed", "permitAll"); - verifyMethodAccessAllowed(NoAnnotationClass.class, loggedInURequest, - "anonymousAllowed", "permitAll"); - verifyMethodAccessAllowed(PermitAllClass.class, loggedInURequest, - "noAnnotation", "anonymousAllowed", "permitAll"); - verifyMethodAccessAllowed(RolesAllowedAdminClass.class, - loggedInURequest, "anonymousAllowed", "permitAll"); - verifyMethodAccessAllowed(RolesAllowedUserClass.class, loggedInURequest, - "anonymousAllowed", "permitAll"); - // Class level access - verifyClassAccessAllowed(AnonymousAllowedClass.class, loggedInURequest, - true); - verifyClassAccessAllowed(DenyAllClass.class, loggedInURequest, false); - verifyClassAccessAllowed(NoAnnotationClass.class, loggedInURequest, - false); - verifyClassAccessAllowed(PermitAllClass.class, loggedInURequest, true); - verifyClassAccessAllowed(RolesAllowedAdminClass.class, loggedInURequest, - false); - verifyClassAccessAllowed(RolesAllowedUserClass.class, loggedInURequest, - false); - } - - @Test - public void userRoleAccessAllowed() throws Exception { - HttpServletRequest userRoleRequest = createRequest(USER_PRINCIPAL, - "user"); - - verifyMethodAccessAllowed(AnonymousAllowedClass.class, userRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedUser", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(DenyAllClass.class, userRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedUser", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(NoAnnotationClass.class, userRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedUser", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(PermitAllClass.class, userRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedUser", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(RolesAllowedAdminClass.class, userRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedUser", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(RolesAllowedUserClass.class, userRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedUser", "rolesAllowedUserAdmin"); - // Class level access - verifyClassAccessAllowed(AnonymousAllowedClass.class, userRoleRequest, - true); - verifyClassAccessAllowed(DenyAllClass.class, userRoleRequest, false); - verifyClassAccessAllowed(NoAnnotationClass.class, userRoleRequest, - false); - verifyClassAccessAllowed(PermitAllClass.class, userRoleRequest, true); - verifyClassAccessAllowed(RolesAllowedAdminClass.class, userRoleRequest, - false); - verifyClassAccessAllowed(RolesAllowedUserClass.class, userRoleRequest, - true); - } - - @Test - public void userAndAdminRoleAccessAllowed() throws Exception { - HttpServletRequest adminRoleRequest = createRequest(USER_PRINCIPAL, - "user", "admin"); - - // Method level access - - verifyMethodAccessAllowed(AnonymousAllowedClass.class, adminRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedUser", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(DenyAllClass.class, adminRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedUser", - "rolesAllowedAdmin", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(NoAnnotationClass.class, adminRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedUser", - "rolesAllowedAdmin", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(PermitAllClass.class, adminRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedUser", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(RolesAllowedAdminClass.class, - adminRoleRequest, "noAnnotation", "anonymousAllowed", - "permitAll", "rolesAllowedUser", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(RolesAllowedUserClass.class, adminRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedUser", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - - // Class level access - verifyClassAccessAllowed(AnonymousAllowedClass.class, adminRoleRequest, - true); - verifyClassAccessAllowed(DenyAllClass.class, adminRoleRequest, false); - verifyClassAccessAllowed(NoAnnotationClass.class, adminRoleRequest, - false); - verifyClassAccessAllowed(PermitAllClass.class, adminRoleRequest, true); - verifyClassAccessAllowed(RolesAllowedAdminClass.class, adminRoleRequest, - true); - verifyClassAccessAllowed(RolesAllowedUserClass.class, adminRoleRequest, - true); - } - - @Test - public void adminRoleAccessAllowed() throws Exception { - HttpServletRequest adminRoleRequest = createRequest(USER_PRINCIPAL, - "admin"); - - verifyMethodAccessAllowed(AnonymousAllowedClass.class, adminRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedAdmin", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(DenyAllClass.class, adminRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(NoAnnotationClass.class, adminRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(PermitAllClass.class, adminRoleRequest, - "noAnnotation", "anonymousAllowed", "permitAll", - "rolesAllowedAdmin", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(RolesAllowedAdminClass.class, - adminRoleRequest, "noAnnotation", "anonymousAllowed", - "permitAll", "rolesAllowedAdmin", "rolesAllowedUserAdmin"); - verifyMethodAccessAllowed(RolesAllowedUserClass.class, adminRoleRequest, - "anonymousAllowed", "permitAll", "rolesAllowedAdmin", - "rolesAllowedUserAdmin"); - - // Class level access - verifyClassAccessAllowed(AnonymousAllowedClass.class, adminRoleRequest, - true); - verifyClassAccessAllowed(DenyAllClass.class, adminRoleRequest, false); - verifyClassAccessAllowed(NoAnnotationClass.class, adminRoleRequest, - false); - verifyClassAccessAllowed(PermitAllClass.class, adminRoleRequest, true); - verifyClassAccessAllowed(RolesAllowedAdminClass.class, adminRoleRequest, - true); - verifyClassAccessAllowed(RolesAllowedUserClass.class, adminRoleRequest, - false); - } - - @Test(expected = IllegalStateException.class) - public void hasClassAccessNoCurrentRequest() { - CurrentInstance.clearAll(); - accessAnnotationChecker.hasAccess(AnonymousAllowedClass.class); - } - - @Test(expected = IllegalStateException.class) - public void hasMethodAccessNoCurrentRequest() throws Exception { - CurrentInstance.clearAll(); - accessAnnotationChecker - .hasAccess(AnonymousAllowedClass.class.getMethod("permitAll")); - } - - @Test - public void hasClassAccessUsingCurrentRequest() { - try { - CurrentInstance.set(VaadinRequest.class, new VaadinServletRequest( - createRequest(USER_PRINCIPAL), null)); - Assert.assertTrue( - accessAnnotationChecker.hasAccess(PermitAllClass.class)); - } finally { - CurrentInstance.clearAll(); - } - } - - @Test - public void hasMethodAccessUsingCurrentRequest() throws Exception { - try { - CurrentInstance.set(VaadinRequest.class, new VaadinServletRequest( - createRequest(USER_PRINCIPAL), null)); - Assert.assertTrue(accessAnnotationChecker - .hasAccess(PermitAllClass.class.getMethod("permitAll"))); - } finally { - CurrentInstance.clearAll(); - } - } - - static HttpServletRequest createRequest(Principal userPrincipal, - String... roles) { - Set roleSet = new HashSet<>(); - Collections.addAll(roleSet, roles); - - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Mockito.when(request.getUserPrincipal()).thenReturn(userPrincipal); - Mockito.when(request.isUserInRole(Mockito.anyString())) - .thenAnswer(query -> { - return roleSet.contains(query.getArguments()[0]); - }); - Mockito.when(request.getRequestURL()) - .thenReturn(new StringBuffer(REQUEST_URL)); - return request; - } - - private void verifyMethodAccessAllowed(Class endpointClass, - HttpServletRequest request, String... expectedAccessibleMethods) - throws Exception { - List expectedAnonList = Arrays - .asList(expectedAccessibleMethods); - for (String endpointMethod : ENDPOINT_METHODS) { - boolean expectedResult = expectedAnonList.contains(endpointMethod); - Method method = endpointClass.getMethod(endpointMethod); - Assert.assertEquals("Expected " + endpointClass.getSimpleName() - + "." + endpointMethod + " to " - + (expectedResult ? "be" : "NOT to be") + " accessible", - expectedResult, - accessAnnotationChecker.hasAccess(method, request)); - } - } - - private void verifyClassAccessAllowed(Class cls, - HttpServletRequest request, boolean expectedResult) - throws Exception { - Assert.assertEquals( - "Expected " + cls.getSimpleName() + " to " - + (expectedResult ? "be" : "NOT to be") + " accessible", - expectedResult, - accessAnnotationChecker.hasAccess(cls, request)); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/auth/AccessControlTestClasses.java b/flow-server/src/test/java/com/vaadin/flow/server/auth/AccessControlTestClasses.java deleted file mode 100644 index 8e01b40f6e1..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/auth/AccessControlTestClasses.java +++ /dev/null @@ -1,351 +0,0 @@ -package com.vaadin.flow.server.auth; - -import jakarta.annotation.security.DenyAll; -import jakarta.annotation.security.PermitAll; -import jakarta.annotation.security.RolesAllowed; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.router.Route; - -public class AccessControlTestClasses { - - public static class NoAnnotationClass { - - public void noAnnotation() { - - } - - @AnonymousAllowed - public void anonymousAllowed() { - - } - - @PermitAll - public void permitAll() { - - } - - @DenyAll - public void denyAll() { - - } - - @RolesAllowed("user") - public void rolesAllowedUser() { - - } - - @RolesAllowed("admin") - public void rolesAllowedAdmin() { - - } - - @RolesAllowed({ "user", "admin" }) - public void rolesAllowedUserAdmin() { - } - - } - - @AnonymousAllowed - public static class AnonymousAllowedClass { - - public void noAnnotation() { - - } - - @AnonymousAllowed - public void anonymousAllowed() { - - } - - @PermitAll - public void permitAll() { - - } - - @DenyAll - public void denyAll() { - - } - - @RolesAllowed("user") - public void rolesAllowedUser() { - - } - - @RolesAllowed("admin") - public void rolesAllowedAdmin() { - - } - - @RolesAllowed({ "user", "admin" }) - public void rolesAllowedUserAdmin() { - } - - } - - @PermitAll - public static class PermitAllClass { - - public void noAnnotation() { - - } - - @AnonymousAllowed - public void anonymousAllowed() { - - } - - @PermitAll - public void permitAll() { - - } - - @DenyAll - public void denyAll() { - - } - - @RolesAllowed("user") - public void rolesAllowedUser() { - - } - - @RolesAllowed("admin") - public void rolesAllowedAdmin() { - - } - - @RolesAllowed({ "user", "admin" }) - public void rolesAllowedUserAdmin() { - } - - } - - @DenyAll - public static class DenyAllClass { - - public void noAnnotation() { - - } - - @AnonymousAllowed - public void anonymousAllowed() { - - } - - @PermitAll - public void permitAll() { - - } - - @DenyAll - public void denyAll() { - - } - - @RolesAllowed("user") - public void rolesAllowedUser() { - - } - - @RolesAllowed("admin") - public void rolesAllowedAdmin() { - - } - - @RolesAllowed({ "user", "admin" }) - public void rolesAllowedUserAdmin() { - } - - } - - @RolesAllowed("user") - public static class RolesAllowedUserClass { - - public void noAnnotation() { - - } - - @AnonymousAllowed - public void anonymousAllowed() { - - } - - @PermitAll - public void permitAll() { - - } - - @DenyAll - public void denyAll() { - - } - - @RolesAllowed("user") - public void rolesAllowedUser() { - - } - - @RolesAllowed("admin") - public void rolesAllowedAdmin() { - - } - - @RolesAllowed({ "user", "admin" }) - public void rolesAllowedUserAdmin() { - } - - } - - @RolesAllowed("admin") - public static class RolesAllowedAdminClass { - - public void noAnnotation() { - - } - - @AnonymousAllowed - public void anonymousAllowed() { - - } - - @PermitAll - public void permitAll() { - - } - - @DenyAll - public void denyAll() { - - } - - @RolesAllowed("user") - public void rolesAllowedUser() { - - } - - @RolesAllowed("admin") - public void rolesAllowedAdmin() { - - } - - @RolesAllowed({ "user", "admin" }) - public void rolesAllowedUserAdmin() { - } - - } - - @Route("login") - public static class TestLoginView extends Component { - - } - - @Route("noannotation") - public static class NoAnnotationView extends Component { - - } - - @AnonymousAllowed - @Route("anon") - public static class AnonymousAllowedView extends Component { - } - - @PermitAll - @Route("permitall") - public static class PermitAllView extends Component { - } - - @DenyAll - @Route("denyall") - public static class DenyAllView extends Component { - } - - @RolesAllowed("user") - @Route("user") - public static class RolesAllowedUserView extends Component { - } - - @RolesAllowed("admin") - @Route("admin") - public static class RolesAllowedAdminView extends Component { - } - - @AnonymousAllowed - public static class AnonymousAllowedParentView extends Component { - } - - @Route("no-annotation-anonymous-by-parent") - public static class NoAnnotationAnonymousAllowedByParentView - extends AnonymousAllowedParentView { - } - - @Route("no-annotation-anonymous-by-grandparent") - public static class NoAnnotationAnonymousAllowedByGrandParentView - extends NoAnnotationAnonymousAllowedByParentView { - } - - @PermitAll - public static class PermitAllGrandParentView { - } - - public static class PermitAllParentView extends PermitAllGrandParentView { - } - - @Route("no-annotation-permitall-by-grandparent") - public static class NoAnnotationPermitAllByGrandParentView - extends PermitAllParentView { - } - - @RolesAllowed("user") - public static class RolesAllowedUserGrandParentView { - } - - public static class RolesAllowedUserParentView - extends RolesAllowedUserGrandParentView { - } - - @Route("no-annotation-roles-allowed-user-by-grandparent") - public static class NoAnnotationRolesAllowedUserByGrandParentView - extends RolesAllowedUserParentView { - } - - @RolesAllowed("admin") - public static class RolesAllowedAdminGrandParentView { - } - - public static class RolesAllowedAdminParentView - extends RolesAllowedAdminGrandParentView { - } - - @Route("no-annotation-roles-allowed-admin-by-grandparent") - public static class NoAnnotationRolesAllowedAdminByGrandParentView - extends RolesAllowedAdminParentView { - } - - @DenyAll - public static class DenyAllGrandParentView { - } - - public static class DenyAllParentView extends DenyAllGrandParentView { - } - - @Route("no-annotation-denyall-by-grandparent") - public static class NoAnnotationDenyAllByGrandParentView - extends DenyAllParentView { - } - - @AnonymousAllowed - public interface CustomComponent { - } - - @Route("no-annotation-denyall-as-interfaces-ignored") - public static class NoAnnotationDenyAllAsInterfacesIgnoredView - implements CustomComponent { - } - - @Route("no-annotation-permitall-from-parent-and-interfaces-ignored") - public static class NoAnnotationPermitAllByGrandParentAsInterfacesIgnoredView - extends PermitAllParentView implements CustomComponent { - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/auth/ViewAccessCheckerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/auth/ViewAccessCheckerTest.java deleted file mode 100644 index be537fe4f35..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/auth/ViewAccessCheckerTest.java +++ /dev/null @@ -1,752 +0,0 @@ -package com.vaadin.flow.server.auth; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; -import java.lang.reflect.Field; -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.component.page.Page; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.AnnotationReader; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.Location; -import com.vaadin.flow.router.NavigationEvent; -import com.vaadin.flow.router.NavigationTrigger; -import com.vaadin.flow.router.NotFoundException; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteNotFoundError; -import com.vaadin.flow.router.Router; -import com.vaadin.flow.router.internal.ErrorStateRenderer; -import com.vaadin.flow.router.internal.ErrorTargetEntry; -import com.vaadin.flow.router.internal.RouteUtil; -import com.vaadin.flow.server.RouteRegistry; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.auth.AccessControlTestClasses.AnonymousAllowedView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.DenyAllView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationAnonymousAllowedByGrandParentView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationAnonymousAllowedByParentView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationDenyAllAsInterfacesIgnoredView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationDenyAllByGrandParentView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationPermitAllByGrandParentAsInterfacesIgnoredView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationPermitAllByGrandParentView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationRolesAllowedAdminByGrandParentView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationRolesAllowedUserByGrandParentView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.NoAnnotationView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.PermitAllView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.RolesAllowedAdminView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.RolesAllowedUserView; -import com.vaadin.flow.server.auth.AccessControlTestClasses.TestLoginView; - -public class ViewAccessCheckerTest { - - private enum User { - USER_NO_ROLES, NORMAL_USER, ADMIN - } - - private ViewAccessChecker viewAccessChecker; - - @Before - public void init() { - this.viewAccessChecker = new ViewAccessChecker(); - this.viewAccessChecker.setLoginView(TestLoginView.class); - } - - @Test - public void anonymousAccessToAnonymousViewAllowed() { - Result result = checkAccess(AnonymousAllowedView.class, null); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccessToNoAnnotationViewDenied() { - Result result = checkAccess(NoAnnotationView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccessToPermitAllViewDenied() { - Result result = checkAccess(PermitAllView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccessToDenyAllViewDenied() { - Result result = checkAccess(DenyAllView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccessToRolesAllowedUserViewDenied() { - Result result = checkAccess(RolesAllowedUserView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccessToRolesAllowedAdminViewDenied() { - Result result = checkAccess(RolesAllowedAdminView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccessToAnonymousViewAllowed() { - Result result = checkAccess(AnonymousAllowedView.class, - User.USER_NO_ROLES); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccessToNoAnnotationViewDenied() { - Result result = checkAccess(NoAnnotationView.class, User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccessToPermitAllViewAllowed() { - Result result = checkAccess(PermitAllView.class, User.USER_NO_ROLES); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccessToDenyAllViewDenied() { - Result result = checkAccess(DenyAllView.class, User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccessToRolesAllowedUserViewDenied() { - Result result = checkAccess(RolesAllowedUserView.class, - User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccessToRolesAllowedAdminViewDenied() { - Result result = checkAccess(RolesAllowedAdminView.class, - User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccessToAnonymousViewAllowed() { - Result result = checkAccess(AnonymousAllowedView.class, - User.NORMAL_USER); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccessToNoAnnotationViewDenied() { - Result result = checkAccess(NoAnnotationView.class, User.NORMAL_USER); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccessToPermitAllViewAllowed() { - Result result = checkAccess(PermitAllView.class, User.NORMAL_USER); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccessToDenyAllViewDenied() { - Result result = checkAccess(DenyAllView.class, User.NORMAL_USER); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccessToRolesAllowedUserViewAllowed() { - Result result = checkAccess(RolesAllowedUserView.class, - User.NORMAL_USER); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccessToRolesAllowedAdminViewDenied() { - Result result = checkAccess(RolesAllowedAdminView.class, - User.NORMAL_USER); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccessToAnonymousViewAllowed() { - Result result = checkAccess(AnonymousAllowedView.class, User.ADMIN); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccessToNoAnnotationViewDenied() { - Result result = checkAccess(NoAnnotationView.class, User.ADMIN); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccessToPermitAllViewAllowed() { - Result result = checkAccess(PermitAllView.class, User.ADMIN); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccessToDenyAllViewDenied() { - Result result = checkAccess(DenyAllView.class, User.ADMIN); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccessToRolesAllowedUserViewDenied() { - Result result = checkAccess(RolesAllowedUserView.class, User.ADMIN); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccessToRolesAllowedAdminViewAllowed() { - Result result = checkAccess(RolesAllowedAdminView.class, User.ADMIN); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loginViewAccessAlwaysAllowed() { - Assert.assertTrue( - checkAccess(TestLoginView.class, null).wasTargetViewRendered()); - Assert.assertTrue(checkAccess(TestLoginView.class, User.NORMAL_USER) - .wasTargetViewRendered()); - Assert.assertTrue(checkAccess(TestLoginView.class, User.USER_NO_ROLES) - .wasTargetViewRendered()); - Assert.assertTrue(checkAccess(TestLoginView.class, User.ADMIN) - .wasTargetViewRendered()); - } - - @Test - public void redirectUrlStoredForAnonymousUsers() { - Result result = checkAccess(RolesAllowedAdminView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - Assert.assertEquals( - AccessAnnotationCheckerTest.REQUEST_URL - + getRoute(RolesAllowedAdminView.class), - result.sessionAttributes.get( - ViewAccessChecker.SESSION_STORED_REDIRECT_ABSOLUTE)); - Assert.assertEquals(getRoute(RolesAllowedAdminView.class), - result.sessionAttributes - .get(ViewAccessChecker.SESSION_STORED_REDIRECT)); - } - - @Test - public void redirectUrlNotStoredForLoggedInUsers() { - Result result = checkAccess(RolesAllowedAdminView.class, - User.NORMAL_USER); - Assert.assertFalse(result.wasTargetViewRendered()); - Assert.assertNull(result.sessionAttributes - .get(ViewAccessChecker.SESSION_STORED_REDIRECT)); - Assert.assertNull(result.sessionAttributes - .get(ViewAccessChecker.SESSION_STORED_REDIRECT_ABSOLUTE)); - } - - @Test - public void disabledAccessCheckerAlwaysPasses_rejectsWhenEnabled() { - viewAccessChecker = new ViewAccessChecker(false); - Assert.assertTrue( - "Expected admin view to be accessible for non " - + "authenticated users when access checker is disabled", - checkAccess(RolesAllowedAdminView.class, null) - .wasTargetViewRendered()); - viewAccessChecker.enable(); - Assert.assertFalse( - "Expected admin view to be not accessible for non " - + "authenticated users when access checker is enabled", - checkAccess(RolesAllowedAdminView.class, null) - .wasTargetViewRendered()); - } - - @Test(expected = IllegalStateException.class) - public void setLoginViewStringCannotBeCalledAfterSettingClass() - throws Exception { - resetLoginView(); - this.viewAccessChecker.setLoginView(TestLoginView.class); - this.viewAccessChecker.setLoginView("/foo"); - } - - @Test(expected = IllegalStateException.class) - public void setLoginViewClassCannotBeCalledAfterSettingClass() - throws Exception { - resetLoginView(); - this.viewAccessChecker.setLoginView(TestLoginView.class); - this.viewAccessChecker.setLoginView(TestLoginView.class); - } - - @Test(expected = IllegalStateException.class) - public void setLoginViewStringCannotBeCalledAfterSettingString() - throws Exception { - resetLoginView(); - this.viewAccessChecker.setLoginView("/foo"); - this.viewAccessChecker.setLoginView("/foo"); - } - - @Test(expected = IllegalStateException.class) - public void setLoginViewClassCannotBeCalledAfterSettingString() - throws Exception { - resetLoginView(); - this.viewAccessChecker.setLoginView("/foo"); - this.viewAccessChecker.setLoginView(TestLoginView.class); - } - - @Test - public void openingRestrictedViewRedirectsAnonymousUserToLogin() { - Result result = checkAccess(RolesAllowedAdminView.class, null); - Assert.assertEquals(TestLoginView.class, result.getForwardedTo()); - } - - @Test - public void openingRestrictedViewRedirectsAnonymousUserToLogin_whenUsingLoginPath() - throws Exception { - resetLoginView(); - viewAccessChecker.setLoginView("/log-in"); - Result result = checkAccess(RolesAllowedAdminView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - Assert.assertEquals("/log-in", result.getExternalForwardUrl()); - } - - @Test - public void openingRestrictedViewShowsNotFoundForLoggedInUser() { - Result result = checkAccess(RolesAllowedAdminView.class, - User.NORMAL_USER); - Assert.assertEquals(NotFoundException.class, result.getRerouteError()); - Assert.assertEquals("", result.getRerouteErrorMessage()); - } - - @Test - public void openingRestrictedViewShowsReasonInDevelopmentMode() { - Result result = checkAccess(RolesAllowedAdminView.class, - User.NORMAL_USER, false); - Assert.assertEquals(NotFoundException.class, result.getRerouteError()); - Assert.assertEquals("Access denied", result.getRerouteErrorMessage()); - } - - @Test - public void openingNoAnnotationViewShowsReasonAndHintInDevelopmentMode() { - Result result = checkAccess(NoAnnotationView.class, User.NORMAL_USER, - false); - Assert.assertEquals(NotFoundException.class, result.getRerouteError()); - Assert.assertEquals( - "Access denied. Consider adding one of the following annotations " - + "to make the view accessible: @AnonymousAllowed, " - + "@PermitAll, @RolesAllowed.", - result.getRerouteErrorMessage()); - } - - @Test - public void openingNoAnnotationViewDoesNotShowAnyReasonAndHintInProductionMode() { - Result result = checkAccess(NoAnnotationView.class, User.NORMAL_USER, - true); - Assert.assertEquals(NotFoundException.class, result.getRerouteError()); - Assert.assertEquals("", result.getRerouteErrorMessage()); - } - - @Test - public void redirectWhenNoLoginSet() throws Exception { - resetLoginView(); - Result result = checkAccess(RolesAllowedAdminView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - Assert.assertEquals(NotFoundException.class, result.getRerouteError()); - } - - @Test - public void anonymousAccess_to_noAnnotationAnonymousAllowedByParent_allowed() { - Result result = checkAccess( - NoAnnotationAnonymousAllowedByParentView.class, null); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccess_to_noAnnotationAnonymousAllowedByGrandParent_allowed() { - Result result = checkAccess( - NoAnnotationAnonymousAllowedByGrandParentView.class, null); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccess_to_noAnnotationPermitAllByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationPermitAllByGrandParentView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccess_to_noAnnotationDenyAllByGrandParentView_denied() { - Result result = checkAccess(NoAnnotationDenyAllByGrandParentView.class, - null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccess_to_noAnnotationRolesAllowedUserByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationRolesAllowedUserByGrandParentView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void anonymousAccess_to_noAnnotationRolesAllowedAdminByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationRolesAllowedAdminByGrandParentView.class, null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccess_to_noAnnotationAnonymousAllowedByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationAnonymousAllowedByGrandParentView.class, - User.USER_NO_ROLES); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccess_to_noAnnotationPermitAllByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationPermitAllByGrandParentView.class, - User.USER_NO_ROLES); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccess_to_noAnnotationDenyAllByGrandParentView_denied() { - Result result = checkAccess(NoAnnotationDenyAllByGrandParentView.class, - User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccess_to_noAnnotationRolesAllowedUserByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationRolesAllowedUserByGrandParentView.class, - User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccess_to_noAnnotationRolesAllowedAdminByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationRolesAllowedAdminByGrandParentView.class, - User.USER_NO_ROLES); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccess_to_noAnnotationAnonymousAllowedByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationAnonymousAllowedByGrandParentView.class, - User.NORMAL_USER); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccess_to_noAnnotationPermitAllByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationPermitAllByGrandParentView.class, User.NORMAL_USER); - Assert.assertTrue("Target view should have been rendered", - result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccess_to_noAnnotationDenyAllByGrandParentView_denied() { - Result result = checkAccess(NoAnnotationDenyAllByGrandParentView.class, - User.NORMAL_USER); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccess_to_noAnnotationRolesAllowedUserByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationRolesAllowedUserByGrandParentView.class, - User.NORMAL_USER); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInUserRoleAccess_to_noAnnotationRolesAllowedAdminByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationRolesAllowedAdminByGrandParentView.class, - User.NORMAL_USER); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccess_to_noAnnotationAnonymousAllowedByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationAnonymousAllowedByGrandParentView.class, - User.ADMIN); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccess_to_noAnnotationPermitAllByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationPermitAllByGrandParentView.class, User.ADMIN); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccess_to_noAnnotationDenyAllByGrandParentView_denied() { - Result result = checkAccess(NoAnnotationDenyAllByGrandParentView.class, - User.ADMIN); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccess_to_noAnnotationRolesAllowedUserByGrandParentView_denied() { - Result result = checkAccess( - NoAnnotationRolesAllowedUserByGrandParentView.class, - User.ADMIN); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInAdminRoleAccess_To_noAnnotationRolesAllowedAdminByGrandParentView_allowed() { - Result result = checkAccess( - NoAnnotationRolesAllowedAdminByGrandParentView.class, - User.ADMIN); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - @Test - public void anyAccess_to_noAnnotationDenyAllAsInterfacesIgnoredView_denied() { - Assert.assertFalse( - checkAccess(NoAnnotationDenyAllAsInterfacesIgnoredView.class, - null).wasTargetViewRendered()); - - Assert.assertFalse( - checkAccess(NoAnnotationDenyAllAsInterfacesIgnoredView.class, - User.USER_NO_ROLES).wasTargetViewRendered()); - - Assert.assertFalse( - checkAccess(NoAnnotationDenyAllAsInterfacesIgnoredView.class, - User.NORMAL_USER).wasTargetViewRendered()); - - Assert.assertFalse( - checkAccess(NoAnnotationDenyAllAsInterfacesIgnoredView.class, - User.ADMIN).wasTargetViewRendered()); - } - - @Test - public void anonymousAccess_to_noAnnotationPermitAllByGrandParentAsInterfacesIgnoredView_denied() { - Result result = checkAccess( - NoAnnotationPermitAllByGrandParentAsInterfacesIgnoredView.class, - null); - Assert.assertFalse(result.wasTargetViewRendered()); - } - - @Test - public void loggedInNoRolesAccess_to_noAnnotationPermitAllByGrandParentAsInterfacesIgnoredView_allowed() { - Result result = checkAccess( - NoAnnotationPermitAllByGrandParentAsInterfacesIgnoredView.class, - User.USER_NO_ROLES); - Assert.assertTrue(result.wasTargetViewRendered()); - } - - private void resetLoginView() - throws NoSuchFieldException, IllegalAccessException { - Field f = ViewAccessChecker.class.getDeclaredField("loginView"); - f.setAccessible(true); - f.set(this.viewAccessChecker, null); - } - - private static class Result { - - public BeforeEnterEvent event; - public Map sessionAttributes; - - public Class getReroutedTo() { - if (!event.hasRerouteTarget() - || event.getRerouteTarget() instanceof ErrorStateRenderer) { - return null; - } - return event.getRerouteTargetType(); - } - - public Class getForwardedTo() { - if (!event.hasForwardTarget()) { - return null; - } - return event.getForwardTargetType(); - } - - public String getRerouteErrorMessage() { - if (!event.hasRerouteTarget() || !(event - .getRerouteTarget() instanceof ErrorStateRenderer)) { - return null; - } - - return event.getErrorParameter().getCustomMessage(); - } - - public Class getRerouteError() { - if (!event.hasRerouteTarget() || !(event - .getRerouteTarget() instanceof ErrorStateRenderer)) { - return null; - } - - return event.getErrorParameter().getException().getClass(); - } - - public String getRerouteURL() { - if (event.hasUnknownForward()) { - return event.getUnknownForward(); - } else { - return null; - } - } - - public String getExternalForwardUrl() { - if (event.hasExternalForwardUrl()) { - return event.getExternalForwardUrl(); - } else { - return null; - } - } - - public boolean wasTargetViewRendered() { - return getReroutedTo() == null && getForwardedTo() == null - && getRerouteError() == null && getRerouteURL() == null - && getExternalForwardUrl() == null; - } - - } - - private Result checkAccess(Class viewClass, User user) { - return checkAccess(viewClass, user, true); - } - - private Result checkAccess(Class viewClass, User user, - boolean productionMode) { - Result result = setupRequest(viewClass, user, productionMode); - BeforeEnterEvent event = result.event; - - this.viewAccessChecker.beforeEnter(event); - return result; - } - - private Result setupRequest(Class navigationTarget, User user, - boolean productionMode) { - CurrentInstance.clearAll(); - - Principal principal; - String[] roles; - - if (user == User.USER_NO_ROLES) { - principal = AccessAnnotationCheckerTest.USER_PRINCIPAL; - roles = new String[0]; - } else if (user == User.NORMAL_USER) { - principal = AccessAnnotationCheckerTest.USER_PRINCIPAL; - roles = new String[] { "user" }; - } else if (user == User.ADMIN) { - principal = AccessAnnotationCheckerTest.USER_PRINCIPAL; - roles = new String[] { "admin" }; - } else { - principal = null; - roles = new String[0]; - } - - VaadinServletRequest vaadinServletRequest = Mockito - .mock(VaadinServletRequest.class); - HttpServletRequest httpServletRequest = AccessAnnotationCheckerTest - .createRequest(principal, roles); - Mockito.when(vaadinServletRequest.getHttpServletRequest()) - .thenReturn(httpServletRequest); - Mockito.when(vaadinServletRequest.getUserPrincipal()) - .thenAnswer(answer -> httpServletRequest.getUserPrincipal()); - Mockito.when(vaadinServletRequest.getSession()) - .thenAnswer(answer -> httpServletRequest.getSession()); - Mockito.when(vaadinServletRequest.isUserInRole(Mockito.any())) - .thenAnswer(answer -> httpServletRequest - .isUserInRole(answer.getArgument(0))); - Mockito.when(vaadinServletRequest.getRequestURL()).thenReturn( - new StringBuffer(AccessAnnotationCheckerTest.REQUEST_URL)); - - CurrentInstance.set(VaadinRequest.class, vaadinServletRequest); - - Router router = Mockito.mock(Router.class); - UI ui = Mockito.mock(UI.class); - Page page = Mockito.mock(Page.class); - Mockito.when(ui.getPage()).thenReturn(page); - VaadinSession vaadinSession = Mockito.mock(VaadinSession.class); - Mockito.when(ui.getSession()).thenReturn(vaadinSession); - DeploymentConfiguration configuration = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(vaadinSession.getConfiguration()) - .thenReturn(configuration); - Mockito.when(configuration.isProductionMode()) - .thenReturn(productionMode); - - UIInternals uiInternals = Mockito.mock(UIInternals.class); - Mockito.when(ui.getInternals()).thenReturn(uiInternals); - Mockito.when(uiInternals.getRouter()).thenReturn(router); - - Mockito.when(router.getErrorNavigationTarget(Mockito.any())) - .thenAnswer(invocation -> { - Class exceptionClass = invocation.getArguments()[0] - .getClass(); - if (exceptionClass == NotFoundException.class) { - return Optional.of( - new ErrorTargetEntry(RouteNotFoundError.class, - NotFoundException.class)); - } else { - return Optional.empty(); - } - - }); - Location location = new Location(getRoute(navigationTarget)); - NavigationEvent navigationEvent = new NavigationEvent(router, location, - ui, NavigationTrigger.ROUTER_LINK); - BeforeEnterEvent event = new BeforeEnterEvent(navigationEvent, - navigationTarget, new ArrayList<>()); - - RouteRegistry routeRegistry = Mockito.mock(RouteRegistry.class); - Mockito.when(router.getRegistry()).thenReturn(routeRegistry); - Mockito.when(routeRegistry.getNavigationTarget(Mockito.anyString())) - .thenAnswer(invocation -> { - String url = (String) invocation.getArguments()[0]; - if (location.getPath().equals(url)) { - return Optional.of(navigationTarget); - } else { - return Optional.empty(); - } - }); - - HttpSession session = Mockito.mock(HttpSession.class); - Map sessionAttributes = new HashMap<>(); - Mockito.when(httpServletRequest.getSession()).thenReturn(session); - Mockito.doAnswer(invocation -> { - String key = (String) invocation.getArguments()[0]; - Object value = invocation.getArguments()[1]; - - sessionAttributes.put(key, value); - - return null; - }).when(session).setAttribute(Mockito.anyString(), Mockito.any()); - - Result info = new Result(); - info.event = event; - info.sessionAttributes = sessionAttributes; - - return info; - } - - private String getRoute(Class navigationTarget) { - Optional route = AnnotationReader - .getAnnotationFor(navigationTarget, Route.class); - - return RouteUtil.getRoutePath(navigationTarget, route.get()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/AtmospherePushConnectionTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/AtmospherePushConnectionTest.java deleted file mode 100644 index 50a68018636..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/AtmospherePushConnectionTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.server.communication.AtmospherePushConnection.State; - -import org.atmosphere.cpr.AtmosphereResource; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -/** - * @author Vaadin Ltd - * @since 1.0 - */ -public class AtmospherePushConnectionTest { - @Test - public void testSerialization() throws Exception { - - UI ui = Mockito.mock(UI.class); - AtmosphereResource resource = Mockito.mock(AtmosphereResource.class); - - AtmospherePushConnection connection = new AtmospherePushConnection(ui); - connection.connect(resource); - - Assert.assertEquals(State.CONNECTED, connection.getState()); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - new ObjectOutputStream(baos).writeObject(connection); - - connection = (AtmospherePushConnection) new ObjectInputStream( - new ByteArrayInputStream(baos.toByteArray())).readObject(); - - Assert.assertEquals(State.DISCONNECTED, connection.getState()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/CommunicationUtil.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/CommunicationUtil.java deleted file mode 100644 index 33925be1874..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/CommunicationUtil.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.communication; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.mockito.internal.verification.VerificationModeFactory; - -class CommunicationUtil { - - static String getStringWhenWriteBytesOffsetLength(OutputStream outputStream) - throws IOException { - ArgumentCaptor contentArg = ArgumentCaptor - .forClass(byte[].class); - ArgumentCaptor offsetArg = ArgumentCaptor.forClass(int.class); - ArgumentCaptor lengthArg = ArgumentCaptor.forClass(int.class); - - Mockito.verify(outputStream, VerificationModeFactory.atLeastOnce()) - .write(contentArg.capture(), offsetArg.capture(), - lengthArg.capture()); - - List offsetValues = offsetArg.getAllValues(); - List lengthValues = lengthArg.getAllValues(); - - AtomicInteger i = new AtomicInteger(); - - return contentArg.getAllValues().stream().map(bytes -> { - return new String(bytes, offsetValues.get(i.get()), - lengthValues.get(i.getAndIncrement())); - }).collect(Collectors.joining()); - } - - static String getStringWhenWriteString(OutputStream outputStream) - throws IOException { - ArgumentCaptor contentArg = ArgumentCaptor - .forClass(byte[].class); - - Mockito.verify(outputStream, VerificationModeFactory.atLeastOnce()) - .write(contentArg.capture()); - - return contentArg.getAllValues().stream() - .map(bytes -> new String(bytes)).collect(Collectors.joining()); - } - - static String getStringWhenWriteString(PrintWriter printWriter) { - ArgumentCaptor contentArg = ArgumentCaptor - .forClass(String.class); - - Mockito.verify(printWriter, VerificationModeFactory.atLeastOnce()) - .write(contentArg.capture()); - - return String.join("", contentArg.getAllValues()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/HeartbeatHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/HeartbeatHandlerTest.java deleted file mode 100644 index 1498b8f45a7..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/HeartbeatHandlerTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.IOException; - -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; - -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.when; - -public class HeartbeatHandlerTest { - - @Test - public void synchronizedHandleRequest_uiPresent_setLastHeartbeatTimestampIsCalledOnce() - throws IOException { - VaadinService service = mock(VaadinService.class); - VaadinSession session = mock(VaadinSession.class); - VaadinRequest request = mock(VaadinRequest.class); - VaadinResponse response = mock(VaadinResponse.class); - UI ui = mock(UI.class); - UIInternals uiInternals = mock(UIInternals.class); - - when(ui.getInternals()).thenReturn(uiInternals); - when(session.getService()).thenReturn(service); - when(service.findUI(request)).thenReturn(ui); - - HeartbeatHandler handler = new HeartbeatHandler(); - handler.synchronizedHandleRequest(session, request, response); - - Mockito.verify(ui.getInternals(), times(1)) - .setLastHeartbeatTimestamp(anyLong()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java deleted file mode 100644 index 1959c0507ed..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java +++ /dev/null @@ -1,983 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import jakarta.servlet.http.HttpServletRequest; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -import org.jsoup.Jsoup; -import org.jsoup.internal.StringUtil; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.JavaScriptBootstrapUI; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.internal.DevModeHandler; -import com.vaadin.flow.internal.DevModeHandlerManager; -import com.vaadin.flow.internal.UsageStatistics; -import com.vaadin.flow.server.AppShellRegistry; -import com.vaadin.flow.server.BootstrapHandler; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.flow.server.startup.VaadinAppShellInitializerTest.AppShellWithPWA; -import com.vaadin.flow.server.startup.VaadinAppShellInitializerTest.MyAppShellWithConfigurator; -import com.vaadin.flow.server.startup.VaadinAppShellInitializerTest.MyAppShellWithLoadingIndicatorConfig; -import com.vaadin.flow.server.startup.VaadinAppShellInitializerTest.MyAppShellWithPushConfig; -import com.vaadin.flow.server.startup.VaadinAppShellInitializerTest.MyAppShellWithReconnectionDialogConfig; -import com.vaadin.flow.server.startup.VaadinInitializerException; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import elemental.json.Json; -import elemental.json.JsonObject; -import static com.vaadin.flow.component.internal.JavaScriptBootstrapUI.SERVER_ROUTING; -import static com.vaadin.flow.server.Constants.VAADIN_WEBAPP_RESOURCES; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.INDEX_HTML; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class IndexHtmlRequestHandlerTest { - private static final String SPRING_CSRF_ATTRIBUTE_IN_SESSION = "org.springframework.security.web.csrf.CsrfToken"; - private static final String SPRING_CSRF_ATTRIBUTE = "_csrf"; - private MockServletServiceSessionSetup mocks; - private MockServletServiceSessionSetup.TestVaadinServletService service; - private VaadinSession session; - private IndexHtmlRequestHandler indexHtmlRequestHandler; - private VaadinResponse response; - private ByteArrayOutputStream responseOutput; - private MockDeploymentConfiguration deploymentConfiguration; - private VaadinContext context; - - private String springTokenString; - private String springTokenHeaderName = "x-CSRF-TOKEN"; - private String springTokenParamName = SPRING_CSRF_ATTRIBUTE_IN_SESSION; - - private int expectedScriptsTagsOnBootstrapPage = 4; - - @Before - public void setUp() throws Exception { - mocks = new MockServletServiceSessionSetup(); - service = mocks.getService(); - session = mocks.getSession(); - response = Mockito.mock(VaadinResponse.class); - responseOutput = new ByteArrayOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(responseOutput); - deploymentConfiguration = mocks.getDeploymentConfiguration(); - deploymentConfiguration.setEnableDevServer(false); - indexHtmlRequestHandler = new IndexHtmlRequestHandler(); - context = Mockito.mock(VaadinContext.class); - springTokenString = UUID.randomUUID().toString(); - } - - @Test - public void serveIndexHtml_requestWithRootPath_serveContentFromTemplate() - throws IOException { - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Assert.assertTrue( - "Response should have content from the index.html template", - indexHtml.contains("index.html template content")); - Assert.assertTrue( - "Response should have styles for the system-error dialogs", - indexHtml.contains(".v-system-error")); - } - - @Test - public void serveNotFoundIndexHtml_requestWithRootPath_failsWithIOException() - throws IOException { - VaadinServletService vaadinService = Mockito - .mock(VaadinServletService.class); - Mockito.when(vaadinService.getDeploymentConfiguration()) - .thenReturn(deploymentConfiguration); - - Mockito.when(vaadinService.getContext()).thenReturn(context); - final Lookup lookup = Mockito.mock(Lookup.class); - ResourceProvider resourceProvider = Mockito - .mock(ResourceProvider.class); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(lookup); - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(resourceProvider); - URL resource = Mockito.mock(URL.class); - Mockito.when(resourceProvider - .getApplicationResource(VAADIN_WEBAPP_RESOURCES + INDEX_HTML)) - .thenReturn(resource); - when(resource.openStream()).thenReturn(null); - - VaadinServletRequest vaadinRequest = Mockito - .mock(VaadinServletRequest.class); - Mockito.when(vaadinRequest.getService()).thenReturn(vaadinService); - - String path = DEFAULT_FRONTEND_DIR + "index.html"; - - String expectedError = String - .format("Failed to load content of '%1$s'. " - + "It is required to have '%1$s' file when " - + "using client side bootstrapping.", path); - - IOException expectedException = assertThrows(IOException.class, - () -> indexHtmlRequestHandler.synchronizedHandleRequest(session, - vaadinRequest, response)); - Assert.assertEquals(expectedError, expectedException.getMessage()); - } - - @Test - public void serveIndexHtml_requestWithRootPath_hasBaseHrefElement() - throws IOException { - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Assert.assertTrue("Response should have correct base href", - indexHtml.contains(" { - // refuse any request with extension - return !req.getPathInfo().matches(".+\\.[A-z][A-z\\d]+$"); - }); - - Assert.assertTrue( - "The handler should handle a route with " + "parameter", - indexHtmlRequestHandler - .canHandleRequest(createVaadinRequest("/some/route"))); - Assert.assertTrue("The handler should handle a normal route", - indexHtmlRequestHandler - .canHandleRequest(createVaadinRequest("/myroute"))); - Assert.assertTrue("The handler should handle a directory request", - indexHtmlRequestHandler.canHandleRequest( - createVaadinRequest("/myroute/ends/withslash/"))); - Assert.assertTrue( - "The handler should handle a request if it has " - + "extension pattern in the middle of the path", - indexHtmlRequestHandler.canHandleRequest( - createVaadinRequest("/documentation/10.0.x1/flow"))); - - Assert.assertFalse( - "The handler should not handle request with extension", - indexHtmlRequestHandler.canHandleRequest( - createVaadinRequest("/nested/picture.png"))); - Assert.assertFalse( - "The handler should not handle request with capital extension", - indexHtmlRequestHandler.canHandleRequest( - createVaadinRequest("/nested/CAPITAL.PNG"))); - Assert.assertFalse( - "The handler should not handle request with extension", - indexHtmlRequestHandler - .canHandleRequest(createVaadinRequest("/script.js"))); - - Assert.assertFalse( - "The handler should not handle request with extension", - indexHtmlRequestHandler - .canHandleRequest(createVaadinRequest("/music.mp3"))); - Assert.assertFalse( - "The handler should not handle request with only extension", - indexHtmlRequestHandler - .canHandleRequest(createVaadinRequest("/.htaccess"))); - } - - @Test - public void canHandleRequest_allow_oldBrowser() { - Assert.assertTrue(indexHtmlRequestHandler.canHandleRequest( - createRequestWithDestination("/", null, null))); - } - - @Test - public void canHandleRequest_handle_indexHtmlRequest() { - Assert.assertTrue(indexHtmlRequestHandler.canHandleRequest( - createRequestWithDestination("/", "document", "navigate"))); - } - - @Test - public void canHandleRequest_doNotHandle_scriptRequest() { - Assert.assertFalse(indexHtmlRequestHandler.canHandleRequest( - createRequestWithDestination("/", "script", "no-cors"))); - } - - @Test - public void canHandleRequest_doNotHandle_imageRequest() { - Assert.assertFalse(indexHtmlRequestHandler.canHandleRequest( - createRequestWithDestination("/", "image", "no-cors"))); - } - - @Test - public void canHandleRequest_doNotHandle_vaadinStaticResources() { - Assert.assertFalse(indexHtmlRequestHandler.canHandleRequest( - createRequestWithDestination("/VAADIN/foo.js", null, null))); - } - - @Test - public void canHandleRequest_handle_serviceWorkerDocumentRequest() { - Assert.assertTrue(indexHtmlRequestHandler.canHandleRequest( - createRequestWithDestination("/", "empty", "same-origin"))); - } - - @Test - public void bootstrapListener_addListener_responseIsModified() - throws IOException { - service.addIndexHtmlRequestListener(evt -> evt.getDocument().head() - .getElementsByTag("script").remove()); - service.addIndexHtmlRequestListener(evt -> { - evt.getDocument().head().appendElement("script").attr("src", - "testing.1"); - }); - service.addIndexHtmlRequestListener(evt -> evt.getDocument().head() - .appendElement("script").attr("src", "testing.2")); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - Elements scripts = document.head().getElementsByTag("script"); - int expectedScripts = 4; - Assert.assertEquals(expectedScripts, scripts.size()); - Assert.assertEquals("testing.1", - scripts.get(expectedScripts - 2).attr("src")); - Assert.assertEquals("testing.2", - scripts.get(expectedScripts - 1).attr("src")); - } - - @Test - public void should_add_initialUidl_when_includeInitialBootstrapUidl() - throws IOException { - deploymentConfiguration.setEagerServerLoad(true); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements scripts = document.head().getElementsByTag("script"); - Assert.assertEquals(expectedScriptsTagsOnBootstrapPage, scripts.size()); - Element initialUidlScript = scripts - .get(expectedScriptsTagsOnBootstrapPage - 2); - Assert.assertEquals("", initialUidlScript.attr("initial")); - Assert.assertTrue( - initialUidlScript.toString().contains("Could not navigate")); - - Mockito.verify(session, Mockito.times(1)).setAttribute(SERVER_ROUTING, - Boolean.TRUE); - } - - @Test - public void should_not_add_initialUidl_when_not_includeInitialBootstrapUidl() - throws IOException { - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements scripts = document.head().getElementsByTag("script"); - Assert.assertEquals(expectedScriptsTagsOnBootstrapPage, scripts.size()); - Element initialUidlScript = scripts - .get(expectedScriptsTagsOnBootstrapPage - 2); - - Assert.assertEquals( - "window.Vaadin = window.Vaadin || {};window.Vaadin.TypeScript= {};", - initialUidlScript.childNode(0).toString()); - Assert.assertEquals("", initialUidlScript.attr("initial")); - - Mockito.verify(session, Mockito.times(0)).setAttribute(SERVER_ROUTING, - Boolean.TRUE); - } - - @Test - public void should_initialize_UI_and_add_initialUidl_when_valid_route() - throws IOException { - deploymentConfiguration.setEagerServerLoad(true); - - service.setBootstrapInitialPredicate(request -> { - return request.getPathInfo().equals("/"); - }); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements scripts = document.head().getElementsByTag("script"); - Assert.assertEquals(expectedScriptsTagsOnBootstrapPage, scripts.size()); - Element initialUidlScript = scripts - .get(expectedScriptsTagsOnBootstrapPage - 2); - Assert.assertEquals("", initialUidlScript.attr("initial")); - String scriptContent = initialUidlScript.toString(); - Assert.assertTrue(scriptContent.contains("Could not navigate")); - Assert.assertFalse("Initial object content should not be escaped", - scriptContent.contains("<") - || scriptContent.contains(">")); - Assert.assertNotNull(UI.getCurrent()); - } - - @Test - public void should_not_initialize_UI_and_add_initialUidl_when_invalid_route() - throws IOException { - deploymentConfiguration.setEagerServerLoad(true); - - service.setBootstrapInitialPredicate(request -> { - return request.getPathInfo().equals("/"); - }); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/foo"), response); - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements scripts = document.head().getElementsByTag("script"); - Assert.assertEquals(expectedScriptsTagsOnBootstrapPage, scripts.size()); - Element initialUidlScript = scripts - .get(expectedScriptsTagsOnBootstrapPage - 2); - Assert.assertEquals( - "window.Vaadin = window.Vaadin || {};window.Vaadin.TypeScript= {};", - initialUidlScript.childNode(0).toString()); - Assert.assertEquals("", initialUidlScript.attr("initial")); - Assert.assertNull(UI.getCurrent()); - } - - @Test - public void should_getter_UI_return_not_empty_when_includeInitialBootstrapUidl() - throws IOException { - deploymentConfiguration.setEagerServerLoad(true); - - VaadinRequest request = createVaadinRequest("/"); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - - request, response); - - ArgumentCaptor captor = ArgumentCaptor - .forClass(IndexHtmlResponse.class); - - verify(request.getService()).modifyIndexHtmlResponse(captor.capture()); - - Assert.assertNotNull(captor.getValue().getUI()); - } - - @Test - public void should_getter_UI_return_empty_when_not_includeInitialBootstrapUidl() - throws IOException { - VaadinRequest request = createVaadinRequest("/"); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, request, - response); - - ArgumentCaptor captor = ArgumentCaptor - .forClass(IndexHtmlResponse.class); - - verify(request.getService()).modifyIndexHtmlResponse(captor.capture()); - - Assert.assertEquals(Optional.empty(), captor.getValue().getUI()); - } - - @Test - public void should_include_spring_csrf_token_in_meta_tags_when_return_not_null_spring_csrf_in_request() - throws IOException { - VaadinRequest request = createVaadinRequestWithSpringCsrfToken(); - indexHtmlRequestHandler.synchronizedHandleRequest(session, request, - response); - assertSpringCsrfTokenIsAvailableAsMetaTagsInDom(); - } - - @Test - public void should_not_include_token_in_dom_when_return_null_csrfToken_in_session() - throws IOException { - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements scripts = document.head().getElementsByTag("script"); - Assert.assertEquals(expectedScriptsTagsOnBootstrapPage, scripts.size()); - Element initialUidlScript = scripts - .get(expectedScriptsTagsOnBootstrapPage - 2); - Assert.assertFalse(initialUidlScript.childNode(0).toString() - .contains("window.Vaadin = {Flow: {\"csrfToken\":")); - Assert.assertEquals("", initialUidlScript.attr("initial")); - } - - @Test - public void should_not_include_spring_csrf_token_in_meta_tags_when_return_null_spring_csrf_in_request() - throws IOException { - VaadinRequest request = createVaadinRequest("/"); - indexHtmlRequestHandler.synchronizedHandleRequest(session, request, - response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Assert.assertEquals(0, document.head() - .getElementsByAttribute(SPRING_CSRF_ATTRIBUTE).size()); - Assert.assertEquals(0, - document.head().getElementsByAttribute("_csrf_header").size()); - } - - @Test - public void should_include_spring_token_in_dom_when_referer_is_service_worker() - throws IOException { - VaadinRequest request = createVaadinRequestWithSpringCsrfToken(); - Mockito.when(request.getHeader("referer")) - .thenReturn("http://somewhere.test/sw.js"); - indexHtmlRequestHandler.synchronizedHandleRequest(session, request, - response); - assertSpringCsrfTokenIsAvailableAsMetaTagsInDom(); - } - - @Test - public void should_use_client_routing_when_there_is_a_router_call() - throws IOException { - - deploymentConfiguration.setEagerServerLoad(true); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - Mockito.verify(session, Mockito.times(1)).setAttribute(SERVER_ROUTING, - Boolean.TRUE); - Mockito.verify(session, Mockito.times(0)).setAttribute(SERVER_ROUTING, - Boolean.FALSE); - - ((JavaScriptBootstrapUI) UI.getCurrent()).connectClient("foo", "bar", - "/foo", "", null); - - Mockito.verify(session, Mockito.times(1)).setAttribute(SERVER_ROUTING, - Boolean.FALSE); - } - - @Test - public void should_attachWebpackErrors() throws Exception { - deploymentConfiguration.setEnableDevServer(true); - deploymentConfiguration.setProductionMode(false); - - DevModeHandler devServer = Mockito.mock(DevModeHandler.class); - Mockito.when(devServer.getFailedOutput()) - .thenReturn("Failed to compile"); - Mockito.when(devServer.prepareConnection(Mockito.anyString(), - Mockito.anyString())) - .thenReturn(Mockito.mock(HttpURLConnection.class)); - service.setContext(context); - DevModeHandlerManager devModeHandlerManager = new DevModeHandlerManager() { - - @Override - public Class[] getHandlesTypes() { - return new Class[0]; - } - - @Override - public void initDevModeHandler(Set> classes, - VaadinContext context) throws VaadinInitializerException { - - } - - @Override - public void setDevModeHandler(DevModeHandler devModeHandler) { - - } - - @Override - public DevModeHandler getDevModeHandler() { - return devServer; - } - - @Override - public void launchBrowserInDevelopmentMode(String url) { - } - - @Override - public void stopDevModeHandler() { - } - - }; - ResourceProvider resourceProvider = Mockito - .mock(ResourceProvider.class); - Lookup lookup = Lookup.compose( - Lookup.of(devModeHandlerManager, DevModeHandlerManager.class), - Lookup.of(resourceProvider, ResourceProvider.class)); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(lookup); - - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - mockApplicationConfiguration(appConfig); - - URL resource = Mockito.mock(URL.class); - Mockito.when(resourceProvider - .getApplicationResource(VAADIN_WEBAPP_RESOURCES + INDEX_HTML)) - .thenReturn(resource); - when(resource.openStream()).thenReturn(new ByteArrayInputStream( - "".getBytes())); - - // Send the request - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Assert.assertTrue("Should have a system error dialog", - indexHtml.contains("
    ")); - Assert.assertTrue("Should show webpack failure error", - indexHtml.contains("Failed to compile")); - } - - @Test - public void should_not_add_metaElements_when_not_appShellPresent() - throws Exception { - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - // the template used in clientSide mode already has two metas - // see: src/main/resources/com/vaadin/flow/server/frontend/index.html - Elements elements = document.head().getElementsByTag("meta"); - assertEquals(2, elements.size()); - } - - @Test - public void should_add_metaAndPwa_Inline_Elements_when_appShellPresent() - throws Exception { - // Set class in context and do not call initializer - AppShellRegistry registry = AppShellRegistry.getInstance(context); - registry.setShell(AppShellWithPWA.class); - mocks.setAppShellRegistry(registry); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements elements = document.head().getElementsByTag("meta"); - assertEquals(8, elements.size()); - - Optional viewPort = findFirstElementByNameAttrEqualTo(elements, - "viewport"); - assertTrue("'viewport' meta link should exist.", viewPort.isPresent()); - assertEquals("my-viewport", viewPort.get().attr("content")); - - Optional appleMobileWebAppCapable = findFirstElementByNameAttrEqualTo( - elements, "apple-mobile-web-app-capable"); - assertTrue("'apple-mobile-web-app-capable' meta link should exist.", - appleMobileWebAppCapable.isPresent()); - assertEquals("yes", appleMobileWebAppCapable.get().attr("content")); - - Optional themeColor = findFirstElementByNameAttrEqualTo( - elements, "theme-color"); - assertTrue("'theme-color' meta link should exists.", - themeColor.isPresent()); - assertEquals("#ffffff", themeColor.get().attr("content")); - - Optional appleMobileWebAppStatusBar = findFirstElementByNameAttrEqualTo( - elements, "apple-mobile-web-app-status-bar-style"); - assertTrue( - "'apple-mobile-web-app-status-bar-style' meta link should exists.", - appleMobileWebAppStatusBar.isPresent()); - assertEquals("#ffffff", - appleMobileWebAppStatusBar.get().attr("content")); - - Optional mobileWebAppCapableElements = findFirstElementByNameAttrEqualTo( - elements, "mobile-web-app-capable"); - assertTrue("'mobile-web-app-capable' meta link should exists.", - mobileWebAppCapableElements.isPresent()); - assertEquals("yes", mobileWebAppCapableElements.get().attr("content")); - - Optional appleTouchFullScreenElements = findFirstElementByNameAttrEqualTo( - elements, "apple-touch-fullscreen"); - assertTrue("'apple-touch-fullscreen' meta link should exist.", - appleTouchFullScreenElements.isPresent()); - assertEquals("yes", appleTouchFullScreenElements.get().attr("content")); - - Optional appleMobileWebAppTitleElements = findFirstElementByNameAttrEqualTo( - elements, "apple-mobile-web-app-title"); - assertTrue("'apple-mobile-web-app-title' should exist.", - appleMobileWebAppTitleElements.isPresent()); - assertEquals("n", appleMobileWebAppTitleElements.get().attr("content")); - - Elements headInlineAndStyleElements = document.head() - .getElementsByTag("style"); - assertEquals(3, headInlineAndStyleElements.size()); - - assertEquals("[hidden] { display: none !important; }", - headInlineAndStyleElements.get(1).childNode(0).toString()); - - assertEquals("text/css", - headInlineAndStyleElements.get(2).attr("type")); - assertEquals("body,#outlet{width:my-width;height:my-height;}", - headInlineAndStyleElements.get(2).childNode(0).toString()); - } - - @Test - public void should_add_elements_when_appShellWithConfigurator() - throws Exception { - // Set class in context and do not call initializer - AppShellRegistry registry = AppShellRegistry.getInstance(context); - registry.setShell(MyAppShellWithConfigurator.class); - mocks.setAppShellRegistry(registry); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements elements = document.head().getElementsByTag("meta"); - assertEquals(4, elements.size()); - // already in the index.html used as template - assertEquals("UTF-8", elements.get(0).attr("charset")); - - // replaced ones in the index.html template by configurator ones - assertEquals("viewport", elements.get(1).attr("name")); - assertEquals("my-viewport", elements.get(1).attr("content")); - - // added by configurator - assertEquals("foo", elements.get(2).attr("name")); - assertEquals("bar", elements.get(2).attr("content")); - assertEquals("lorem", elements.get(3).attr("name")); - assertEquals("ipsum", elements.get(3).attr("content")); - - assertEquals("my-title", document.head().getElementsByTag("title") - .get(0).childNode(0).toString()); - - Elements headInlineAndStyleElements = document.head() - .getElementsByTag("style"); - assertEquals(4, headInlineAndStyleElements.size()); - - assertEquals("[hidden] { display: none !important; }", - headInlineAndStyleElements.get(2).childNode(0).toString()); - - assertEquals("text/css", - headInlineAndStyleElements.get(3).attr("type")); - assertEquals("body,#outlet{width:my-width;height:my-height;}", - headInlineAndStyleElements.get(3).childNode(0).toString()); - - Elements bodyInlineElements = document.body() - .getElementsByTag("script"); - assertEquals(3, bodyInlineElements.size()); - } - - @Test - public void should_export_usage_statistics_in_development_mode() - throws IOException { - deploymentConfiguration.setProductionMode(false); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements bodyInlineElements = document.body() - .getElementsByTag("script"); - assertEquals(2, bodyInlineElements.size()); - - String entries = UsageStatistics.getEntries().map(entry -> { - JsonObject json = Json.createObject(); - - json.put("is", entry.getName()); - json.put("version", entry.getVersion()); - - return json.toString(); - }).collect(Collectors.joining(",")); - - String expected = StringUtil - .normaliseWhitespace("window.Vaadin = window.Vaadin || {}; " - + "window.Vaadin.registrations = window.Vaadin.registrations || [];\n" - + "window.Vaadin.registrations.push(" + entries + ");"); - - String htmlContent = bodyInlineElements.get(1).childNode(0).outerHtml(); - htmlContent = htmlContent.replace("\r", ""); - htmlContent = htmlContent.replace("\n", " "); - assertEquals(StringUtil.normaliseWhitespace(expected), htmlContent); - } - - @Test - public void should_NOT_export_usage_statistics_in_production_mode() - throws IOException { - deploymentConfiguration.setProductionMode(true); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements bodyInlineElements = document.body() - .getElementsByTag("script"); - assertEquals(1, bodyInlineElements.size()); - } - - @Test - public void should_store_IndexHtmltitleToUI_When_LoadingServerEagerly() - throws IOException { - deploymentConfiguration.setEagerServerLoad(true); - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - assertEquals("Flow Test CCDM", - UI.getCurrent().getInternals().getAppShellTitle()); - } - - @Test(expected = UnsupportedOperationException.class) - public void should_throwUnSupportedException_when_usingAppShellToConfigureLoadingIndicator() - throws Exception { - // Set class in context and do not call initializer - AppShellRegistry registry = AppShellRegistry.getInstance(context); - registry.setShell(MyAppShellWithLoadingIndicatorConfig.class); - mocks.setAppShellRegistry(registry); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - } - - @Test(expected = UnsupportedOperationException.class) - public void should_throwUnSupportedException_when_usingAppShellToConfigureReconnectionDialog() - throws Exception { - // Set class in context and do not call initializer - AppShellRegistry registry = AppShellRegistry.getInstance(context); - registry.setShell(MyAppShellWithReconnectionDialogConfig.class); - mocks.setAppShellRegistry(registry); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - } - - @Test(expected = UnsupportedOperationException.class) - public void should_throwUnSupportedException_when_usingAppShellToConfigurePushMode() - throws Exception { - // Set class in context and do not call initializer - AppShellRegistry registry = AppShellRegistry.getInstance(context); - registry.setShell(MyAppShellWithPushConfig.class); - mocks.setAppShellRegistry(registry); - - indexHtmlRequestHandler.synchronizedHandleRequest(session, - createVaadinRequest("/"), response); - } - - @After - public void tearDown() throws Exception { - session.unlock(); - mocks.cleanup(); - } - - private Optional findFirstElementByNameAttrEqualTo( - Elements elements, String name) { - return elements.stream() - .filter(element -> name.equals(element.attr("name"))) - .findFirst(); - } - - private VaadinServletRequest createRequestWithDestination(String pathInfo, - String fetchDest, String fetchMode) { - VaadinServletRequest req = createVaadinRequest(pathInfo); - Mockito.when(req.getHeader(Mockito.anyString())).thenAnswer(arg -> { - if ("Sec-Fetch-Dest".equals(arg.getArgument(0))) { - return fetchDest; - } else if ("Sec-Fetch-Mode".equals(arg.getArgument(0))) { - return fetchMode; - } - return null; - }); - - return req; - } - - private VaadinServletRequest createVaadinRequest(String pathInfo) { - HttpServletRequest request = createRequest(pathInfo); - return new VaadinServletRequest(request, Mockito.spy(service)); - } - - private HttpServletRequest createRequest(String pathInfo) { - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Mockito.doAnswer(invocation -> "").when(request).getServletPath(); - Mockito.doAnswer(invocation -> pathInfo).when(request).getPathInfo(); - Mockito.doAnswer(invocation -> new StringBuffer(pathInfo)).when(request) - .getRequestURL(); - return request; - } - - private void mockApplicationConfiguration( - ApplicationConfiguration appConfig) { - Mockito.when(appConfig.isProductionMode()).thenReturn(false); - Mockito.when(appConfig.enableDevServer()).thenReturn(true); - - Mockito.when(appConfig.getStringProperty(Mockito.anyString(), - Mockito.anyString())) - .thenAnswer(invocation -> invocation.getArgument(1)); - Mockito.when(appConfig.getBooleanProperty(Mockito.anyString(), - Mockito.anyBoolean())) - .thenAnswer(invocation -> invocation.getArgument(1)); - } - - @Test - public void internal_request_no_bootstrap_page() { - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getPathInfo()).thenReturn(null); - Mockito.when(request.getParameter("v-r")).thenReturn("hello-foo-bar"); - Assert.assertTrue(BootstrapHandler.isFrameworkInternalRequest(request)); - Assert.assertFalse(indexHtmlRequestHandler.canHandleRequest(request)); - - Mockito.when(request.getParameter("v-r")).thenReturn("init"); - Assert.assertTrue(BootstrapHandler.isFrameworkInternalRequest(request)); - Assert.assertFalse(indexHtmlRequestHandler.canHandleRequest(request)); - } - - @Test - public void synchronizedHandleRequest_badLocation_noUiCreated() - throws IOException { - final IndexHtmlRequestHandler bootstrapHandler = new IndexHtmlRequestHandler(); - - final VaadinServletRequest request = Mockito - .mock(VaadinServletRequest.class); - Mockito.doAnswer(invocation -> "..**").when(request).getPathInfo(); - - final MockServletServiceSessionSetup.TestVaadinServletResponse response = mocks - .createResponse(); - - final boolean value = bootstrapHandler.synchronizedHandleRequest( - mocks.getSession(), request, response); - Assert.assertTrue("No further request handlers should be called", - value); - - Assert.assertEquals("Invalid status code reported", 400, - response.getErrorCode()); - Assert.assertEquals("Invalid message reported", - "Invalid location: Relative path cannot contain .. segments", - response.getErrorMessage()); - } - - @Test - public void serviceWorkerRequest_canNotHandleRequest() { - IndexHtmlRequestHandler bootstrapHandler = new IndexHtmlRequestHandler(); - - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - - Mockito.when(request.getHeader(BootstrapHandler.SERVICE_WORKER_HEADER)) - .thenReturn("script"); - - Assert.assertFalse(bootstrapHandler.canHandleRequest(request)); - } - - private VaadinRequest createVaadinRequestWithSpringCsrfToken() { - VaadinRequest request = Mockito.spy(createVaadinRequest("/")); - Map csrfJsonMap = new HashMap<>(); - csrfJsonMap.put("token", springTokenString); - csrfJsonMap.put("headerName", springTokenHeaderName); - csrfJsonMap.put("parameterName", springTokenParamName); - Mockito.when(request.getAttribute(SPRING_CSRF_ATTRIBUTE_IN_SESSION)) - .thenReturn(csrfJsonMap); - return request; - } - - private void assertSpringCsrfTokenIsAvailableAsMetaTagsInDom() { - try { - String indexHtml = responseOutput - .toString(StandardCharsets.UTF_8.name()); - Document document = Jsoup.parse(indexHtml); - - Elements csrfMetaEelement = document.head() - .getElementsByAttributeValue("name", SPRING_CSRF_ATTRIBUTE); - Assert.assertEquals(1, csrfMetaEelement.size()); - Assert.assertEquals(springTokenString, - csrfMetaEelement.first().attr("content")); - - Elements csrfHeaderMetaElement = document.head() - .getElementsByAttributeValue("name", "_csrf_header"); - Assert.assertEquals(1, csrfHeaderMetaElement.size()); - Assert.assertEquals(springTokenHeaderName, - csrfHeaderMetaElement.first().attr("content")); - - Elements csrfParameterMetaElement = document.head() - .getElementsByAttributeValue("name", "_csrf_parameter"); - Assert.assertEquals(1, csrfParameterMetaElement.size()); - Assert.assertEquals(springTokenParamName, - csrfParameterMetaElement.first().attr("content")); - } catch (Exception e) { - Assert.fail("Unable to parse the index html page"); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java deleted file mode 100644 index 3f7411f95eb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.IOException; -import java.util.regex.Pattern; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.PushConfiguration; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.JavaScriptBootstrapUI; -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.dom.NodeVisitor.ElementType; -import com.vaadin.flow.dom.TestNodeVisitor; -import com.vaadin.flow.dom.impl.BasicElementStateProvider; -import com.vaadin.flow.server.AppShellRegistry; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.MockServletServiceSessionSetup.TestVaadinServletResponse; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinServletContext; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.communication.PushMode; - -import elemental.json.Json; -import elemental.json.JsonObject; - -import static com.vaadin.flow.component.internal.JavaScriptBootstrapUI.SERVER_ROUTING; - -@NotThreadSafe -public class JavaScriptBootstrapHandlerTest { - - private MockServletServiceSessionSetup mocks; - - private TestVaadinServletResponse response; - private VaadinSession session; - private JavaScriptBootstrapHandler jsInitHandler; - - @Push - static public class PushAppShell implements AppShellConfigurator { - } - - @Before - public void setup() throws Exception { - mocks = new MockServletServiceSessionSetup(); - response = mocks.createResponse(); - session = mocks.getSession(); - jsInitHandler = new JavaScriptBootstrapHandler(); - } - - @After - public void tearDown() { - mocks.cleanup(); - } - - @Test - public void should_handleRequest_when_initTypeRequest() throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/", "v-r=init&foo"); - Assert.assertTrue(jsInitHandler.canHandleRequest(request)); - } - - @Test - public void should_not_handleRequest_when_pathInfo_set() throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/foo", - "v-r=init&foo"); - Assert.assertFalse(jsInitHandler.canHandleRequest(request)); - } - - @Test - public void should_not_handleRequest_if_not_initTypeRequest() - throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/", "v-r=bar"); - Assert.assertFalse(jsInitHandler.canHandleRequest(request)); - } - - @Test - public void should_produceValidJsonResponse() throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&foo&location"); - jsInitHandler.handleRequest(session, request, response); - - Assert.assertEquals(200, response.getErrorCode()); - - Assert.assertEquals("application/json", response.getContentType()); - - JsonObject json = Json.parse(response.getPayload()); - - Assert.assertTrue(json.hasKey("stats")); - Assert.assertTrue(json.hasKey("errors")); - Assert.assertTrue(json.hasKey("appConfig")); - Assert.assertTrue(json.getObject("appConfig").hasKey("appId")); - Assert.assertTrue(json.getObject("appConfig").getObject("uidl") - .hasKey("changes")); - Assert.assertTrue(json.getObject("appConfig").getBoolean("debug")); - Assert.assertFalse( - json.getObject("appConfig").hasKey("webComponentMode")); - - Assert.assertEquals("./", - json.getObject("appConfig").getString("contextRootUrl")); - Assert.assertNull( - "ServiceUrl should not be set. It will be computed by flow-client", - json.getObject("appConfig").get("serviceUrl")); - Assert.assertEquals("http://localhost:8888/", - json.getObject("appConfig").getString("requestURL")); - - Assert.assertFalse(json.hasKey("pushScript")); - } - - @Test - public void should_initialize_UI() throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&foo&location="); - jsInitHandler.handleRequest(session, request, response); - - Assert.assertNotNull(UI.getCurrent()); - Assert.assertEquals(JavaScriptBootstrapUI.class, - UI.getCurrent().getClass()); - - Mockito.verify(session, Mockito.times(0)).setAttribute(SERVER_ROUTING, - Boolean.TRUE); - - } - - @Test - public void should_attachViewTo_UiContainer() throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&foo&location="); - jsInitHandler.handleRequest(session, request, response); - - JavaScriptBootstrapUI ui = (JavaScriptBootstrapUI) UI.getCurrent(); - ui.connectClient("a-tag", "an-id", "a-route", "", null); - - TestNodeVisitor visitor = new TestNodeVisitor(true); - BasicElementStateProvider.get().visit(ui.getElement().getNode(), - visitor); - - Assert.assertTrue( - hasNodeTag(visitor, "^.*", ElementType.REGULAR)); - Assert.assertTrue(hasNodeTag(visitor, "^.*", - ElementType.VIRTUAL_ATTACHED)); - Assert.assertTrue(hasNodeTag(visitor, "^
    .*", ElementType.REGULAR)); - Assert.assertTrue( - hasNodeTag(visitor, "^
    .*Could not navigate to 'a-route'.*", - ElementType.REGULAR)); - - } - - @Test - public void should_attachViewTo_Body_when_serverRouting() throws Exception { - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&location=bar%3Fpar1%26par2&serverSideRouting"); - - jsInitHandler.handleRequest(session, request, response); - - JavaScriptBootstrapUI ui = (JavaScriptBootstrapUI) UI.getCurrent(); - - TestNodeVisitor visitor = new TestNodeVisitor(true); - BasicElementStateProvider.get().visit(ui.getElement().getNode(), - visitor); - - Assert.assertTrue( - hasNodeTag(visitor, "^.*", ElementType.REGULAR)); - Assert.assertTrue(hasNodeTag(visitor, "^
    .*", ElementType.REGULAR)); - Assert.assertTrue(hasNodeTag(visitor, - "^
    .*Could not navigate to 'bar'.*", ElementType.REGULAR)); - Mockito.verify(session, Mockito.times(1)).setAttribute(SERVER_ROUTING, - Boolean.TRUE); - - } - - @Test - public void should_respondPushScript_when_enabledInDeploymentConfiguration() - throws Exception { - mocks.getDeploymentConfiguration().setPushMode(PushMode.AUTOMATIC); - - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&foo&location="); - jsInitHandler.handleRequest(session, request, response); - - Assert.assertEquals(200, response.getErrorCode()); - Assert.assertEquals("application/json", response.getContentType()); - JsonObject json = Json.parse(response.getPayload()); - - // Using regex, because version depends on the build - Assert.assertTrue(json.getString("pushScript").matches( - "^\\./VAADIN/static/push/vaadinPush\\.js\\?v=[\\w\\.\\-]+$")); - } - - @Test - public void should_respondPushScript_when_nonRootServletPath() - throws Exception { - mocks.getDeploymentConfiguration().setPushMode(PushMode.AUTOMATIC); - - VaadinRequest request = mocks.createRequest(mocks, "/", "/vaadin/", - "v-r=init&foo&location="); - jsInitHandler.handleRequest(session, request, response); - - Assert.assertEquals(200, response.getErrorCode()); - Assert.assertEquals("application/json", response.getContentType()); - JsonObject json = Json.parse(response.getPayload()); - - // Using regex, because version depends on the build - Assert.assertTrue(json.getString("pushScript").matches( - "^\\./VAADIN/static/push/vaadinPush\\.js\\?v=[\\w\\.\\-]+$")); - } - - @Test - public void should_invoke_modifyPushConfiguration() throws Exception { - AppShellRegistry registry = Mockito.mock(AppShellRegistry.class); - mocks.setAppShellRegistry(registry); - - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&foo&location="); - jsInitHandler.handleRequest(session, request, response); - - Mockito.verify(registry) - .modifyPushConfiguration(Mockito.any(PushConfiguration.class)); - } - - @Test - public void should_respondPushScript_when_annotatedInAppShell() - throws Exception { - VaadinServletContext context = new VaadinServletContext( - mocks.getServletContext()); - AppShellRegistry registry = AppShellRegistry.getInstance(context); - registry.setShell(PushAppShell.class); - mocks.setAppShellRegistry(registry); - - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&foo&location"); - jsInitHandler.handleRequest(session, request, response); - - Assert.assertEquals(200, response.getErrorCode()); - Assert.assertEquals("application/json", response.getContentType()); - JsonObject json = Json.parse(response.getPayload()); - - // Using regex, because version depends on the build - Assert.assertTrue(json.getString("pushScript").matches( - "^\\./VAADIN/static/push/vaadinPush\\.js\\?v=[\\w\\.\\-]+$")); - } - - @Test - public void synchronizedHandleRequest_badLocation_noUiCreated() - throws IOException { - final JavaScriptBootstrapHandler bootstrapHandler = new JavaScriptBootstrapHandler(); - - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=init&location=..**"); - - final MockServletServiceSessionSetup.TestVaadinServletResponse response = mocks - .createResponse(); - - final boolean value = bootstrapHandler.synchronizedHandleRequest( - mocks.getSession(), request, response); - Assert.assertTrue("No further request handlers should be called", - value); - - Assert.assertEquals("Invalid status code reported", 400, - response.getErrorCode()); - Assert.assertEquals("Invalid message reported", - "Invalid location: Relative path cannot contain .. segments", - response.getErrorMessage()); - } - - @Test - public void synchronizedHandleRequest_noLocationParameter_noUiCreated() - throws IOException { - final JavaScriptBootstrapHandler bootstrapHandler = new JavaScriptBootstrapHandler(); - - VaadinRequest request = mocks.createRequest(mocks, "/", - "v-r=ini&foobar"); - - final MockServletServiceSessionSetup.TestVaadinServletResponse response = mocks - .createResponse(); - - final boolean value = bootstrapHandler.synchronizedHandleRequest( - mocks.getSession(), request, response); - Assert.assertTrue("No further request handlers should be called", - value); - - Assert.assertEquals("Invalid status code reported", 400, - response.getErrorCode()); - Assert.assertEquals("Invalid message reported", - "Invalid location: Location parameter missing from bootstrap request to server.", - response.getErrorMessage()); - } - - private boolean hasNodeTag(TestNodeVisitor visitor, String htmContent, - ElementType type) { - Pattern regex = Pattern.compile(htmContent, Pattern.DOTALL); - return visitor.getVisited().entrySet().stream().anyMatch(entry -> { - return entry.getValue().equals(type) - && regex.matcher(entry.getKey().toString()).find(); - }); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/MetadataWriterTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/MetadataWriterTest.java deleted file mode 100644 index 743296efdfc..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/MetadataWriterTest.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.server.SystemMessages; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.VaadinSessionState; -import com.vaadin.flow.server.WrappedSession; - -import elemental.json.JsonObject; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class MetadataWriterTest { - - private UI ui; - private VaadinSession session; - private SystemMessages messages; - - @Before - public void setup() { - ui = Mockito.mock(UI.class); - session = Mockito.mock(VaadinSession.class); - Mockito.when(ui.getSession()).thenReturn(session); - messages = Mockito.mock(SystemMessages.class); - } - - private void disableSessionExpirationMessages(SystemMessages messages) { - when(messages.isSessionExpiredNotificationEnabled()).thenReturn(true); - when(messages.getSessionExpiredMessage()).thenReturn(null); - when(messages.getSessionExpiredCaption()).thenReturn(null); - } - - @Test - public void writeAsyncTag() throws Exception { - assertMetadataOutput(false, true, "{\"async\":true}"); - } - - @Test - public void writeRepaintTag() throws Exception { - assertMetadataOutput(true, false, "{\"repaintAll\":true}"); - } - - @Test - public void writeRepaintAndAsyncTag() throws Exception { - assertMetadataOutput(true, true, - "{\"repaintAll\":true,\"async\":true}"); - } - - @Test - public void writeRedirectWithExpiredSession() throws Exception { - disableSessionExpirationMessages(messages); - - assertMetadataOutput(false, false, "{}"); - } - - @Test - public void writeRedirectWithActiveSession() throws Exception { - WrappedSession wrappedSession = mock(WrappedSession.class); - when(session.getSession()).thenReturn(wrappedSession); - - disableSessionExpirationMessages(messages); - - assertMetadataOutput(false, false, - "{\"timedRedirect\":{\"interval\":15,\"url\":\"\"}}"); - } - - @Test - public void writeAsyncWithSystemMessages() throws IOException { - WrappedSession wrappedSession = mock(WrappedSession.class); - when(session.getSession()).thenReturn(wrappedSession); - - disableSessionExpirationMessages(messages); - - assertMetadataOutput(false, true, - "{\"async\":true,\"timedRedirect\":{\"interval\":15,\"url\":\"\"}}"); - } - - @Test - public void writeSessionExpiredTag_sessionIsOpen() throws Exception { - Mockito.when(session.getState()).thenReturn(VaadinSessionState.OPEN); - assertMetadataOutput(false, false, "{}"); - } - - @Test - public void writeSessionExpiredTag_sessionIsClosing() throws Exception { - Mockito.when(session.getState()).thenReturn(VaadinSessionState.CLOSING); - assertMetadataOutput(false, false, "{\"sessionExpired\":true}"); - - Mockito.when(session.getState()).thenReturn(VaadinSessionState.CLOSED); - assertMetadataOutput(false, false, "{\"sessionExpired\":true}"); - } - - @Test - public void writeSessionExpiredTag_sessionIsClosed() throws Exception { - Mockito.when(session.getState()).thenReturn(VaadinSessionState.CLOSED); - assertMetadataOutput(false, false, "{\"sessionExpired\":true}"); - } - - private void assertMetadataOutput(boolean repaintAll, boolean async, - String expectedOutput) { - JsonObject meta = new MetadataWriter().createMetadata(ui, repaintAll, - async, messages); - Assert.assertEquals(expectedOutput, meta.toJson()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/PushAtmosphereHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/PushAtmosphereHandlerTest.java deleted file mode 100644 index 1659fc326eb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/PushAtmosphereHandlerTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.communication; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Collections; -import java.util.Properties; - -import org.atmosphere.cpr.AtmosphereRequest; -import org.atmosphere.cpr.AtmosphereResource; -import org.atmosphere.cpr.AtmosphereResponse; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.server.DefaultDeploymentConfiguration; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.startup.ApplicationConfiguration; - -public class PushAtmosphereHandlerTest { - - private AtmosphereResource resource; - - private AtmosphereRequest request; - private AtmosphereResponse response; - private PrintWriter printWriter; - - private PushAtmosphereHandler atmosphereHandler; - - @Before - public void setup() throws IOException { - request = Mockito.mock(AtmosphereRequest.class); - response = Mockito.mock(AtmosphereResponse.class); - printWriter = Mockito.mock(PrintWriter.class); - Mockito.when(response.getWriter()).thenReturn(printWriter); - - resource = Mockito.mock(AtmosphereResource.class); - Mockito.when(resource.getRequest()).thenReturn(request); - Mockito.when(resource.getResponse()).thenReturn(response); - - VaadinContext context = new MockVaadinContext(); - ApplicationConfiguration config = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(config.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - Mockito.when(config.getContext()).thenReturn(context); - VaadinServletService service = new VaadinServletService(null, - new DefaultDeploymentConfiguration(config, getClass(), - new Properties())); - - PushHandler handler = new PushHandler(service); - - atmosphereHandler = new PushAtmosphereHandler(); - atmosphereHandler.setPushHandler(handler); - } - - @Test - public void writeSessionExpiredAsyncGet() throws Exception { - writeSessionExpiredAsync("GET"); - } - - @Test - public void writeSessionExpiredAsyncPost() throws Exception { - writeSessionExpiredAsync("POST"); - } - - private void writeSessionExpiredAsync(String httpMethod) - throws IOException { - Mockito.when(request.getMethod()).thenReturn(httpMethod); - - atmosphereHandler.onRequest(resource); - - String responseContent = CommunicationUtil - .getStringWhenWriteString(printWriter); - - // response shouldn't contain async - Assert.assertEquals("Invalid response", - "for(;;);[{\"meta\":{\"async\":true,\"sessionExpired\":true}}]", - responseContent); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/PushHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/PushHandlerTest.java deleted file mode 100644 index 9d2ee7c22da..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/PushHandlerTest.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; - -import org.atmosphere.cpr.AtmosphereRequest; -import org.atmosphere.cpr.AtmosphereResource; -import org.atmosphere.cpr.AtmosphereResource.TRANSPORT; -import org.atmosphere.cpr.AtmosphereResourceEvent; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.internal.BrowserLiveReload; -import com.vaadin.flow.internal.BrowserLiveReloadAccessor; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.SessionExpiredException; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -public class PushHandlerTest { - - @Test - public void onConnect_websocketTransport_requestStartIsCalledOnServiceInstance() { - VaadinServletService service = runTest((handler, resource) -> { - Mockito.when(resource.transport()).thenReturn(TRANSPORT.WEBSOCKET); - handler.onConnect(resource); - }); - - Mockito.verify(service).requestStart(Mockito.any(), Mockito.any()); - } - - @Test - public void onConnect_notWebsocketTransport_requestStartIsNotCalledOnServiceInstance() { - VaadinServletService service = runTest((handler, resource) -> { - Mockito.when(resource.transport()).thenReturn(TRANSPORT.AJAX); - handler.onConnect(resource); - }); - - Mockito.verify(service, Mockito.times(0)).requestStart(Mockito.any(), - Mockito.any()); - } - - @Test - public void onMessage_websocketTransport_requestStartIsCalledOnServiceInstance() { - VaadinServletService service = runTest((handler, resource) -> { - Mockito.when(resource.transport()).thenReturn(TRANSPORT.WEBSOCKET); - handler.onMessage(resource); - }); - - Mockito.verify(service).requestStart(Mockito.any(), Mockito.any()); - } - - @Test - public void onMessage_notWebsocketTransport_requestStartIsNotCalledOnServiceInstance() { - VaadinServletService service = runTest((handler, resource) -> { - Mockito.when(resource.transport()).thenReturn(TRANSPORT.AJAX); - handler.onMessage(resource); - }); - - Mockito.verify(service, Mockito.times(0)).requestStart(Mockito.any(), - Mockito.any()); - } - - @Test - public void onConnect_devMode_websocket_refreshConnection_onConnectIsCalled_callWithUIIsNotCalled() - throws ServiceException { - MockVaadinServletService service = Mockito - .spy(MockVaadinServletService.class); - MockDeploymentConfiguration deploymentConfiguration = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - deploymentConfiguration.setProductionMode(false); - deploymentConfiguration.setDevModeLiveReloadEnabled(true); - deploymentConfiguration.setDevToolsEnabled(true); - - ApplicationConfiguration applicationConfiguration = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(applicationConfiguration.isProductionMode()) - .thenReturn(false); - - VaadinContext context = service.getContext(); - context.setAttribute(ApplicationConfiguration.class, - applicationConfiguration); - - BrowserLiveReload liveReload = mockBrowserLiveReloadImpl(context); - - AtomicReference res = new AtomicReference<>(); - runTest(service, (handler, resource) -> { - AtmosphereRequest request = resource.getRequest(); - Mockito.when(request - .getParameter(ApplicationConstants.DEBUG_WINDOW_CONNECTION)) - .thenReturn(""); - Mockito.when(resource.transport()).thenReturn(TRANSPORT.WEBSOCKET); - handler.onConnect(resource); - res.set(resource); - }); - Mockito.verify(service, Mockito.times(0)).requestStart(Mockito.any(), - Mockito.any()); - Mockito.verify(liveReload).onConnect(res.get()); - } - - @Test - public void onMessage_devMode_websocket_refreshConnection_callWithUIIsNotCalled() - throws ServiceException { - MockVaadinServletService service = Mockito - .spy(MockVaadinServletService.class); - MockDeploymentConfiguration deploymentConfiguration = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - deploymentConfiguration.setProductionMode(false); - deploymentConfiguration.setDevModeLiveReloadEnabled(true); - deploymentConfiguration.setDevToolsEnabled(true); - - VaadinContext context = service.getContext(); - mockBrowserLiveReloadImpl(context); - - AtomicReference res = new AtomicReference<>(); - runTest(service, (handler, resource) -> { - AtmosphereRequest request = resource.getRequest(); - try { - Mockito.when(request.getReader()) - .thenReturn(new BufferedReader(new StringReader(""))); - } catch (IOException e) { - throw new RuntimeException(e); - } - Mockito.when(request - .getParameter(ApplicationConstants.DEBUG_WINDOW_CONNECTION)) - .thenReturn(""); - Mockito.when(resource.transport()).thenReturn(TRANSPORT.WEBSOCKET); - try { - Mockito.when(request.getReader()) - .thenReturn(new BufferedReader(new StringReader("{}"))); - } catch (IOException e) { - throw new RuntimeException(e); - } - handler.onMessage(resource); - res.set(resource); - }); - Mockito.verify(service, Mockito.times(0)).requestStart(Mockito.any(), - Mockito.any()); - } - - @Test - public void onConnect_devMode_websocket_noRefreshConnection_delegteCallWithUI() - throws ServiceException { - MockVaadinServletService service = Mockito - .spy(MockVaadinServletService.class); - MockDeploymentConfiguration deploymentConfiguration = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - deploymentConfiguration.setProductionMode(false); - runTest(service, (handler, resource) -> { - AtmosphereRequest request = resource.getRequest(); - Mockito.when(request - .getParameter(ApplicationConstants.DEBUG_WINDOW_CONNECTION)) - .thenReturn(null); - Mockito.when(resource.transport()).thenReturn(TRANSPORT.WEBSOCKET); - handler.onConnect(resource); - }); - Mockito.verify(service).requestStart(Mockito.any(), Mockito.any()); - } - - @Test - public void onConnect_devMode_notWebsocket_refreshConnection_delegteCallWithUI() - throws ServiceException, SessionExpiredException { - MockVaadinServletService service = Mockito - .spy(MockVaadinServletService.class); - MockDeploymentConfiguration deploymentConfiguration = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - deploymentConfiguration.setProductionMode(false); - runTest(service, (handler, resource) -> { - AtmosphereRequest request = resource.getRequest(); - Mockito.when(request - .getParameter(ApplicationConstants.DEBUG_WINDOW_CONNECTION)) - .thenReturn(""); - Mockito.when(resource.transport()).thenReturn(TRANSPORT.AJAX); - handler.onConnect(resource); - }); - Mockito.verify(service).findVaadinSession(Mockito.any()); - } - - @Test - public void connectionLost_noSession_currentInstancesAreCleared() - throws SessionExpiredException { - try { - mockConnectionLost(new MockVaadinSession(), false); - - Assert.assertNull(VaadinSession.getCurrent()); - } finally { - VaadinSession.setCurrent(null); - } - } - - @Test - public void connectionLost_sessionIsSetViaCurrent_currentInstancesAreCleared() - throws SessionExpiredException { - try { - mockConnectionLost(new MockVaadinSession(), true); - Assert.assertNotNull(VaadinSession.getCurrent()); - } finally { - VaadinSession.setCurrent(null); - } - } - - @Test - public void debugWindowConnection_productionMode_mustNeverBeConnected() - throws Exception { - ApplicationConfiguration applicationConfiguration = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(applicationConfiguration.isProductionMode()) - .thenReturn(true); - - MockVaadinServletService service = Mockito - .spy(MockVaadinServletService.class); - VaadinContext context = service.getContext(); - context.setAttribute(ApplicationConfiguration.class, - applicationConfiguration); - - runTest(service, (handler, resource) -> { - Mockito.when(resource.transport()).thenReturn(TRANSPORT.WEBSOCKET); - Mockito.when(resource.getRequest() - .getParameter(ApplicationConstants.DEBUG_WINDOW_CONNECTION)) - .thenReturn(""); - Mockito.doNothing().when(handler).callWithService(Mockito.any(), - Mockito.any()); - - handler.onConnect(resource); - - Mockito.verify(handler, Mockito.never()) - .callWithService(Mockito.any(), Mockito.any()); - Mockito.verify(handler, Mockito.never()).callWithUi(Mockito.any(), - Mockito.any()); - }); - - } - - private void mockConnectionLost(VaadinSession session, boolean setSession) { - AtomicBoolean sessionIsSet = new AtomicBoolean(); - MockVaadinServletService service = new MockVaadinServletService() { - @Override - public com.vaadin.flow.server.VaadinSession findVaadinSession( - VaadinRequest request) throws SessionExpiredException { - VaadinSession.setCurrent(session); - sessionIsSet.set(true); - Assert.assertNotNull(VaadinSession.getCurrent()); - return session; - } - - @Override - public UI findUI(VaadinRequest request) { - return null; - } - }; - - if (setSession) { - VaadinSession.setCurrent(session); - } - PushHandler handler = new PushHandler(service); - - AtmosphereResource resource = Mockito.mock(AtmosphereResource.class); - AtmosphereRequest request = Mockito.mock(AtmosphereRequest.class); - Mockito.when(resource.getRequest()).thenReturn(request); - - AtmosphereResourceEvent event = Mockito - .mock(AtmosphereResourceEvent.class); - Mockito.when(event.getResource()).thenReturn(resource); - handler.connectionLost(event); - - Assert.assertTrue(sessionIsSet.get()); - } - - private VaadinServletService runTest(VaadinServletService service, - BiConsumer testExec) - throws ServiceException { - PushHandler handler = Mockito.spy(new PushHandler(service)); - - AtmosphereResource resource = Mockito.mock(AtmosphereResource.class); - AtmosphereRequest request = Mockito.mock(AtmosphereRequest.class); - Mockito.when(resource.getRequest()).thenReturn(request); - - testExec.accept(handler, resource); - - return service; - } - - private VaadinServletService runTest( - BiConsumer testExec) { - MockVaadinServletService service = Mockito - .spy(MockVaadinServletService.class); - try { - runTest(service, testExec); - return service; - } catch (ServiceException exception) { - throw new RuntimeException(exception); - } - } - - public static BrowserLiveReload mockBrowserLiveReloadImpl( - VaadinContext context) { - BrowserLiveReload liveReload = Mockito.mock(BrowserLiveReload.class); - Lookup lookup = Lookup.of(new BrowserLiveReloadAccessor() { - @Override - public BrowserLiveReload getLiveReload(VaadinContext context) { - return liveReload; - } - }, BrowserLiveReloadAccessor.class); - context.setAttribute(Lookup.class, lookup); - return liveReload; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/PwaHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/PwaHandlerTest.java deleted file mode 100644 index 8bb7c17aa3a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/PwaHandlerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.server.PwaConfiguration; -import com.vaadin.flow.server.PwaRegistry; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinSession; - -public class PwaHandlerTest { - - private VaadinSession session = Mockito.mock(VaadinSession.class); - - private VaadinRequest request = Mockito.mock(VaadinRequest.class); - - private VaadinResponse response = Mockito.mock(VaadinResponse.class); - - @Test - public void handleRequest_noPwaRegistry_returnsFalse() throws IOException { - PwaHandler handler = new PwaHandler(() -> null); - Assert.assertFalse(handler.handleRequest(session, request, response)); - } - - @Test - public void handleRequest_pwaRegistryConfigIsDisabled_returnsFalse() - throws IOException { - PwaRegistry registry = Mockito.mock(PwaRegistry.class); - PwaConfiguration configuration = Mockito.mock(PwaConfiguration.class); - Mockito.when(registry.getPwaConfiguration()).thenReturn(configuration); - Mockito.when(configuration.isEnabled()).thenReturn(false); - PwaHandler handler = new PwaHandler(() -> registry); - Assert.assertFalse(handler.handleRequest(session, request, response)); - } - - @Test - public void handleRequest_pwaRegistryConfigIsEnabled_pathIsPwaResource_returnsTrue() - throws IOException { - PwaRegistry registry = Mockito.mock(PwaRegistry.class); - PwaConfiguration configuration = Mockito.mock(PwaConfiguration.class); - Mockito.when(registry.getPwaConfiguration()).thenReturn(configuration); - Mockito.when(configuration.isEnabled()).thenReturn(true); - PwaHandler handler = new PwaHandler(() -> registry); - - Mockito.when(response.getWriter()) - .thenReturn(new PrintWriter(new StringWriter())); - Mockito.when(registry.getRuntimeServiceWorkerJs()).thenReturn(""); - - Mockito.when(request.getPathInfo()) - .thenReturn("/sw-runtime-resources-precache.js"); - Assert.assertTrue(handler.handleRequest(session, request, response)); - } - - @Test - public void handleRequest_pwaRegistryConfigIsEnabled_handlerIsInitializedOnce() - throws IOException { - - PwaRegistry registry = Mockito.mock(PwaRegistry.class); - PwaConfiguration configuration = Mockito.mock(PwaConfiguration.class); - Mockito.when(registry.getPwaConfiguration()).thenReturn(configuration); - Mockito.when(configuration.isEnabled()).thenReturn(true); - PwaHandler handler = new PwaHandler(() -> registry); - - Mockito.when(response.getWriter()) - .thenReturn(new PrintWriter(new StringWriter())); - Mockito.when(registry.getRuntimeServiceWorkerJs()).thenReturn(""); - Mockito.when(request.getPathInfo()) - .thenReturn("/sw-runtime-resources-precache.js"); - - Assert.assertTrue(handler.handleRequest(session, request, response)); - Assert.assertTrue(handler.handleRequest(session, request, response)); - - Mockito.verify(registry, Mockito.times(1)).getIcons(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/ServerRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/ServerRpcHandlerTest.java deleted file mode 100644 index ae7272e4b3d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/ServerRpcHandlerTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.vaadin.flow.server.communication; - -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.DependencyList; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.MessageDigestUtil; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.communication.ServerRpcHandler.InvalidUIDLSecurityKeyException; -import com.vaadin.flow.shared.ApplicationConstants; - -public class ServerRpcHandlerTest { - private VaadinRequest request; - private VaadinService service; - private VaadinSession session; - private UI ui; - private UIInternals uiInternals; - private DependencyList dependencyList; - - private StateTree uiTree; - final private String csrfToken = ""; - - private ServerRpcHandler serverRpcHandler; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void setup() { - request = Mockito.mock(VaadinRequest.class); - service = Mockito.mock(VaadinService.class); - session = Mockito.mock(VaadinSession.class); - ui = Mockito.mock(UI.class); - uiInternals = Mockito.mock(UIInternals.class); - dependencyList = Mockito.mock(DependencyList.class); - - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(session.getService()).thenReturn(service); - - Mockito.when(ui.getInternals()).thenReturn(uiInternals); - Mockito.when(ui.getSession()).thenReturn(session); - Mockito.when(ui.getCsrfToken()).thenReturn(csrfToken); - - DeploymentConfiguration deploymentConfiguration = Mockito - .mock(DeploymentConfiguration.class); - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(deploymentConfiguration); - - uiTree = new StateTree(uiInternals); - Mockito.when(uiInternals.getStateTree()).thenReturn(uiTree); - Mockito.when(uiInternals.getDependencyList()) - .thenReturn(dependencyList); - - serverRpcHandler = new ServerRpcHandler(); - } - - @Test - public void handleRpc_resynchronize_throwsExceptionAndDirtiesTreeAndClearsDependenciesSent() - throws IOException, - ServerRpcHandler.InvalidUIDLSecurityKeyException { - // given - StringReader reader = new StringReader("{\"csrfToken\": \"" + csrfToken - + "\", \"rpc\":[], \"resynchronize\": true, \"clientId\":1}"); - uiTree.collectChanges(c -> { // clean tree - }); - thrown.expect( - ServerRpcHandler.ResynchronizationRequiredException.class); - - // when - serverRpcHandler.handleRpc(ui, reader, request); - - // then there are dirty nodes - Assert.assertTrue(uiTree.hasDirtyNodes()); - - // the dependencies-sent cache was cleared - Mockito.verify(dependencyList).clearPendingSendToClient(); - } - - @Test - public void handleRpc_duplicateMessage_doNotThrow() - throws InvalidUIDLSecurityKeyException, IOException { - String msg = "{\"" + ApplicationConstants.CLIENT_TO_SERVER_ID + "\":1}"; - ServerRpcHandler handler = new ServerRpcHandler() { - @Override - protected String getMessage(Reader reader) throws IOException { - return msg; - }; - }; - - ui = new UI(); - ui.getInternals().setSession(session); - ui.getInternals().setLastProcessedClientToServerId(1, - MessageDigestUtil.sha256(msg)); - - // This invocation shouldn't throw. No other checks - handler.handleRpc(ui, Mockito.mock(Reader.class), request); - } - - @Test(expected = UnsupportedOperationException.class) - public void handleRpc_unexpectedMessage_throw() - throws InvalidUIDLSecurityKeyException, IOException { - ServerRpcHandler handler = new ServerRpcHandler() { - @Override - protected String getMessage(Reader reader) throws IOException { - return "{\"" + ApplicationConstants.CLIENT_TO_SERVER_ID - + "\":1}"; - }; - }; - - ui = new UI(); - ui.getInternals().setSession(session); - - handler.handleRpc(ui, Mockito.mock(Reader.class), request); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java deleted file mode 100644 index 5c172e07f7f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamReceiverHandlerTest.java +++ /dev/null @@ -1,452 +0,0 @@ -package com.vaadin.flow.server.communication; - -import jakarta.servlet.ReadListener; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletInputStream; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.Part; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.UIInternals; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.server.ErrorHandler; -import com.vaadin.flow.server.HttpStatusCode; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.StreamReceiver; -import com.vaadin.flow.server.StreamResourceRegistry; -import com.vaadin.flow.server.StreamVariable; -import com.vaadin.flow.server.UploadException; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.ApplicationConstants; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class StreamReceiverHandlerTest { - - private StreamReceiverHandler handler; - @Mock - private VaadinResponse response; - @Mock - private StreamVariable streamVariable; - @Mock - private StateNode stateNode; - // @Mock - private VaadinRequest request; - @Mock - private UI ui; - @Mock - private UIInternals uiInternals; - @Mock - private StateTree stateTree; - @Mock - private VaadinSession session; - @Mock - private OutputStream responseOutput; - @Mock - private StreamReceiver streamReceiver; - @Mock - private StreamResourceRegistry registry; - @Mock - private ErrorHandler errorHandler; - - private VaadinServletService mockService; - - private final int uiId = 123; - private final int nodeId = 1233; - private final String variableName = "name"; - private final String expectedSecurityKey = "key"; - - private String contentLength; - private ServletInputStream inputStream; - private OutputStream outputStream; - private String contentType; - private List parts; - - private boolean isGetContentLengthLongCalled; - - @Before - public void setup() throws Exception { - contentLength = "6"; - inputStream = createInputStream("foobar"); - outputStream = mock(OutputStream.class); - contentType = "foobar"; - parts = Collections.emptyList(); - MockitoAnnotations.initMocks(this); - - handler = new StreamReceiverHandler(); - - mockService = new MockVaadinServletService(); - - mockRequest(); - mockReceiverAndRegistry(); - mockUi(); - - when(streamReceiver.getNode()).thenReturn(stateNode); - when(stateNode.isAttached()).thenReturn(true); - when(streamVariable.getOutputStream()) - .thenAnswer(invocationOnMock -> outputStream); - when(response.getOutputStream()).thenReturn(responseOutput); - - Mockito.when(session.getErrorHandler()) - .thenReturn(Mockito.mock(ErrorHandler.class)); - } - - private void mockReceiverAndRegistry() { - when(session.getResourceRegistry()).thenReturn(registry); - when(registry.getResource(Mockito.any())) - .thenReturn(Optional.of(streamReceiver)); - when(streamReceiver.getId()).thenReturn(expectedSecurityKey); - when(streamReceiver.getStreamVariable()).thenReturn(streamVariable); - } - - private void mockRequest() throws IOException { - HttpServletRequest servletRequest = Mockito - .mock(HttpServletRequest.class); - when(servletRequest.getContentLength()).thenAnswer( - invocationOnMock -> Integer.parseInt(contentLength)); - - request = new VaadinServletRequest(servletRequest, mockService) { - @Override - public String getParameter(String name) { - if ("restartApplication".equals(name) - || "ignoreRestart".equals(name) - || "closeApplication".equals(name)) { - return null; - } - return "1"; - } - - @Override - public String getPathInfo() { - return "/" + StreamRequestHandler.DYN_RES_PREFIX + uiId + "/" - + nodeId + "/" + variableName + "/" - + expectedSecurityKey; - } - - @Override - public String getMethod() { - return "POST"; - } - - @Override - public ServletInputStream getInputStream() throws IOException { - return inputStream; - } - - @Override - public String getHeader(String name) { - if ("content-length".equals(name.toLowerCase())) { - return contentLength; - } - return super.getHeader(name); - } - - @Override - public String getContentType() { - return contentType; - } - - @Override - public Collection getParts() - throws IOException, ServletException { - return parts; - } - - @Override - public long getContentLengthLong() { - isGetContentLengthLongCalled = true; - return 0; - } - }; - } - - private ServletInputStream createInputStream(final String content) { - return new ServletInputStream() { - boolean finished = false; - - @Override - public boolean isFinished() { - return finished; - } - - @Override - public boolean isReady() { - return true; - } - - @Override - public void setReadListener(ReadListener readListener) { - - } - - int counter = 0; - byte[] msg = content.getBytes(); - - @Override - public int read() throws IOException { - if (counter > msg.length + 1) { - throw new AssertionError( - "-1 was ignored by StreamReceiverHandler."); - } - - if (counter >= msg.length) { - counter++; - finished = true; - return -1; - } - - return msg[counter++]; - } - }; - } - - private Part createPart(InputStream inputStream, String contentType, - String name, long size) throws IOException { - Part part = mock(Part.class); - when(part.getInputStream()).thenReturn(inputStream); - when(part.getContentType()).thenReturn(contentType); - when(part.getSubmittedFileName()).thenReturn(name); - when(part.getSize()).thenReturn(size); - return part; - } - - private void mockUi() { - when(ui.getInternals()).thenReturn(uiInternals); - when(uiInternals.getStateTree()).thenReturn(stateTree); - when(stateTree.getNodeById(Mockito.anyInt())).thenReturn(stateNode); - when(session.getUIById(uiId)).thenReturn(ui); - } - - @Test - public void doHandleXhrFilePost_outputStreamGetterThrows_responseStatusIs500() - throws IOException { - Mockito.doThrow(RuntimeException.class).when(streamVariable) - .getOutputStream(); - - handler.doHandleXhrFilePost(session, request, response, streamReceiver, - stateNode, 1); - - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - @Test - public void doHandleXhrFilePost_outputStreamThrowsOnWrite_responseStatusIs500() - throws IOException { - - Mockito.doThrow(RuntimeException.class).when(outputStream) - .write(Mockito.any(), Mockito.anyInt(), Mockito.anyInt()); - - handler.doHandleXhrFilePost(session, request, response, streamReceiver, - stateNode, 1); - - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - @Test - public void doHandleXhrFilePost_happyPath_setContentTypeNoExplicitSetStatus() - throws IOException { - handler.doHandleXhrFilePost(session, request, response, streamReceiver, - stateNode, 1); - - Mockito.verify(response).setContentType( - ApplicationConstants.CONTENT_TYPE_TEXT_HTML_UTF_8); - Mockito.verify(response, Mockito.times(0)).setStatus(Mockito.anyInt()); - } - - @Test - public void doHandleMultipartFileUpload_noPart_uploadFailed_responseStatusIs500_getContentLengthLongCalled() - throws IOException { - - handler.doHandleMultipartFileUpload(session, request, response, - streamReceiver, stateNode); - - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - Assert.assertTrue(isGetContentLengthLongCalled); - } - - @Test - public void doHandleMultipartFileUpload_hasParts_uploadFailed_responseStatusIs500() - throws IOException { - contentType = "multipart/form-data; boundary=----WebKitFormBoundary7NsWHeCJVZNwi6ll"; - inputStream = createInputStream( - "------WebKitFormBoundary7NsWHeCJVZNwi6ll\n" - + "Content-Disposition: form-data; name=\"file\"; filename=\"EBookJP.txt\"\n" - + "Content-Type: text/plain\n" + "\n" + "\n" - + "------WebKitFormBoundary7NsWHeCJVZNwi6ll--"); - Mockito.doThrow(RuntimeException.class).when(outputStream) - .write(Mockito.any(), Mockito.anyInt(), Mockito.anyInt()); - contentLength = "99"; - - parts = new ArrayList<>(); - parts.add(createPart(createInputStream("foobar"), "text/plain", - "EBookJP.txt", 6)); - - handler.doHandleMultipartFileUpload(session, request, response, - streamReceiver, stateNode); - - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - /** - * Tests whether we get infinite loop if InputStream is already read - * (#10096) - */ - @Test - public void exceptionIsThrownOnUnexpectedEnd() throws IOException { - contentType = "multipart/form-data; boundary=----WebKitFormBoundary7NsWHeCJVZNwi6ll"; - inputStream = createInputStream( - "------WebKitFormBoundary7NsWHeCJVZNwi6ll\n" - + "Content-Disposition: form-data; name=\"file\"; filename=\"EBookJP.txt\"\n" - + "Content-Type: text/plain\n" + "\n" + "\n" - + "------WebKitFormBoundary7NsWHeCJVZNwi6ll--"); - contentLength = "99"; - - handler.doHandleMultipartFileUpload(session, request, response, null, - null); - - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - @Test - public void responseIsSentOnCorrectSecurityKey() throws IOException { - handler.handleRequest(session, request, response, streamReceiver, - String.valueOf(uiId), expectedSecurityKey); - - Mockito.verify(responseOutput).close(); - } - - @Test - public void responseIsNotSentOnIncorrectSecurityKey() throws IOException { - when(streamReceiver.getId()).thenReturn("another key expected"); - - handler.handleRequest(session, request, response, streamReceiver, - String.valueOf(uiId), expectedSecurityKey); - - Mockito.verifyNoInteractions(responseOutput); - } - - @Test - public void responseIsNotSentOnMissingSecurityKey() throws IOException { - when(streamReceiver.getId()).thenReturn(null); - - handler.handleRequest(session, request, response, streamReceiver, - String.valueOf(uiId), expectedSecurityKey); - - Mockito.verifyNoInteractions(responseOutput); - } - - @Test // Vaadin Spring #381 - public void partsAreUsedDirectlyIfPresentWithoutParsingInput() - throws IOException { - contentType = "multipart/form-data; boundary=----WebKitFormBoundary7NsWHeCJVZNwi6ll"; - inputStream = createInputStream( - "------WebKitFormBoundary7NsWHeCJVZNwi6ll\n" - + "Content-Disposition: form-data; name=\"file\"; filename=\"EBookJP.txt\"\n" - + "Content-Type: text/plain\n" + "\n" + "\n" - + "------WebKitFormBoundary7NsWHeCJVZNwi6ll--"); - outputStream = new ByteArrayOutputStream(); - contentLength = "99"; - final String fileName = "EBookJP.txt"; - final String contentType = "text/plain"; - - parts = new ArrayList<>(); - parts.add(createPart(createInputStream("foobar"), contentType, fileName, - 6)); - - handler.handleRequest(session, request, response, streamReceiver, - String.valueOf(uiId), expectedSecurityKey); - - Mockito.verify(responseOutput).close(); - ArgumentCaptor endEventArgumentCaptor = ArgumentCaptor - .forClass(StreamVariable.StreamingEndEvent.class); - Mockito.verify(streamVariable) - .streamingFinished(endEventArgumentCaptor.capture()); - Assert.assertEquals("foobar", new String( - ((ByteArrayOutputStream) outputStream).toByteArray())); - Assert.assertEquals(fileName, - endEventArgumentCaptor.getValue().getFileName()); - Assert.assertEquals(contentType, - endEventArgumentCaptor.getValue().getMimeType()); - - Mockito.verify(response).setContentType( - ApplicationConstants.CONTENT_TYPE_TEXT_HTML_UTF_8); - Mockito.verify(response, Mockito.times(0)).setStatus(Mockito.anyInt()); - } - - @Test - public void handleFileUploadValidationAndData_inputStreamThrowsIOException_exceptionIsNotRethrown_exceptionIsNotHandlerByErrorHandler() - throws UploadException { - InputStream inputStream = new InputStream() { - - @Override - public int read() throws IOException { - throw new IOException(); - } - }; - handler.handleFileUploadValidationAndData(session, inputStream, - streamReceiver, null, null, 0, stateNode); - - Mockito.verifyNoInteractions(errorHandler); - Mockito.verify(streamVariable).streamingFailed(Mockito.any()); - } - - @Test - public void handleFileUploadValidationAndData_inputStreamThrowsIOExceptionOnClose_exceptionIsNotRethrown_exceptionIsNotHandlerByErrorHandler() - throws UploadException { - InputStream inputStream = new InputStream() { - @Override - public int read() { - return -1; - } - - @Override - public void close() throws IOException { - throw new IOException(); - } - }; - handler.handleFileUploadValidationAndData(session, inputStream, - streamReceiver, null, null, 0, stateNode); - - Mockito.verifyNoInteractions(errorHandler); - } - - @Test - public void doHandleMultipartFileUpload_IOExceptionIsThrown_exceptionIsNotRethrown_exceptionIsNotHandlerByErrorHandler() - throws IOException, ServletException { - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.doThrow(IOException.class).when(request).getParts(); - handler.doHandleMultipartFileUpload(session, request, response, - streamReceiver, stateNode); - Mockito.verifyNoInteractions(errorHandler); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamRequestHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamRequestHandlerTest.java deleted file mode 100644 index 5281c22cac7..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamRequestHandlerTest.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.vaadin.flow.server.communication; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletOutputStream; - -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.StreamResource; -import com.vaadin.flow.server.StreamResourceRegistry; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; -import com.vaadin.tests.util.MockUI; - -import static com.vaadin.flow.server.communication.StreamRequestHandler.DYN_RES_PREFIX; - -@NotThreadSafe -public class StreamRequestHandlerTest { - - private StreamRequestHandler handler = new StreamRequestHandler(); - private MockVaadinSession session; - private VaadinServletRequest request; - private VaadinResponse response; - private StreamResourceRegistry streamResourceRegistry; - private UI ui; - - @Before - public void setUp() throws ServletException, ServiceException { - VaadinService service = new MockVaadinServletService(); - - session = new AlwaysLockedVaadinSession(service) { - @Override - public StreamResourceRegistry getResourceRegistry() { - return streamResourceRegistry; - } - }; - streamResourceRegistry = new StreamResourceRegistry(session); - request = Mockito.mock(VaadinServletRequest.class); - ServletContext servletContext = Mockito.mock(ServletContext.class); - Mockito.when(servletContext.getMimeType(Mockito.anyString())) - .thenReturn(null); - Mockito.when(request.getServletContext()).thenReturn(servletContext); - response = Mockito.mock(VaadinResponse.class); - ui = new MockUI(); - UI.setCurrent(ui); - } - - @After - public void cleanup() { - CurrentInstance.clearAll(); - } - - @Test - public void streamResourceNameEndsWithPluses_streamFactory_resourceIsStreamed() - throws IOException { - testStreamResourceInputStreamFactory("end with multiple pluses", - "readme++.md"); - } - - @Test - public void streamResourceNameEndsWithPluses_resourceWriter_resourceIsStreamed() - throws IOException { - testStreamResourceStreamResourceWriter("end with multiple pluses", - "readme++.md"); - } - - @Test - public void streamResourceNameContainsSpaceEndsWithPluses_streamFactory_resourceIsStreamed() - throws IOException { - testStreamResourceInputStreamFactory( - "end with space and multiple pluses", "readme ++.md"); - } - - @Test - public void streamResourceNameContainsSpaceEndsWithPluses_resourceWriter_resourceIsStreamed() - throws IOException { - testStreamResourceStreamResourceWriter( - "end with space and multiple pluses", "readme ++.md"); - } - - @Test - public void streamResourceNameEndsInPlus_streamFactory_resourceIsStreamed() - throws IOException { - testStreamResourceInputStreamFactory("end in plus", "readme+.md"); - } - - @Test - public void streamResourceNameEndsInPlus_resourceWriter_resourceIsStreamed() - throws IOException { - testStreamResourceStreamResourceWriter("end in plus", "readme+.md"); - } - - @Test - public void streamResourceNameContainsPlus_streamFactory_resourceIsStreamed() - throws IOException { - testStreamResourceInputStreamFactory("plus in middle", - "readme+mine.md"); - } - - @Test - public void streamResourceNameContainsPlus_resourceWriter_resourceIsStreamed() - throws IOException { - testStreamResourceStreamResourceWriter("plus in middle", - "readme+mine.md"); - } - - @Test - public void streamResourceNameContainsPlusAndSpaces_streamFactory_resourceIsStreamed() - throws IOException { - testStreamResourceInputStreamFactory("plus surrounded by spaces", - "readme + mine.md"); - } - - @Test - public void streamResourceNameContainsPlusAndSpaces_resourceWriter_resourceIsStreamed() - throws IOException { - testStreamResourceStreamResourceWriter("plus surrounded by spaces", - "readme + mine.md"); - } - - private void testStreamResourceInputStreamFactory(String testString, - String fileName) throws IOException { - - final byte[] testBytes = testString.getBytes(); - StreamResource res = new StreamResource(fileName, - () -> new ByteArrayInputStream(testBytes)); - - streamResourceRegistry.registerResource(res); - - ServletOutputStream outputStream = Mockito - .mock(ServletOutputStream.class); - Mockito.when(response.getOutputStream()).thenReturn(outputStream); - Mockito.when(request.getPathInfo()) - .thenReturn(String.format("/%s%s/%s/%s", DYN_RES_PREFIX, - ui.getId().orElse("-1"), res.getId(), res.getName())); - - handler.handleRequest(session, request, response); - - Mockito.verify(response).getOutputStream(); - - ArgumentCaptor argument = ArgumentCaptor.forClass(byte[].class); - Mockito.verify(outputStream).write(argument.capture(), Mockito.anyInt(), - Mockito.anyInt()); - - byte[] buf = new byte[1024]; - for (int i = 0; i < testBytes.length; i++) { - buf[i] = testBytes[i]; - } - Assert.assertArrayEquals("Output differed from expected", buf, - argument.getValue()); - Mockito.verify(response).setCacheTime(Mockito.anyLong()); - Mockito.verify(response).setContentType("application/octet-stream"); - } - - private void testStreamResourceStreamResourceWriter(String testString, - String fileName) throws IOException { - - final byte[] testBytes = testString.getBytes(); - StreamResource res = new StreamResource(fileName, - (stream, session) -> stream.write(testBytes)); - - streamResourceRegistry.registerResource(res); - - ServletOutputStream outputStream = Mockito - .mock(ServletOutputStream.class); - Mockito.when(response.getOutputStream()).thenReturn(outputStream); - Mockito.when(request.getPathInfo()) - .thenReturn(String.format("/%s%s/%s/%s", DYN_RES_PREFIX, - ui.getId().orElse("-1"), res.getId(), res.getName())); - - handler.handleRequest(session, request, response); - - Mockito.verify(response).getOutputStream(); - - ArgumentCaptor argument = ArgumentCaptor.forClass(byte[].class); - Mockito.verify(outputStream).write(argument.capture()); - - Assert.assertArrayEquals("Output differed from expected", testBytes, - argument.getValue()); - Mockito.verify(response).setCacheTime(Mockito.anyLong()); - Mockito.verify(response).setContentType("application/octet-stream"); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamResourceHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamResourceHandlerTest.java deleted file mode 100644 index 6a8ef714744..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/StreamResourceHandlerTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.server.HttpStatusCode; -import com.vaadin.flow.server.InputStreamFactory; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.StreamResource; -import com.vaadin.flow.server.StreamResourceWriter; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinServletResponse; -import com.vaadin.tests.util.AlwaysLockedVaadinSession; - -public class StreamResourceHandlerTest { - - private StreamResourceHandler handler = new StreamResourceHandler(); - private MockVaadinSession session; - private VaadinServletRequest request; - private VaadinServletResponse response; - - @Before - public void setUp() throws ServletException, ServiceException { - VaadinService service = new MockVaadinServletService(); - - session = new AlwaysLockedVaadinSession(service); - request = Mockito.mock(VaadinServletRequest.class); - ServletContext context = Mockito.mock(ServletContext.class); - Mockito.when(request.getServletContext()).thenReturn(context); - response = Mockito.mock(VaadinServletResponse.class); - } - - @Test - public void inputStreamFactoryThrowsException_responseStatusIs500() - throws IOException { - StreamResource res = new StreamResource("readme.md", - (InputStreamFactory) () -> { - throw new RuntimeException("Simulated"); - }); - try { - handler.handleRequest(session, request, response, res); - } catch (RuntimeException ignore) { - // Ignore exception, it's expected. We need to check the status - } - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - @Test - public void inputStreamResourceWriterThrows_responseStatusIs500() - throws IOException { - StreamResource res = new StreamResource("readme.md", - (StreamResourceWriter) (stream, session) -> { - throw new RuntimeException("Simulated"); - }); - try { - handler.handleRequest(session, request, response, res); - } catch (RuntimeException ignore) { - // Ignore exception, it's expected. We need to check the status - } - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - @Test - public void inputStreamResourceWriterIsNull_responseStatusIs500() - throws IOException { - @SuppressWarnings("serial") - StreamResource res = new StreamResource("readme.md", - () -> new ByteArrayInputStream(new byte[0])) { - @Override - public StreamResourceWriter getWriter() { - return null; - } - }; - try { - handler.handleRequest(session, request, response, res); - } catch (IOException ignore) { - // Ignore exception, it's expected. We need to check the status - } - Mockito.verify(response) - .setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()); - } - - @Test - public void inputStreamResourceHasHeader_headerIsWritten() - throws IOException { - StreamResource res = new StreamResource("readme.md", - () -> new ByteArrayInputStream(new byte[0])); - - res.setHeader("foo", "bar"); - - handler.handleRequest(session, request, response, res); - - Mockito.verify(response).setHeader("foo", "bar"); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/UidlRequestHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/UidlRequestHandlerTest.java deleted file mode 100644 index 825bcc27f16..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/UidlRequestHandlerTest.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.communication; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.StringWriter; -import java.util.Collections; -import java.util.Properties; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.internal.JavaScriptBootstrapUI; -import com.vaadin.flow.server.DefaultDeploymentConfiguration; -import com.vaadin.flow.server.HandlerHelper.RequestType; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import com.vaadin.flow.shared.ApplicationConstants; - -import elemental.json.JsonObject; -import elemental.json.impl.JsonUtil; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -public class UidlRequestHandlerTest { - - private VaadinRequest request; - private VaadinResponse response; - private OutputStream outputStream; - - private UidlRequestHandler handler; - - @Before - public void setup() throws IOException { - request = Mockito.mock(VaadinRequest.class); - response = Mockito.mock(VaadinResponse.class); - outputStream = Mockito.mock(OutputStream.class); - Mockito.when(response.getOutputStream()).thenReturn(outputStream); - - handler = new UidlRequestHandler(); - } - - @Test - public void writeSessionExpired() throws Exception { - ApplicationConfiguration config = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(config.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - Mockito.when(config.getBuildFolder()).thenReturn("."); - VaadinContext context = new MockVaadinContext(); - Mockito.when(config.getContext()).thenReturn(context); - VaadinService service = new VaadinServletService(null, - new DefaultDeploymentConfiguration(config, getClass(), - new Properties())); - when(request.getService()).thenReturn(service); - - when(request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER)) - .thenReturn(RequestType.UIDL.getIdentifier()); - - boolean result = handler.handleSessionExpired(request, response); - Assert.assertTrue("Result should be true", result); - - String responseContent = CommunicationUtil - .getStringWhenWriteBytesOffsetLength(outputStream); - - // response shouldn't contain async - Assert.assertEquals("Invalid response", - "for(;;);[{\"meta\":{\"sessionExpired\":true}}]", - responseContent); - } - - @Test - public void writeSessionExpired_whenUINotFound() throws IOException { - - VaadinService service = mock(VaadinService.class); - VaadinSession session = mock(VaadinSession.class); - when(session.getService()).thenReturn(service); - - when(service.findUI(request)).thenReturn(null); - - boolean result = handler.synchronizedHandleRequest(session, request, - response); - Assert.assertTrue("Result should be true", result); - - String responseContent = CommunicationUtil - .getStringWhenWriteString(outputStream); - - // response shouldn't contain async - Assert.assertEquals("Invalid response", - "for(;;);[{\"meta\":{\"sessionExpired\":true}}]", - responseContent); - } - - @Test - public void should_not_modifyUidl_when_MPR_nonJavaScriptBootstrapUI() - throws Exception { - JavaScriptBootstrapUI ui = null; - - UidlRequestHandler handler = spy(new UidlRequestHandler()); - StringWriter writer = new StringWriter(); - - JsonObject uidl = generateUidl(true, true); - doReturn(uidl).when(handler).createUidl(ui, false); - - handler.writeUidl(ui, writer, false); - - String out = writer.toString(); - - assertTrue(out.startsWith("for(;;);[{")); - assertTrue(out.endsWith("}]")); - - uidl = JsonUtil.parse(out.substring(9, out.length() - 1)); - String v7Uidl = uidl.getArray("execute").getArray(2).getString(1); - - assertTrue(v7Uidl.contains("http://localhost:9998/#!away")); - assertTrue(v7Uidl.contains("window.location.hash = '!away';")); - - assertEquals("setTimeout(() => window.history.pushState(null, '', $0))", - uidl.getArray("execute").getArray(1).getString(1)); - } - - @Test - public void should_modifyUidl_when_MPR_JavaScriptBootstrapUI() - throws Exception { - JavaScriptBootstrapUI ui = mock(JavaScriptBootstrapUI.class); - - UidlRequestHandler handler = spy(new UidlRequestHandler()); - StringWriter writer = new StringWriter(); - - JsonObject uidl = generateUidl(true, true); - doReturn(uidl).when(handler).createUidl(ui, false); - - handler.writeUidl(ui, writer, false); - - String out = writer.toString(); - uidl = JsonUtil.parse(out.substring(9, out.length() - 1)); - - String v7Uidl = uidl.getArray("execute").getArray(2).getString(1); - assertFalse(v7Uidl.contains("http://localhost:9998/#!away")); - assertTrue(v7Uidl.contains("http://localhost:9998/")); - assertFalse(v7Uidl.contains("window.location.hash = '!away';")); - } - - @Test - public void should_changeURL_when_v7LocationProvided() throws Exception { - JavaScriptBootstrapUI ui = mock(JavaScriptBootstrapUI.class); - - UidlRequestHandler handler = spy(new UidlRequestHandler()); - StringWriter writer = new StringWriter(); - - JsonObject uidl = generateUidl(true, true); - doReturn(uidl).when(handler).createUidl(ui, false); - - handler.writeUidl(ui, writer, false); - - String out = writer.toString(); - uidl = JsonUtil.parse(out.substring(9, out.length() - 1)); - - assertEquals( - "setTimeout(() => history.pushState(null, null, 'http://localhost:9998/#!away'));", - uidl.getArray("execute").getArray(1).getString(1)); - } - - @Test - public void should_updateHash_when_v7LocationNotProvided() - throws Exception { - JavaScriptBootstrapUI ui = mock(JavaScriptBootstrapUI.class); - - UidlRequestHandler handler = spy(new UidlRequestHandler()); - StringWriter writer = new StringWriter(); - - JsonObject uidl = generateUidl(false, true); - doReturn(uidl).when(handler).createUidl(ui, false); - - handler.writeUidl(ui, writer, false); - - String out = writer.toString(); - uidl = JsonUtil.parse(out.substring(9, out.length() - 1)); - - assertEquals( - "setTimeout(() => history.pushState(null, null, location.pathname + location.search + '#!away'));", - uidl.getArray("execute").getArray(1).getString(1)); - } - - @Test - public void should_not_modify_non_MPR_Uidl() throws Exception { - JavaScriptBootstrapUI ui = mock(JavaScriptBootstrapUI.class); - - UidlRequestHandler handler = spy(new UidlRequestHandler()); - StringWriter writer = new StringWriter(); - - JsonObject uidl = generateUidl(true, true); - uidl.getArray("execute").getArray(2).remove(1); - - doReturn(uidl).when(handler).createUidl(ui, false); - - handler.writeUidl(ui, writer, false); - - String expected = uidl.toJson(); - - String out = writer.toString(); - uidl = JsonUtil.parse(out.substring(9, out.length() - 1)); - - String actual = uidl.toJson(); - - assertEquals(expected, actual); - } - - @Test - public void should_not_update_browser_history_if_no_hash_in_location() - throws Exception { - JavaScriptBootstrapUI ui = mock(JavaScriptBootstrapUI.class); - - UidlRequestHandler handler = spy(new UidlRequestHandler()); - StringWriter writer = new StringWriter(); - - JsonObject uidl = getUidlWithNoHashInLocation(); - - doReturn(uidl).when(handler).createUidl(ui, false); - - handler.writeUidl(ui, writer, false); - - String out = writer.toString(); - Assert.assertFalse(out.contains("history.pushState")); - } - - private JsonObject generateUidl(boolean withLocation, boolean withHash) { - - // @formatter:off - JsonObject uidl = JsonUtil.parse( - "{" + - " \"syncId\": 3," + - " \"clientId\": 3," + - " \"changes\": []," + - " \"execute\": [" + - " [\"\", \"document.title = $0\"]," + - " [\"\", \"setTimeout(() => window.history.pushState(null, '', $0))\"]," + - " [[0, 16], \"___PLACE_FOR_V7_UIDL___\", \"$0.firstElementChild.setResponse($1)\"]," + - " [1,null,[0, 16], \"return (function() { this.$server['}p']($0, true, $1)}).apply($2)\"]" + - " ]," + - " \"timings\": []" + - "}"); - - String v7String = - "\"syncId\": 2," + - "\"clientId\": 2," + - "\"changes\": [" + - " [],[\"___PLACE_FOR_LOCATION_CHANGE___\"]" + - "]," + - "\"state\": {" + - "}," + - "\"types\": {" + - "}," + - "\"hierarchy\": {" + - "}," + - "\"rpc\": [" + - " [],[" + - " \"11\"," + - " \"com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc\"," + - " \"executeJavaScript\", [ \"___PLACE_FOR_HASH_RPC___\" ]" + - " ],[" + - " \"12\"," + - " \"com.example.FooRpc\"," + - " \"barMethod\", [{}, {}]" + - " ],[]" + - "]," + - "\"meta\": {}, \"resources\": {},\"typeMappings\": {},\"typeInheritanceMap\": {}, \"timings\": []"; - - String locationChange = - "\"change\", {\"pid\": \"0\"}, [\"0\", {\"id\": \"0\", \"location\": \"http://localhost:9998/#!away\"}]"; - - String hashRpc = - "window.location.hash = '!away';"; - - // @formatter:on - - if (withLocation) { - v7String = v7String.replace("\"___PLACE_FOR_LOCATION_CHANGE___\"", - locationChange); - } - if (withHash) { - v7String = v7String.replace("___PLACE_FOR_HASH_RPC___", hashRpc); - } - - uidl.getArray("execute").getArray(2).set(1, v7String); - return uidl; - } - - private JsonObject getUidlWithNoHashInLocation() { - // @formatter:off - return JsonUtil.parse( - "{" + - " \"syncId\": 3," + - " \"clientId\": 3," + - " \"changes\": []," + - " \"execute\": [" + - " [" + - " [" + - " 0," + - " 9" + - " ]," + - " '\"syncId\": 1, \"clientId\": 0, \"changes\" : [[\"change\",{\"pid\":\"0\"},[\"0\",{\"id\":\"0\",\"location\":\"http://localhost:8080/\",\"v\":{\"action\":\"\"}},[\"actions\",{}]]]], \"state\":{\"1\":{\"componentSettings\":[]}}, \"types\":{\"0\":\"0\",\"1\":\"2\"}, \"hierarchy\":{\"0\":[\"1\"]}, \"rpc\" : [], \"meta\" : {\"async\":true}, \"resources\" : {}, \"timings\":[113, 113]'," + - " \"ROOT\"" + - " ]" + - " ]," + - " \"timings\": [" + - " 20880," + - " 18181" + - " ]" + - "}" - ); - // @formatter:on - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/UidlWriterTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/UidlWriterTest.java deleted file mode 100644 index 1898ffc518e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/UidlWriterTest.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import jakarta.servlet.http.HttpServletRequest; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.StyleSheet; -import com.vaadin.flow.component.internal.PendingJavaScriptInvocation; -import com.vaadin.flow.component.internal.UIInternals.JavaScriptInvocation; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.internal.JsonUtils; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RoutePathProvider; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.BootstrapHandlerTest; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.MockVaadinContext.RoutePathProviderImpl; -import com.vaadin.flow.server.VaadinServletContext; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.flow.shared.ui.Dependency; -import com.vaadin.flow.shared.ui.LoadMode; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; - -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@NotThreadSafe -public class UidlWriterTest { - private static final String CSS_STYLE_NAME = Dependency.Type.STYLESHEET - .name(); - private MockServletServiceSessionSetup mocks; - - @JavaScript("UI-parent-JAVASCRIPT") - private static class ParentUI extends UI { - } - - @JavaScript("UI-JAVASCRIPT") - private static class TestUI extends ParentUI { - } - - @Tag("div") - @JavaScript("super-JAVASCRIPT") - @StyleSheet("super-STYLESHEET") - public static class SuperComponent extends Component { - } - - public static class EmptyClassWithInterface extends SuperComponent - implements AnotherComponentInterface { - } - - @JavaScript("JAVASCRIPT") - @StyleSheet("STYLESHEET") - public static class ActualComponent extends EmptyClassWithInterface - implements ComponentInterface { - } - - @JavaScript("child1-JAVASCRIPT") - @JavaScript("child2-JAVASCRIPT") - @StyleSheet("child1-STYLESHEET") - @StyleSheet("child2-STYLESHEET") - public static class ChildComponent extends ActualComponent - implements ChildComponentInterface2 { - } - - @JavaScript("interface-JAVASCRIPT") - @StyleSheet("interface-STYLESHEET") - public interface ComponentInterface { - } - - @JavaScript("anotherinterface-JAVASCRIPT") - @StyleSheet("anotherinterface-STYLESHEET") - public interface AnotherComponentInterface { - } - - @JavaScript("childinterface1-JAVASCRIPT") - @StyleSheet("childinterface1-STYLESHEET") - public interface ChildComponentInterface1 { - } - - @JavaScript("childinterface2-JAVASCRIPT") - @StyleSheet("childinterface2-STYLESHEET") - public interface ChildComponentInterface2 extends ChildComponentInterface1 { - } - - @Tag("test") - @JavaScript(value = "lazy.js", loadMode = LoadMode.LAZY) - @StyleSheet(value = "lazy.css", loadMode = LoadMode.LAZY) - @JavaScript(value = "inline.js", loadMode = LoadMode.INLINE) - @StyleSheet(value = "inline.css", loadMode = LoadMode.INLINE) - @JavaScript("eager.js") - @StyleSheet("eager.css") - public static class ComponentWithAllDependencyTypes extends Component { - } - - @Tag("base") - @Route(value = "", layout = ParentClass.class) - public static class BaseClass extends Component { - } - - @Tag("parent") - @ParentLayout(SuperParentClass.class) - public static class ParentClass extends Component implements RouterLayout { - } - - @Tag("super-parent") - public static class SuperParentClass extends Component - implements RouterLayout { - } - - @After - public void tearDown() { - if (mocks != null) { - mocks.cleanup(); - } - } - - @Test - public void testEncodeExecuteJavaScript_npmMode() { - Element element = ElementFactory.createDiv(); - - JavaScriptInvocation invocation1 = new JavaScriptInvocation( - "$0.focus()", element); - JavaScriptInvocation invocation2 = new JavaScriptInvocation( - "console.log($0, $1)", "Lives remaining:", Integer.valueOf(3)); - List executeJavaScriptList = Stream - .of(invocation1, invocation2) - .map(invocation -> new PendingJavaScriptInvocation( - element.getNode(), invocation)) - .collect(Collectors.toList()); - - JsonArray json = UidlWriter - .encodeExecuteJavaScriptList(executeJavaScriptList); - - JsonArray expectedJson = JsonUtils.createArray(JsonUtils.createArray( - // Null since element is not attached - Json.createNull(), Json.create("$0.focus()")), - JsonUtils.createArray(Json.create("Lives remaining:"), - Json.create(3), Json.create("console.log($0, $1)"))); - - assertTrue(JsonUtils.jsonEquals(expectedJson, json)); - } - - @Test - public void componentDependencies_npmMode() throws Exception { - UI ui = initializeUIForDependenciesTest(new TestUI()); - UidlWriter uidlWriter = new UidlWriter(); - addInitialComponentDependencies(ui, uidlWriter); - - // no dependencies should be resent in next response - JsonObject response = uidlWriter.createUidl(ui, false); - assertFalse(response.hasKey(LoadMode.EAGER.name())); - assertFalse(response.hasKey(LoadMode.INLINE.name())); - assertFalse(response.hasKey(LoadMode.LAZY.name())); - } - - @Test - public void testComponentInterfaceDependencies_npmMode() throws Exception { - UI ui = initializeUIForDependenciesTest(new TestUI()); - UidlWriter uidlWriter = new UidlWriter(); - - addInitialComponentDependencies(ui, uidlWriter); - - // test that dependencies only from new child interfaces are added - ui.add(new ActualComponent(), new SuperComponent(), - new ChildComponent()); - - JsonObject response = uidlWriter.createUidl(ui, false); - Map dependenciesMap = getDependenciesMap(response); - - assertEquals(4, dependenciesMap.size()); - assertDependency("childinterface1-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - assertDependency("childinterface2-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - assertDependency("child1-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - assertDependency("child2-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - } - - @Test - public void checkAllTypesOfDependencies_npmMode() throws Exception { - UI ui = initializeUIForDependenciesTest(new TestUI()); - UidlWriter uidlWriter = new UidlWriter(); - addInitialComponentDependencies(ui, uidlWriter); - - ui.add(new ComponentWithAllDependencyTypes()); - JsonObject response = uidlWriter.createUidl(ui, false); - Map> dependenciesMap = Stream - .of(LoadMode.values()) - .map(mode -> response.getArray(mode.name())) - .flatMap(JsonUtils:: stream) - .collect(Collectors.toMap( - jsonObject -> LoadMode.valueOf( - jsonObject.getString(Dependency.KEY_LOAD_MODE)), - Collections::singletonList, (list1, list2) -> { - List result = new ArrayList<>(list1); - result.addAll(list2); - return result; - })); - - assertThat( - "Dependencies with all types of load mode should be present in this response", - dependenciesMap.size(), is(LoadMode.values().length)); - - List eagerDependencies = dependenciesMap - .get(LoadMode.EAGER); - assertThat("Should have an eager dependency", eagerDependencies, - hasSize(1)); - assertThat("Eager dependencies should not have inline contents", - eagerDependencies.stream() - .filter(json -> json.hasKey(Dependency.KEY_CONTENTS)) - .collect(Collectors.toList()), - hasSize(0)); - - JsonObject eagerDependency = eagerDependencies.get(0); - assertEquals("eager.css", - eagerDependency.getString(Dependency.KEY_URL)); - assertEquals(Dependency.Type.STYLESHEET, Dependency.Type - .valueOf(eagerDependency.getString(Dependency.KEY_TYPE))); - - List lazyDependencies = dependenciesMap.get(LoadMode.LAZY); - JsonObject lazyDependency = lazyDependencies.get(0); - assertEquals("lazy.css", lazyDependency.getString(Dependency.KEY_URL)); - assertEquals(Dependency.Type.STYLESHEET, Dependency.Type - .valueOf(lazyDependency.getString(Dependency.KEY_TYPE))); - - List inlineDependencies = dependenciesMap - .get(LoadMode.INLINE); - assertInlineDependencies(inlineDependencies); - } - - @Test - public void resynchronizationRequested_responseFieldContainsResynchronize() - throws Exception { - UI ui = initializeUIForDependenciesTest(new TestUI()); - UidlWriter uidlWriter = new UidlWriter(); - - JsonObject response = uidlWriter.createUidl(ui, false, true); - assertTrue("Response contains resynchronize field", - response.hasKey(ApplicationConstants.RESYNCHRONIZE_ID)); - assertTrue("Response resynchronize field is set to true", - response.getBoolean(ApplicationConstants.RESYNCHRONIZE_ID)); - } - - private void assertInlineDependencies(List inlineDependencies) { - assertThat("Should have an inline dependency", inlineDependencies, - hasSize(1)); - assertThat("Eager dependencies should not have urls", - inlineDependencies.stream() - .filter(json -> json.hasKey(Dependency.KEY_URL)) - .collect(Collectors.toList()), - hasSize(0)); - - JsonObject inlineDependency = inlineDependencies.get(0); - - String url = inlineDependency.getString(Dependency.KEY_CONTENTS); - assertEquals("inline.css", url); - assertEquals(Dependency.Type.STYLESHEET, Dependency.Type - .valueOf(inlineDependency.getString(Dependency.KEY_TYPE))); - } - - private UI initializeUIForDependenciesTest(UI ui) throws Exception { - mocks = new MockServletServiceSessionSetup(); - - VaadinServletContext context = (VaadinServletContext) mocks.getService() - .getContext(); - Lookup lookup = context.getAttribute(Lookup.class); - Mockito.when(lookup.lookup(RoutePathProvider.class)) - .thenReturn(new RoutePathProviderImpl()); - - VaadinSession session = mocks.getSession(); - session.lock(); - ui.getInternals().setSession(session); - - RouteConfiguration routeConfiguration = RouteConfiguration - .forRegistry(ui.getInternals().getRouter().getRegistry()); - routeConfiguration.update(() -> { - routeConfiguration.getHandledRegistry().clean(); - routeConfiguration.setAnnotatedRoute(BaseClass.class); - }); - - for (String type : new String[] { "html", "js", "css" }) { - mocks.getServlet().addServletContextResource("inline." + type, - "inline." + type); - } - - HttpServletRequest servletRequestMock = mock(HttpServletRequest.class); - - VaadinServletRequest vaadinRequestMock = mock( - VaadinServletRequest.class); - - when(vaadinRequestMock.getHttpServletRequest()) - .thenReturn(servletRequestMock); - - ui.doInit(vaadinRequestMock, 1); - ui.getInternals().getRouter().initializeUI(ui, - BootstrapHandlerTest.requestToLocation(vaadinRequestMock)); - - return ui; - } - - private void addInitialComponentDependencies(UI ui, UidlWriter uidlWriter) { - ui.add(new ActualComponent()); - - JsonObject response = uidlWriter.createUidl(ui, false); - Map dependenciesMap = getDependenciesMap(response); - - assertEquals(4, dependenciesMap.size()); - - // UI parent first, then UI, then super component's dependencies, then - // the interfaces and then the component - assertDependency("super-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - - assertDependency("anotherinterface-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - - assertDependency("interface-" + CSS_STYLE_NAME, CSS_STYLE_NAME, - dependenciesMap); - - assertDependency(CSS_STYLE_NAME, CSS_STYLE_NAME, dependenciesMap); - } - - private Map getDependenciesMap(JsonObject response) { - return Stream.of(LoadMode.values()) - .map(mode -> response.getArray(mode.name())) - .flatMap(JsonUtils:: stream) - .collect(Collectors.toMap( - jsonObject -> jsonObject.getString(Dependency.KEY_URL), - Function.identity())); - } - - private void assertDependency(String url, String type, - Map dependenciesMap) { - JsonObject jsonValue = dependenciesMap.get(url); - assertNotNull( - "Expected dependencies map to have dependency with key=" + url, - jsonValue); - assertEquals(url, jsonValue.get(Dependency.KEY_URL).asString()); - assertEquals(type, jsonValue.get(Dependency.KEY_TYPE).asString()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/WebComponentBootstrapHandlerViteTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/WebComponentBootstrapHandlerViteTest.java deleted file mode 100644 index dc70fd62dc1..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/WebComponentBootstrapHandlerViteTest.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Collections; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.MockVaadinSession; -import com.vaadin.flow.server.PwaConfiguration; -import com.vaadin.flow.server.PwaIcon; -import com.vaadin.flow.server.PwaRegistry; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServlet; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.webcomponent.WebComponentConfigurationRegistry; -import com.vaadin.flow.shared.ApplicationConstants; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES; -import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_STATISTICS_JSON; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; - -public class WebComponentBootstrapHandlerViteTest { - - private static class TestWebComponentBootstrapHandler - extends WebComponentBootstrapHandler { - @Override - protected boolean canHandleRequest(VaadinRequest request) { - return true; - } - - @Override - protected String getServiceUrl(VaadinRequest request, - VaadinResponse response) { - return "/"; - } - } - - @Test - public void writeBootstrapPage_skipMetaAndStyleHeaderElements() - throws IOException { - WebComponentBootstrapHandler handler = new WebComponentBootstrapHandler(); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - - Element head = new Document("").normalise().head(); - Element meta = head.ownerDocument().createElement("meta"); - head.appendChild(meta); - meta.attr("http-equiv", "Content-Type"); - - Element style = head.ownerDocument().createElement("style"); - head.appendChild(style); - style.attr("type", "text/css"); - style.text("body {height:100vh;width:100vw;margin:0;}"); - - Element script = head.ownerDocument().createElement("script"); - head.appendChild(script); - script.text("var i=1;"); - - VaadinResponse response = getMockResponse(stream); - handler.writeBootstrapPage("", response, head, ""); - - String resultingScript = stream.toString(StandardCharsets.UTF_8.name()); - - MatcherAssert.assertThat(resultingScript, - CoreMatchers.containsString("var i=1;")); - MatcherAssert.assertThat(resultingScript, CoreMatchers.not(CoreMatchers - .containsString("body {height:100vh;width:100vw;margin:0;}"))); - MatcherAssert.assertThat(resultingScript, - CoreMatchers.not(CoreMatchers.containsString("http-equiv"))); - } - - @Test - public void writeBootstrapPage_scriptSrcHasNoDoubleQuotes_attributeIsTransferred() - throws IOException { - WebComponentBootstrapHandler handler = new WebComponentBootstrapHandler(); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - - Element head = new Document("").normalise().head(); - - Element script = head.ownerDocument().createElement("script"); - head.appendChild(script); - script.attr("src", "foo'bar%20%27?baz%22"); - - VaadinResponse response = getMockResponse(stream); - handler.writeBootstrapPage("", response, head, ""); - - String resultingScript = stream.toString(StandardCharsets.UTF_8.name()); - MatcherAssert.assertThat(resultingScript, - CoreMatchers.containsString("foo'bar%20%27?baz%22")); - } - - @Test(expected = IllegalStateException.class) - public void writeBootstrapPage_scriptSrcHasDoubleQuotes_throws() - throws IOException { - WebComponentBootstrapHandler handler = new WebComponentBootstrapHandler(); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - - Element head = new Document("").normalise().head(); - - Element script = head.ownerDocument().createElement("script"); - head.appendChild(script); - script.attr("src", "foo\""); - - VaadinResponse response = getMockResponse(stream); - handler.writeBootstrapPage("", response, head, ""); - } - - @Test - public void writeBootstrapPage_noPWA() - throws IOException, ServiceException { - TestWebComponentBootstrapHandler handler = new TestWebComponentBootstrapHandler(); - - PwaRegistry registry = Mockito.mock(PwaRegistry.class); - - PwaConfiguration conf = Mockito.mock(PwaConfiguration.class); - - Mockito.when(registry.getPwaConfiguration()).thenReturn(conf); - - Mockito.when(conf.isEnabled()).thenReturn(true); - - Mockito.when(conf.getManifestPath()).thenReturn("bar"); - - PwaIcon icon = Mockito.mock(PwaIcon.class); - Mockito.when(icon.asElement()).thenReturn(new Element("h1")); - - Mockito.when(registry.getHeaderIcons()) - .thenReturn(Collections.singletonList(icon)); - - VaadinServletService service = new MockVaadinServletService() { - @Override - protected PwaRegistry getPwaRegistry() { - return registry; - }; - }; - - initLookup(service); - - VaadinSession session = new MockVaadinSession(service); - session.lock(); - session.setConfiguration(service.getDeploymentConfiguration()); - MockDeploymentConfiguration config = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - config.setEnableDevServer(false); - - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(request.getServletPath()).thenReturn("/"); - VaadinResponse response = getMockResponse(null); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(stream); - - handler.synchronizedHandleRequest(session, request, response); - - String result = stream.toString(StandardCharsets.UTF_8.name()); - MatcherAssert.assertThat(result, - CoreMatchers.not(CoreMatchers.containsString("bar"))); - MatcherAssert.assertThat(result, - CoreMatchers.not(CoreMatchers.containsString("h1"))); - MatcherAssert.assertThat(result, - CoreMatchers.not(CoreMatchers.containsString("baz"))); - } - - @Test - public void writeBootstrapPage_devToolsDisabled() - throws IOException, ServiceException { - TestWebComponentBootstrapHandler handler = new TestWebComponentBootstrapHandler(); - VaadinServletService service = new MockVaadinServletService(); - initLookup(service); - - VaadinSession session = new MockVaadinSession(service); - session.lock(); - session.setConfiguration(service.getDeploymentConfiguration()); - MockDeploymentConfiguration config = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - config.setEnableDevServer(false); - - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(request.getServletPath()).thenReturn("/"); - VaadinResponse response = getMockResponse(null); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(stream); - - handler.synchronizedHandleRequest(session, request, response); - - String result = stream.toString(StandardCharsets.UTF_8.name()); - - int scriptIndex = result.indexOf("var hasScript = function(src)"); - Assert.assertTrue(scriptIndex >= 0); - - Assert.assertTrue(result.contains("\\\"devToolsEnabled\\\": false")); - } - - @Test - public void writeBootstrapPage_spepe() throws Exception { - WebComponentBootstrapHandler handler = new WebComponentBootstrapHandler(); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - - Element head = new Document("").normalise().head(); - - VaadinResponse response = getMockResponse(stream); - handler.writeBootstrapPage("", response, head, ""); - - String resultingScript = stream.toString(StandardCharsets.UTF_8.name()); - } - - @Test - public void canHandleRequest_hasNoWebComponentConfigPathIsWebComponentUI_returnsFalse() { - WebComponentBootstrapHandler handler = new WebComponentBootstrapHandler(); - - VaadinRequest request = mockRequest(false); - Assert.assertFalse(handler.canHandleRequest(request)); - } - - @Test - public void canHandleRequest_hasWebComponentConfigPathIsWebComponentUI_returnsTrue() { - WebComponentBootstrapHandler handler = new WebComponentBootstrapHandler(); - - VaadinRequest request = mockRequest(true); - Assert.assertTrue(handler.canHandleRequest(request)); - } - - @Ignore - @Test - public void writeBootstrapPage_withExportChunk() - throws IOException, ServiceException { - TestWebComponentBootstrapHandler handler = new TestWebComponentBootstrapHandler(); - VaadinServletService service = new MockVaadinServletService(); - - initLookup(service); - - VaadinSession session = new MockVaadinSession(service); - session.lock(); - session.setConfiguration(service.getDeploymentConfiguration()); - MockDeploymentConfiguration config = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - config.setEnableDevServer(false); - - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(request.getServletPath()).thenReturn("/"); - VaadinResponse response = getMockResponse(null); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(stream); - - handler.synchronizedHandleRequest(session, request, response); - - String result = stream.toString(StandardCharsets.UTF_8.name()); - Assert.assertTrue( - result.contains("VAADIN/build/vaadin-export-2222.cache.js")); - Assert.assertFalse( - result.contains("VAADIN/build/vaadin-bundle-1111.cache.js")); - } - - @Ignore - @Test - public void writeBootstrapPage_noExportChunk() - throws IOException, ServiceException { - TestWebComponentBootstrapHandler handler = new TestWebComponentBootstrapHandler(); - VaadinServletService service = new MockVaadinServletService(); - - initLookup(service); - - VaadinSession session = new MockVaadinSession(service); - session.lock(); - session.setConfiguration(service.getDeploymentConfiguration()); - MockDeploymentConfiguration config = (MockDeploymentConfiguration) service - .getDeploymentConfiguration(); - config.setApplicationOrSystemProperty(SERVLET_PARAMETER_STATISTICS_JSON, - VAADIN_SERVLET_RESOURCES + "config/stats_no_export.json"); - config.setEnableDevServer(false); - - VaadinServletRequest request = Mockito.mock(VaadinServletRequest.class); - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(request.getServletPath()).thenReturn("/"); - VaadinResponse response = getMockResponse(null); - - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - Mockito.when(response.getOutputStream()).thenReturn(stream); - - handler.synchronizedHandleRequest(session, request, response); - - // no "export" chunk, expect "bundle" in result instead - String result = stream.toString(StandardCharsets.UTF_8.name()); - Assert.assertTrue( - result.contains("VAADIN/build/vaadin-bundle-1111.cache.js")); - } - - private VaadinRequest mockRequest(boolean hasConfig) { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinService service = Mockito.mock(VaadinService.class); - VaadinRequest request = Mockito.mock(VaadinRequest.class); - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(service.getContext()).thenReturn(context); - - WebComponentConfigurationRegistry registry = Mockito - .mock(WebComponentConfigurationRegistry.class); - Mockito.when(context.getAttribute( - Mockito.eq(WebComponentConfigurationRegistry.class), - Mockito.any())).thenReturn(registry); - Mockito.when(registry.hasConfigurations()).thenReturn(hasConfig); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/web-component-ui.js"); - - return request; - } - - private void initLookup(VaadinServletService service) throws IOException { - VaadinContext context = service.getContext(); - Lookup lookup = Mockito.mock(Lookup.class); - context.setAttribute(Lookup.class, lookup); - - ResourceProvider provider = Mockito.mock(ResourceProvider.class); - - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(provider); - - Mockito.when(provider.getApplicationResource(Mockito.anyString())) - .thenAnswer(answer -> WebComponentBootstrapHandlerViteTest.class - .getClassLoader().getResource(answer.getArgument(0))); - - Mockito.when(provider.getClientResourceAsStream( - "META-INF/resources/" + ApplicationConstants.CLIENT_ENGINE_PATH - + "/compile.properties")) - .thenAnswer(invocation -> new ByteArrayInputStream( - "jsFile=foo".getBytes(StandardCharsets.UTF_8))); - } - - private VaadinResponse getMockResponse(ByteArrayOutputStream stream) - throws IOException { - VaadinResponse response = Mockito.mock(VaadinResponse.class); - VaadinService service = Mockito.mock(VaadinService.class); - VaadinContext context = Mockito.mock(VaadinContext.class); - Mockito.when(response.getOutputStream()).thenReturn(stream); - Mockito.when(response.getService()).thenReturn(service); - Mockito.when(service.getContext()).thenReturn(context); - Mockito.when(context.getAttribute( - eq(WebComponentConfigurationRegistry.class), any())).thenReturn( - Mockito.mock(WebComponentConfigurationRegistry.class)); - return response; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/WebComponentProviderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/WebComponentProviderTest.java deleted file mode 100644 index 54315b12c77..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/WebComponentProviderTest.java +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.communication; - -import jakarta.servlet.ServletContext; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.WebComponentExporterFactory.DefaultWebComponentExporterFactory; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.component.webcomponent.WebComponentConfiguration; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.DefaultDeploymentConfiguration; -import com.vaadin.flow.server.HttpStatusCode; -import com.vaadin.flow.server.MockInstantiator; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinRequest; -import com.vaadin.flow.server.VaadinResponse; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServletContext; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.server.webcomponent.WebComponentConfigurationRegistry; -import com.vaadin.flow.shared.communication.PushMode; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; - -@NotThreadSafe -public class WebComponentProviderTest { - - @Mock - VaadinSession session; - @Mock - VaadinServletRequest request; - @Mock - VaadinResponse response; - @Mock - VaadinServletService service; - @Mock - VaadinServletContext context; - @Mock - DeploymentConfiguration configuration; - - WebComponentProvider provider; - - WebComponentConfigurationRegistry registry; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - registry = setUpRegistry(); // same code as used for local variables in - // some tests - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(session.getService()).thenReturn(service); - Mockito.when(service.getContext()).thenReturn(context); - Mockito.when( - context.getAttribute(WebComponentConfigurationRegistry.class)) - .then(invocationOnMock -> registry); - Mockito.when(context.getAttribute( - eq(WebComponentConfigurationRegistry.class), any())) - .then(invocationOnMock -> registry); - Mockito.doAnswer( - invocationOnMock -> registry = (WebComponentConfigurationRegistry) invocationOnMock - .getArguments()[0]) - .when(context) - .setAttribute(any(WebComponentConfigurationRegistry.class)); - VaadinService.setCurrent(service); - Mockito.when(service.getInstantiator()) - .thenReturn(new MockInstantiator()); - Mockito.when(service.getDeploymentConfiguration()) - .thenReturn(configuration); - - VaadinServletService service = Mockito.mock(VaadinServletService.class); - Mockito.doCallRealMethod().when(service) - .getContextRootRelativePath(Mockito.any()); - - Mockito.doCallRealMethod().when(service) - .getContextRootRelativePath(Mockito.any()); - - provider = new WebComponentProvider(); - } - - @After - public void cleanUp() { - CurrentInstance.clearAll(); - } - - @Test - public void nonHandledPaths_handlerInformsNotHandled() throws IOException { - Mockito.when(request.getPathInfo()).thenReturn(null); - Assert.assertFalse("Provider shouldn't handle null path", - provider.canHandleRequest(request)); - - Mockito.when(request.getPathInfo()).thenReturn(""); - Assert.assertFalse("Provider shouldn't handle empty path", - provider.canHandleRequest(request)); - - Mockito.when(request.getPathInfo()).thenReturn("/home"); - Assert.assertFalse("Provider shouldn't handle non web-component path", - provider.canHandleRequest(request)); - } - - @Test - public void faultyTag_handlerInformsNotHandled() throws IOException { - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component" + "/extensionless-component"); - - Assert.assertFalse("Provider shouldn't handle path without extension", - provider.synchronizedHandleRequest(session, request, response)); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/component.js"); - - Assert.assertFalse( - "Provider shouldn't handle request for non-custom element name", - provider.synchronizedHandleRequest(session, request, response)); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/my-component.html"); - - Assert.assertFalse( - "Provider shouldn't handle html extensions in npm mode", - provider.synchronizedHandleRequest(session, request, response)); - } - - @Test - public void webComponentNotPresent_responseReturns404() throws IOException { - ServletContext servletContext = Mockito.mock(ServletContext.class); - - Mockito.when(request.getServletContext()).thenReturn(servletContext); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/my-component.js"); - Assert.assertTrue("Provider should handle web-component request", - provider.synchronizedHandleRequest(session, request, response)); - Mockito.verify(response).sendError(HttpStatusCode.NOT_FOUND.getCode(), - "No web component for my-component"); - } - - @Test - public void webComponentGenerator_responseGetsResult() throws IOException { - registry = setupConfigurations(MyComponentExporter.class); - - ByteArrayOutputStream out = Mockito.mock(ByteArrayOutputStream.class); - - DefaultDeploymentConfiguration configuration = Mockito - .mock(DefaultDeploymentConfiguration.class); - - Mockito.when(response.getOutputStream()).thenReturn(out); - Mockito.when(session.getConfiguration()).thenReturn(configuration); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/my-component.js"); - Assert.assertTrue("Provider should handle web-component request", - provider.synchronizedHandleRequest(session, request, response)); - - Mockito.verify(response).getOutputStream(); - Mockito.verify(out).write(Mockito.any()); - - } - - @Test - public void providesDifferentGeneratedHTMLForEachExportedComponent() - throws IOException { - ArgumentCaptor captor = ArgumentCaptor.forClass(byte[].class); - - registry = setupConfigurations(MyComponentExporter.class, - OtherComponentExporter.class); - - ByteArrayOutputStream out = Mockito.mock(ByteArrayOutputStream.class); - - DefaultDeploymentConfiguration configuration = Mockito - .mock(DefaultDeploymentConfiguration.class); - - Mockito.when(response.getOutputStream()).thenReturn(out); - Mockito.when(session.getConfiguration()).thenReturn(configuration); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/my-component.js"); - Assert.assertTrue("Provider should handle first web-component request", - provider.synchronizedHandleRequest(session, request, response)); - - Mockito.when(request.getPathInfo()) - .thenReturn("/web-component/other-component.js"); - Assert.assertTrue("Provider should handle second web-component request", - provider.synchronizedHandleRequest(session, request, response)); - - Mockito.verify(response, times(2)).getOutputStream(); - Mockito.verify(out, times(2)).write(captor.capture()); - - byte[] first = captor.getAllValues().get(0); - byte[] second = captor.getAllValues().get(1); - - Assert.assertNotEquals("Stream output should not match", first, second); - } - - @Test(expected = IllegalStateException.class) - public void setExporters_exportersHasVariousPushes_throws() { - WebComponentConfigurationRegistry registry = setupConfigurations( - ThemedComponentExporter.class, - AnotherPushComponentExporter.class); - } - - @Test - public void setExporters_exportersHasOnePush_pushIsSet() { - WebComponentConfigurationRegistry registry = setupConfigurations( - ThemedComponentExporter.class, MyComponentExporter.class); - Assert.assertTrue(registry.getEmbeddedApplicationAnnotation(Push.class) - .isPresent()); - } - - @Test - public void setExporters_exportersHasSamePushDeclarations_pushIsSet() { - WebComponentConfigurationRegistry registry = setupConfigurations( - ThemedComponentExporter.class, - SameThemedComponentExporter.class); - Assert.assertEquals(PushMode.AUTOMATIC, registry - .getEmbeddedApplicationAnnotation(Push.class).get().value()); - } - - @Test - public void canHandleRequest_hasNoWebComponentConfigPathIsWebComponentUI_returnsFalse() { - WebComponentProvider handler = new WebComponentProvider(); - - VaadinRequest request = mockRequest(false); - Assert.assertFalse(handler.canHandleRequest(request)); - } - - @Test - public void canHandleRequest_hasWebComponentConfigPathIsWebComponentUI_returnsTrue() { - WebComponentProvider handler = new WebComponentProvider(); - - VaadinRequest request = mockRequest(true); - Assert.assertTrue(handler.canHandleRequest(request)); - } - - private VaadinRequest mockRequest(boolean hasConfig) { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinService service = Mockito.mock(VaadinService.class); - VaadinRequest request = Mockito.mock(VaadinRequest.class); - Mockito.when(request.getService()).thenReturn(service); - Mockito.when(service.getContext()).thenReturn(context); - - WebComponentConfigurationRegistry registry = Mockito - .mock(WebComponentConfigurationRegistry.class); - Mockito.when(context.getAttribute( - Mockito.eq(WebComponentConfigurationRegistry.class), - Mockito.any())).thenReturn(registry); - Mockito.when(registry.hasConfigurations()).thenReturn(hasConfig); - - Mockito.when(request.getPathInfo()).thenReturn("/web-component/a-b.js"); - - return request; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @SafeVarargs - private final WebComponentConfigurationRegistry setupConfigurations( - Class>... exporters) { - WebComponentConfigurationRegistry registry = setUpRegistry(); - - final Set>> set = Stream - .of(exporters).collect(Collectors.toSet()); - - WebComponentExporter.WebComponentConfigurationFactory factory = new WebComponentExporter.WebComponentConfigurationFactory(); - - Set> configurations = new HashSet<>(); - for (Class> exporter : exporters) - configurations.add(factory.create( - new DefaultWebComponentExporterFactory(exporter).create())); - registry.setConfigurations(configurations); - - return registry; - } - - private WebComponentConfigurationRegistry setUpRegistry() { - return new WebComponentConfigurationRegistry() { - }; - } - - @Tag("my-component") - public static class MyComponent extends Component { - } - - public static class MyComponentExporter - extends WebComponentExporter { - - public MyComponentExporter() { - super("my-component"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - @Tag("another-component") - public static class OtherComponent extends Component { - } - - public static class OtherComponentExporter - extends WebComponentExporter { - - public OtherComponentExporter() { - super("other-component"); - } - - @Override - public void configureInstance(WebComponent webComponent, - OtherComponent component) { - - } - } - - @Push - public static class ThemedComponentExporter - extends WebComponentExporter { - public ThemedComponentExporter() { - super("foo"); - } - - @Override - public void configureInstance(WebComponent webComponent, - Component component) { - - } - } - - @Push(value = PushMode.AUTOMATIC) - public static class SameThemedComponentExporter - extends WebComponentExporter { - public SameThemedComponentExporter() { - super("foo"); - } - - @Override - public void configureInstance(WebComponent webComponent, - Component component) { - - } - } - - @Push(value = PushMode.DISABLED) - public static class AnotherPushComponentExporter - extends WebComponentExporter { - public AnotherPushComponentExporter() { - super("foo-bar"); - } - - @Override - public void configureInstance(WebComponent webComponent, - Component component) { - - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AbstractRpcInvocationHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AbstractRpcInvocationHandlerTest.java deleted file mode 100644 index 832e4f5f636..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AbstractRpcInvocationHandlerTest.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.util.Optional; -import java.util.function.Consumer; - -import com.vaadin.flow.component.PollEvent; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.dom.ElementUtil; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.Json; -import elemental.json.JsonObject; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.MockedStatic; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -public class AbstractRpcInvocationHandlerTest { - - private static class TestRpcInvocationHandler - extends AbstractRpcInvocationHandler { - - private StateNode node; - - @Override - public String getRpcType() { - return null; - } - - @Override - protected Optional handleNode(StateNode node, - JsonObject invocationJson) { - this.node = node; - return Optional.of(() -> { - }); - } - } - - private TestRpcInvocationHandler handler = new TestRpcInvocationHandler(); - - @Test - public void handleVisibleAndEnabledNode_nodeIsHandled() { - UI ui = new UI(); - - Element element = createRpcInvocationData(ui, null); - - Assert.assertSame(element.getNode(), handler.node); - } - - @Test - public void handleInactiveNode_nodeIsNotHandled() { - UI ui = new UI(); - - createRpcInvocationData(ui, elem -> { - elem.setVisible(false); - elem.getNode().updateActiveState(); - - }); - - Assert.assertNull(handler.node); - } - - @Test - public void handleInertNode_nodeIsNotHandled() { - UI ui = new UI(); - - createRpcInvocationData(ui, elem -> { - ElementUtil.setInert(elem, true); - ui.getInternals().getStateTree().collectDirtyNodes() - .forEach(stateNode -> stateNode.collectChanges(change -> { - })); - }); - - Assert.assertNull(handler.node); - } - - @Test - public void inertUI_passingNoPollingPayload_ignoresPollingInvocation() { - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createNonPollingRpcInvocationPayload(ui); - Optional runnable = handler.handle(ui, invocationJson); - - Assert.assertEquals(Optional.empty(), runnable); - } - - @Test - public void inertUIWithPollingInterval_passingLegitimatePollingPayload_doesNotIgnorePolling() { - - UI ui = createInertUI(); - - JsonObject invocationJson = createLegitimatePollingRpcInvocationPayload( - ui); - Optional runnable = handler.handle(ui, invocationJson); - Assert.assertEquals(Optional.empty(), runnable); - - ui.setPollInterval(0); - runnable = handler.handle(ui, invocationJson); - Assert.assertEquals(Optional.empty(), runnable); - - ui.setPollInterval(5000); - runnable = handler.handle(ui, invocationJson); - Assert.assertNotEquals(Optional.empty(), runnable); - } - - @Test - public void inertUIWithPollingInterval_passingIllegitimateKeysForPollingPayload_ignoresInvocation() { - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createIllegitimatePayloadKeysPollingRpcInvocationPayload( - ui); - Optional runnable = handler.handle(ui, invocationJson); - - Assert.assertEquals(Optional.empty(), runnable); - } - - @Test - public void inertUIWithPollingInterval_passingIllegitimateGreaterNumberOfKeysForPollingPayload_ignoresInvocation() { - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createIllegitimatePayloadWithGreaterSizePollingRpcInvocationPayload( - ui); - Optional runnable = handler.handle(ui, invocationJson); - - Assert.assertEquals(Optional.empty(), runnable); - } - - @Test - public void inertUIWithPollingInterval_passingIllegitimateSmallerNumberOfKeysForPollingPayload_ignoresInvocation() { - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createIllegitimatePayloadWithSmallerSizePollingRpcInvocationPayload( - ui); - Optional runnable = handler.handle(ui, invocationJson); - - Assert.assertEquals(Optional.empty(), runnable); - } - - @Test - public void inertUIWithPollingInterval_passingIllegitimateNoNodeKeyForPollingPayload_throwsAssertionError() { - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createIllegitimatePayloadNoNodeKeyForPollingRpcInvocationPayload(); - Assert.assertThrows(AssertionError.class, - () -> handler.handle(ui, invocationJson)); - } - - @Test - public void inertUIWithPollingInterval_passingIllegitimateNonRootNodeIdForPollingPayload_ignoresInvocation() { - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createIllegitimatePayloadWithNonRootNodePollingRpcInvocationPayload( - ui); - Optional runnable = handler.handle(ui, invocationJson); - - Assert.assertEquals(Optional.empty(), runnable); - } - - @Test - public void inertUIWithoutPollInterval_passingLegitimatePollingPayload_logsIgnoredPayloadInDebugLevel() { - - Logger logger = spy(Logger.class); - try (MockedStatic mockedLoggerFactory = mockStatic( - LoggerFactory.class)) { - mockedLoggerFactory - .when(() -> LoggerFactory.getLogger( - AbstractRpcInvocationHandler.class.getName())) - .thenReturn(logger); - - UI ui = createInertUI(); - JsonObject invocationJson = createLegitimatePollingRpcInvocationPayload( - ui); - handler.handle(ui, invocationJson); - - verify(logger, times(1)).warn(anyString()); - verify(logger, times(1)).debug(anyString(), (Object) any()); - } - } - - @Test - public void inertUIWithPollingInterval_passingIllegitimatePollingPayload_logsIgnoredPayloadInDebugLevel() { - - Logger logger = spy(Logger.class); - try (MockedStatic mockedLoggerFactory = mockStatic( - LoggerFactory.class)) { - mockedLoggerFactory - .when(() -> LoggerFactory.getLogger( - AbstractRpcInvocationHandler.class.getName())) - .thenReturn(logger); - - UI ui = createInertUIWithPollInterval(); - JsonObject invocationJson = createIllegitimatePayloadKeysPollingRpcInvocationPayload( - ui); - handler.handle(ui, invocationJson); - - verify(logger, times(1)).warn(anyString()); - verify(logger, times(1)).debug(anyString(), (Object) any()); - } - } - - private Element createRpcInvocationData(UI ui, - Consumer additionalConfig) { - Element element = ElementFactory.createAnchor(); - ui.getElement().appendChild(element); - - if (additionalConfig != null) { - additionalConfig.accept(element); - } - - JsonObject object = Json.createObject(); - object.put(JsonConstants.RPC_NODE, element.getNode().getId()); - handler.handle(ui, object); - return element; - } - - private UI createInertUIWithPollInterval() { - UI ui = createInertUI(); - ui.setPollInterval(5000); - return ui; - } - - private UI createInertUI() { - UI ui = new UI(); - ElementUtil.setInert(ui.getElement(), true); - ui.getInternals().getStateTree().collectDirtyNodes() - .forEach(stateNode -> stateNode.collectChanges(change -> { - })); - return ui; - } - - private JsonObject createLegitimatePollingRpcInvocationPayload(UI ui) { - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_TYPE, JsonConstants.RPC_TYPE_EVENT); - payload.put(JsonConstants.RPC_NODE, ui.getElement().getNode().getId()); - payload.put(JsonConstants.RPC_EVENT_TYPE, PollEvent.DOM_EVENT_NAME); - return payload; - } - - private JsonObject createIllegitimatePayloadKeysPollingRpcInvocationPayload( - UI ui) { - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_EVENT_DATA, "DATA"); - payload.put(JsonConstants.RPC_NODE, ui.getElement().getNode().getId()); - payload.put(JsonConstants.RPC_EVENT_TYPE, PollEvent.DOM_EVENT_NAME); - return payload; - } - - private JsonObject createIllegitimatePayloadWithGreaterSizePollingRpcInvocationPayload( - UI ui) { - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_EVENT_DATA, "DATA"); - payload.put(JsonConstants.RPC_TYPE, JsonConstants.RPC_TYPE_EVENT); - payload.put(JsonConstants.RPC_NODE, ui.getElement().getNode().getId()); - payload.put(JsonConstants.RPC_EVENT_TYPE, PollEvent.DOM_EVENT_NAME); - return payload; - } - - private JsonObject createIllegitimatePayloadWithSmallerSizePollingRpcInvocationPayload( - UI ui) { - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_NODE, ui.getElement().getNode().getId()); - payload.put(JsonConstants.RPC_EVENT_TYPE, PollEvent.DOM_EVENT_NAME); - return payload; - } - - private JsonObject createIllegitimatePayloadNoNodeKeyForPollingRpcInvocationPayload() { - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_TYPE, JsonConstants.RPC_TYPE_EVENT); - payload.put(JsonConstants.CHANGE_TYPE, "change"); - payload.put(JsonConstants.RPC_EVENT_TYPE, PollEvent.DOM_EVENT_NAME); - return payload; - } - - private JsonObject createNonPollingRpcInvocationPayload(UI ui) { - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_TYPE, JsonConstants.RPC_TYPE_EVENT); - payload.put(JsonConstants.RPC_NODE, - ui.getInternals().getStateTree().getRootNode().getId()); - payload.put(JsonConstants.RPC_EVENT_TYPE, - JsonConstants.RPC_TYPE_MAP_SYNC); - return payload; - } - - private JsonObject createIllegitimatePayloadWithNonRootNodePollingRpcInvocationPayload( - UI ui) { - Element element = ElementFactory.createAnchor(); - ui.getElement().appendChild(element); - - JsonObject payload = Json.createObject(); - payload.put(JsonConstants.RPC_TYPE, JsonConstants.RPC_TYPE_EVENT); - payload.put(JsonConstants.RPC_NODE, element.getNode().getId()); - payload.put(JsonConstants.RPC_EVENT_TYPE, PollEvent.DOM_EVENT_NAME); - return payload; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AttachExistingElementRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AttachExistingElementRpcHandlerTest.java deleted file mode 100644 index 22d9552f8ed..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AttachExistingElementRpcHandlerTest.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.dom.ChildElementConsumer; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.Node; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.internal.nodefeature.AttachExistingElementFeature; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class AttachExistingElementRpcHandlerTest { - - @Test - public void handleNode_error() { - AttachExistingElementRpcHandler handler = new AttachExistingElementRpcHandler(); - - int requestedId = 1; - JsonObject object = Json.createObject(); - object.put(JsonConstants.RPC_ATTACH_REQUESTED_ID, requestedId); - object.put(JsonConstants.RPC_ATTACH_ASSIGNED_ID, -1); - object.put(JsonConstants.RPC_ATTACH_TAG_NAME, "div"); - object.put(JsonConstants.RPC_ATTACH_INDEX, -1); - - StateNode node = Mockito.mock(StateNode.class); - StateNode requested = Mockito.mock(StateNode.class); - StateTree tree = Mockito.mock(StateTree.class); - Mockito.when(node.getOwner()).thenReturn(tree); - Mockito.when(tree.getNodeById(requestedId)).thenReturn(requested); - - AttachExistingElementFeature feature = new AttachExistingElementFeature( - node); - Node parentNode = Mockito.mock(Node.class); - ChildElementConsumer consumer = Mockito - .mock(ChildElementConsumer.class); - Element sibling = Mockito.mock(Element.class); - feature.register(parentNode, sibling, requested, consumer); - Mockito.when(node.getFeature(AttachExistingElementFeature.class)) - .thenReturn(feature); - - handler.handleNode(node, object); - - Mockito.verify(consumer).onError(parentNode, "div", sibling); - assertNodeIsUnregistered(node, requested, feature); - } - - @Test - public void handleNode_requestedIdEqualsAssignedId() { - AttachExistingElementRpcHandler handler = new AttachExistingElementRpcHandler(); - - int requestedId = 1; - int index = 2; - JsonObject object = Json.createObject(); - object.put(JsonConstants.RPC_ATTACH_REQUESTED_ID, requestedId); - object.put(JsonConstants.RPC_ATTACH_ASSIGNED_ID, requestedId); - object.put(JsonConstants.RPC_ATTACH_TAG_NAME, "div"); - object.put(JsonConstants.RPC_ATTACH_INDEX, index); - - StateNode node = Mockito.mock(StateNode.class); - StateNode requested = Mockito.mock(StateNode.class); - StateTree tree = Mockito.mock(StateTree.class); - - Mockito.when(node.getOwner()).thenReturn(tree); - Mockito.when(tree.getNodeById(requestedId)).thenReturn(requested); - - Mockito.when(requested.hasFeature(Mockito.any())).thenReturn(true); - - AttachExistingElementFeature feature = new AttachExistingElementFeature( - node); - Node parentNode = Mockito.mock(Node.class); - ChildElementConsumer consumer = Mockito - .mock(ChildElementConsumer.class); - Element sibling = Mockito.mock(Element.class); - feature.register(parentNode, sibling, requested, consumer); - Mockito.when(node.getFeature(AttachExistingElementFeature.class)) - .thenReturn(feature); - - handler.handleNode(node, object); - - assertNodeIsUnregistered(node, requested, feature); - Mockito.verify(parentNode).insertChild(index, Element.get(requested)); - Mockito.verify(consumer).accept(Element.get(requested)); - } - - @Test - public void handleNode_requestedIdAndAssignedIdAreDifferent() { - AttachExistingElementRpcHandler handler = new AttachExistingElementRpcHandler(); - - int requestedId = 1; - int assignedId = 2; - int index = 3; - JsonObject object = Json.createObject(); - object.put(JsonConstants.RPC_ATTACH_REQUESTED_ID, requestedId); - object.put(JsonConstants.RPC_ATTACH_ASSIGNED_ID, assignedId); - object.put(JsonConstants.RPC_ATTACH_TAG_NAME, "div"); - object.put(JsonConstants.RPC_ATTACH_INDEX, index); - - StateNode node = Mockito.mock(StateNode.class); - StateNode requested = Mockito.mock(StateNode.class); - StateNode assigned = Mockito.mock(StateNode.class); - StateTree tree = Mockito.mock(StateTree.class); - - Mockito.when(node.getOwner()).thenReturn(tree); - Mockito.when(tree.getNodeById(requestedId)).thenReturn(requested); - Mockito.when(tree.getNodeById(assignedId)).thenReturn(assigned); - - Mockito.when(assigned.hasFeature(Mockito.any())).thenReturn(true); - - AttachExistingElementFeature feature = new AttachExistingElementFeature( - node); - Node parentNode = Mockito.mock(Node.class); - ChildElementConsumer consumer = Mockito - .mock(ChildElementConsumer.class); - Element sibling = Mockito.mock(Element.class); - feature.register(parentNode, sibling, requested, consumer); - Mockito.when(node.getFeature(AttachExistingElementFeature.class)) - .thenReturn(feature); - - handler.handleNode(node, object); - - assertNodeIsUnregistered(node, requested, feature); - Mockito.verify(parentNode, Mockito.times(0)).insertChild(index, - Element.get(assigned)); - Mockito.verify(consumer).accept(Element.get(assigned)); - } - - private void assertNodeIsUnregistered(StateNode node, StateNode requested, - AttachExistingElementFeature feature) { - Mockito.verify(requested).setParent(null); - Assert.assertNull(feature.getParent(requested)); - Assert.assertNull(feature.getCallback(requested)); - Assert.assertNull(feature.getPreviousSibling(node)); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AttachTemplateChildRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AttachTemplateChildRpcHandlerTest.java deleted file mode 100644 index ad613c2238b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/AttachTemplateChildRpcHandlerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.util.HashMap; - -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.StateTree; -import com.vaadin.flow.internal.nodefeature.ElementData; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonValue; - -public class AttachTemplateChildRpcHandlerTest { - - @Test(expected = IllegalStateException.class) - public void handleNode_attachById_elementNotFound() { - doHandleNode_attach_elementNotFound(Json.create("id")); - } - - @Test(expected = IllegalStateException.class) - public void handleNode_attachCustomElement_elementNotFound() { - doHandleNode_attach_elementNotFound(Json.createNull()); - } - - @Test(expected = IllegalStateException.class) - public void handleNode_attachByIdExistingRequest_throwReservedId() { - doHandleNode_attach_throwReservedId(Json.create(2)); - } - - @Test(expected = IllegalStateException.class) - public void handleNode_attachCustonElementCustomId_throwReservedId() { - doHandleNode_attach_throwReservedId(Json.createNull()); - } - - @Test(expected = IllegalArgumentException.class) - public void handleNode_success_throwIllegalInvocation() { - assertHandleNode(1, Json.create("id")); - } - - private void doHandleNode_attach_elementNotFound(JsonValue id) { - assertHandleNode(-1, id); - } - - private void doHandleNode_attach_throwReservedId(JsonValue id) { - assertHandleNode(2, id); - } - - private void assertHandleNode(int assignedId, JsonValue id) { - AttachTemplateChildRpcHandler handler = new AttachTemplateChildRpcHandler(); - - int requestedId = 1; - JsonObject object = Json.createObject(); - object.put(JsonConstants.RPC_ATTACH_REQUESTED_ID, requestedId); - object.put(JsonConstants.RPC_ATTACH_ASSIGNED_ID, assignedId); - object.put(JsonConstants.RPC_ATTACH_ID, id); - - StateNode node = Mockito.mock(StateNode.class); - StateNode parentNode = Mockito.mock(StateNode.class); - StateTree tree = Mockito.mock(StateTree.class); - Mockito.when(node.getOwner()).thenReturn(tree); - Mockito.when(node.getParent()).thenReturn(parentNode); - Mockito.when(tree.getNodeById(requestedId)).thenReturn(node); - Mockito.when(node.getChangeTracker(Mockito.any(), Mockito.any())) - .thenReturn(new HashMap<>()); - - ElementData data = new ElementData(node); - data.setTag("foo"); - Mockito.when(node.getFeature(ElementData.class)).thenReturn(data); - - Mockito.when(parentNode.getId()).thenReturn(3); - - handler.handleNode(node, object); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/EnumDecoderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/EnumDecoderTest.java deleted file mode 100644 index 7fe51448b31..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/EnumDecoderTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import org.junit.Assert; -import org.junit.Test; - -import elemental.json.Json; - -public class EnumDecoderTest { - - private StringToEnumDecoder decoder = new StringToEnumDecoder(); - - enum Title { - MR, MRS; - } - - @Test - public void isApplicable_applicableToStringAndEnum() { - Assert.assertTrue( - decoder.isApplicable(Json.create("foo"), Title.class)); - } - - @Test - public void isApplicable_notApplicableToBooleanAndEnum() { - Assert.assertFalse(decoder.isApplicable(Json.create(true), Enum.class)); - } - - @Test - public void isApplicable_notApplicableToStringAndString() { - Assert.assertFalse( - decoder.isApplicable(Json.create("foo"), String.class)); - } - - @Test - public void isApplicable_notApplicableToStringAndAbstractEnum() { - Assert.assertFalse( - decoder.isApplicable(Json.create("foo"), Enum.class)); - } - - @Test - public void stringToEnum_convertableString_valueIsConverted() - throws RpcDecodeException { - Title title = Title.MRS; - Title decoded = decoder.decode(Json.create(title.name()), Title.class); - Assert.assertEquals(title, decoded); - } - - @Test(expected = IllegalArgumentException.class) - public void stringToEnum_nonConvertableString_valueIsConverted() - throws RpcDecodeException { - decoder.decode(Json.create("foo"), Title.class); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/EventRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/EventRpcHandlerTest.java deleted file mode 100644 index 4bc65ad4d23..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/EventRpcHandlerTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.ComponentTest.TestComponent; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class EventRpcHandlerTest { - - @Test - public void testElementEventNoData() throws Exception { - TestComponent c = new TestComponent(); - Element element = c.getElement(); - UI ui = new UI(); - ui.add(c); - AtomicInteger invocations = new AtomicInteger(0); - - element.addEventListener("test-event", - e -> invocations.incrementAndGet()); - sendElementEvent(element, ui, "test-event", null); - Assert.assertEquals(1, invocations.get()); - } - - @Test - public void testElementEventData() throws Exception { - TestComponent c = new TestComponent(); - Element element = c.getElement(); - UI ui = new UI(); - ui.add(c); - AtomicInteger invocationData = new AtomicInteger(0); - - element.addEventListener("test-event", e -> invocationData - .addAndGet((int) e.getEventData().getNumber("nr"))); - JsonObject eventData = Json.createObject(); - eventData.put("nr", 123); - sendElementEvent(element, ui, "test-event", eventData); - Assert.assertEquals(123, invocationData.get()); - } - - private static JsonObject createElementEventInvocation(Element element, - String eventType, JsonObject eventData) { - StateNode node = element.getNode(); - // Copied from ServerConnector - JsonObject message = Json.createObject(); - message.put(JsonConstants.RPC_NODE, node.getId()); - message.put(JsonConstants.RPC_EVENT_TYPE, eventType); - - if (eventData != null) { - message.put(JsonConstants.RPC_EVENT_DATA, eventData); - } - - return message; - } - - private static void sendElementEvent(Element element, UI ui, - String eventType, JsonObject eventData) throws Exception { - new EventRpcHandler().handle(ui, - createElementEventInvocation(element, eventType, eventData)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/MapSyncRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/MapSyncRpcHandlerTest.java deleted file mode 100644 index d4ac73d6717..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/MapSyncRpcHandlerTest.java +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.io.Serializable; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.hamcrest.CoreMatchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.dom.DisabledUpdateMode; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.dom.ElementFactory; -import com.vaadin.flow.internal.JsonCodec; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.nodefeature.ElementPropertyMap; -import com.vaadin.flow.internal.nodefeature.ModelList; -import com.vaadin.flow.internal.nodefeature.NodeFeature; -import com.vaadin.flow.internal.nodefeature.NodeFeatureRegistry; -import com.vaadin.flow.shared.JsonConstants; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonValue; -import org.mockito.MockedStatic; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class MapSyncRpcHandlerTest { - - private static final String NEW_VALUE = "newValue"; - private static final String DUMMY_EVENT = "dummy-event"; - private static final String TEST_PROPERTY = "test-property"; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Tag(Tag.A) - public static class TestComponent extends Component { - - } - - @Test - public void testSynchronizeProperty() throws Exception { - TestComponent c = new TestComponent(); - Element element = c.getElement(); - ElementPropertyMap.getModel(element.getNode()) - .setUpdateFromClientFilter(name -> true); - - UI ui = new UI(); - ui.add(c); - Assert.assertFalse(element.hasProperty(TEST_PROPERTY)); - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, "value1"); - Assert.assertEquals("value1", element.getPropertyRaw(TEST_PROPERTY)); - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, "value2"); - Assert.assertEquals("value2", element.getPropertyRaw(TEST_PROPERTY)); - } - - @Test - public void syncJSON_jsonIsForStateNodeInList_propertySetToStateNodeCopy() - throws Exception { - // Let's use element's ElementPropertyMap for testing. - TestComponent component = new TestComponent(); - Element element = component.getElement(); - UI ui = new UI(); - ui.add(component); - - StateNode node = element.getNode(); - - // Set model value directly via ElementPropertyMap - ElementPropertyMap propertyMap = node - .getFeature(ElementPropertyMap.class); - propertyMap.setUpdateFromClientFilter(name -> true); - ModelList modelList = propertyMap.resolveModelList("foo"); - // fake StateNode has been created for the model - StateNode item = new StateNode(ElementPropertyMap.class); - modelList.add(item); - item.getFeature(ElementPropertyMap.class).setProperty("bar", "baz"); - - // Use the model node id for JSON object which represents a value to - // update - JsonObject json = Json.createObject(); - json.put("nodeId", item.getId()); - - // send sync request - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, json); - - // Now the model node should be copied and available as the - // TEST_PROPERTY value - Serializable testPropertyValue = propertyMap.getProperty(TEST_PROPERTY); - - Assert.assertTrue(testPropertyValue instanceof StateNode); - - StateNode newNode = (StateNode) testPropertyValue; - Assert.assertNotEquals(item.getId(), newNode.getId()); - - Assert.assertEquals("baz", newNode.getFeature(ElementPropertyMap.class) - .getProperty("bar")); - } - - @Test - public void syncJSON_jsonIsPropertyValueOfStateNode_propertySetToNode() - throws Exception { - // Let's use element's ElementPropertyMap for testing. - TestComponent component = new TestComponent(); - Element element = component.getElement(); - UI ui = new UI(); - ui.add(component); - - StateNode node = element.getNode(); - - // Set model value directly via ElementPropertyMap - ElementPropertyMap propertyMap = node - .getFeature(ElementPropertyMap.class); - propertyMap.setUpdateFromClientFilter(name -> true); - - ElementPropertyMap modelMap = propertyMap.resolveModelMap("foo"); - // fake StateNode has been created for the model - StateNode model = modelMap.getNode(); - modelMap.setProperty("bar", "baz"); - - // Use the model node id for JSON object which represents a value to - // update - JsonObject json = Json.createObject(); - json.put("nodeId", model.getId()); - - // send sync request - sendSynchronizePropertyEvent(element, ui, "foo", json); - - Serializable testPropertyValue = propertyMap.getProperty("foo"); - - Assert.assertTrue(testPropertyValue instanceof StateNode); - - StateNode newNode = (StateNode) testPropertyValue; - Assert.assertSame(model, newNode); - } - - @Test - public void syncJSON_jsonIsNotListItemAndNotPropertyValue_propertySetToJSON() - throws Exception { - // Let's use element's ElementPropertyMap for testing. - TestComponent component = new TestComponent(); - Element element = component.getElement(); - UI ui = new UI(); - ui.add(component); - - StateNode node = element.getNode(); - - TestComponent anotherComonent = new TestComponent(); - StateNode anotherNode = anotherComonent.getElement().getNode(); - - ElementPropertyMap.getModel(node) - .setUpdateFromClientFilter(name -> true); - - // Use the model node id for JSON object which represents a value to - // update - JsonObject json = Json.createObject(); - json.put("nodeId", anotherNode.getId()); - - // send sync request - sendSynchronizePropertyEvent(element, ui, "foo", json); - - Serializable testPropertyValue = node - .getFeature(ElementPropertyMap.class).getProperty("foo"); - - Assert.assertNotSame(anotherNode, testPropertyValue); - Assert.assertTrue(testPropertyValue instanceof JsonValue); - } - - @Test - public void disabledElement_updateDisallowed_updateIsNotDone() - throws Exception { - Element element = ElementFactory.createDiv(); - UI ui = new UI(); - ui.getElement().appendChild(element); - - element.setEnabled(false); - element.addPropertyChangeListener(TEST_PROPERTY, DUMMY_EVENT, event -> { - }).setDisabledUpdateMode(DisabledUpdateMode.ONLY_WHEN_ENABLED); - - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, NEW_VALUE); - - Assert.assertNotEquals(NEW_VALUE, - element.getPropertyRaw(TEST_PROPERTY)); - } - - @Test - public void disabledElement_updateIsAllowedBySynchronizeProperty_updateIsDone() - throws Exception { - Element element = ElementFactory.createDiv(); - UI ui = new UI(); - ui.getElement().appendChild(element); - - element.setEnabled(false); - element.addPropertyChangeListener(TEST_PROPERTY, DUMMY_EVENT, event -> { - }).setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, NEW_VALUE); - - Assert.assertEquals(NEW_VALUE, element.getPropertyRaw(TEST_PROPERTY)); - } - - @Test - public void disabledElement_updateIsAllowedByEventListener_updateIsDone() - throws Exception { - Element element = ElementFactory.createDiv(); - UI ui = new UI(); - ui.getElement().appendChild(element); - - element.setEnabled(false); - element.addEventListener(DUMMY_EVENT, event -> { - }).synchronizeProperty(TEST_PROPERTY) - .setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, NEW_VALUE); - - Assert.assertEquals(NEW_VALUE, element.getPropertyRaw(TEST_PROPERTY)); - } - - @Test - public void implicitlyDisabledElement_updateIsAllowedBySynchronizeProperty_updateIsDone() - throws Exception { - Element element = ElementFactory.createDiv(); - UI ui = new UI(); - ui.getElement().appendChild(element); - - ui.setEnabled(false); - element.addPropertyChangeListener(TEST_PROPERTY, DUMMY_EVENT, event -> { - }).setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, NEW_VALUE); - - Assert.assertEquals(NEW_VALUE, element.getPropertyRaw(TEST_PROPERTY)); - } - - @Test - public void implicitlyDisabledElement_updateIsAllowedByEventListener_updateIsDone() - throws Exception { - Element element = ElementFactory.createDiv(); - UI ui = new UI(); - ui.getElement().appendChild(element); - - ui.setEnabled(false); - element.addEventListener(DUMMY_EVENT, event -> { - }).synchronizeProperty(TEST_PROPERTY) - .setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - sendSynchronizePropertyEvent(element, ui, TEST_PROPERTY, NEW_VALUE); - - Assert.assertEquals(NEW_VALUE, element.getPropertyRaw(TEST_PROPERTY)); - } - - @Test(expected = IllegalArgumentException.class) - public void noSyncPropertiesFeature_noExplicitAllow_throws() { - StateNode noSyncProperties = new StateNode(ElementPropertyMap.class); - - ElementPropertyMap map = noSyncProperties - .getFeature(ElementPropertyMap.class); - - new MapSyncRpcHandler().handleNode(noSyncProperties, - createSyncPropertyInvocation(noSyncProperties, TEST_PROPERTY, - NEW_VALUE)); - - Assert.assertEquals(NEW_VALUE, map.getProperty(TEST_PROPERTY)); - } - - @Test - public void propertyIsNotExplicitlyAllowed_throwsWithElementTagInfo() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(CoreMatchers.allOf( - CoreMatchers.containsString("Element with tag 'foo'"), - CoreMatchers.containsString("'" + TEST_PROPERTY + "'"))); - Element element = new Element("foo"); - - new MapSyncRpcHandler().handleNode(element.getNode(), - createSyncPropertyInvocation(element.getNode(), TEST_PROPERTY, - NEW_VALUE)); - } - - @Test - public void propertyIsNotExplicitlyAllowed_throwsWithComponentInfo() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(CoreMatchers.allOf( - CoreMatchers.containsString( - "Component " + TestComponent.class.getName()), - CoreMatchers.containsString("'" + TEST_PROPERTY + "'"))); - TestComponent component = new TestComponent(); - Element element = component.getElement(); - - new MapSyncRpcHandler().handleNode(element.getNode(), - createSyncPropertyInvocation(element.getNode(), TEST_PROPERTY, - NEW_VALUE)); - } - - @Test - public void propertyIsNotExplicitlyAllowed_subproperty_throwsWithComponentInfo() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(CoreMatchers.allOf( - CoreMatchers.containsString( - "Component " + TestComponent.class.getName()), - CoreMatchers.containsString("'" + TEST_PROPERTY + "'"))); - TestComponent component = new TestComponent(); - Element element = component.getElement(); - - StateNode node = element.getNode(); - ElementPropertyMap propertyMap = node - .getFeature(ElementPropertyMap.class) - .resolveModelMap("foo.bar"); - - new MapSyncRpcHandler().handleNode(propertyMap.getNode(), - createSyncPropertyInvocation(propertyMap.getNode(), - TEST_PROPERTY, NEW_VALUE)); - } - - @Test - public void handleNode_callsElementPropertyMapDeferredUpdateFromClient() { - AtomicInteger deferredUpdateInvocations = new AtomicInteger(); - AtomicReference deferredKey = new AtomicReference<>(); - StateNode node = new StateNode(ElementPropertyMap.class) { - - private ElementPropertyMap map = new ElementPropertyMap(this) { - @Override - public Runnable deferredUpdateFromClient(String key, - Serializable value) { - deferredUpdateInvocations.incrementAndGet(); - deferredKey.set(key); - return () -> { - }; - } - }; - - @Override - public F getFeature(Class featureType) { - if (featureType.equals(ElementPropertyMap.class)) { - return featureType.cast(map); - } - return super.getFeature(featureType); - } - - }; - - new MapSyncRpcHandler().handleNode(node, - createSyncPropertyInvocation(node, TEST_PROPERTY, NEW_VALUE)); - - Assert.assertEquals(1, deferredUpdateInvocations.get()); - Assert.assertEquals(TEST_PROPERTY, deferredKey.get()); - } - - @Test - public void handleNode_stateNodePropertyDefaultValueNotSet_doesNotWarnForUnsetDisabledPropertyChange() { - - ElementPropertyMap map = mock(ElementPropertyMap.class); - when(map.getProperty(anyString())).thenReturn(null); - StateNode disabledNode = mock(StateNode.class); - when(disabledNode.getFeatureIfInitialized(ElementPropertyMap.class)) - .thenReturn(Optional.of(map)); - when(disabledNode.isEnabled()).thenReturn(false); - - Logger logger = spy(Logger.class); - try (MockedStatic mockedLoggerFactory = mockStatic( - LoggerFactory.class)) { - mockedLoggerFactory.when( - () -> LoggerFactory.getLogger(MapSyncRpcHandler.class)) - .thenReturn(logger); - - new MapSyncRpcHandler().handleNode(disabledNode, - createSyncPropertyInvocation(disabledNode, TEST_PROPERTY, - NEW_VALUE)); - - verify(logger, times(0)).warn(anyString(), anyString()); - verify(logger, times(1)).debug(anyString(), anyString()); - } - } - - @Test - public void handleNode_stateNodePropertyDefaultValueSet_warnsForSetDisabledPropertyChange() { - - ElementPropertyMap map = mock(ElementPropertyMap.class); - when(map.getProperty(anyString())).thenReturn(NEW_VALUE); - StateNode disabledNode = mock(StateNode.class); - when(disabledNode.getFeatureIfInitialized(ElementPropertyMap.class)) - .thenReturn(Optional.of(map)); - when(disabledNode.isEnabled()).thenReturn(false); - - Logger logger = spy(Logger.class); - try (MockedStatic mockedLoggerFactory = mockStatic( - LoggerFactory.class)) { - mockedLoggerFactory.when( - () -> LoggerFactory.getLogger(MapSyncRpcHandler.class)) - .thenReturn(logger); - - new MapSyncRpcHandler().handleNode(disabledNode, - createSyncPropertyInvocation(disabledNode, TEST_PROPERTY, - NEW_VALUE)); - - verify(logger, times(1)).warn(anyString(), anyString()); - verify(logger, times(0)).debug(anyString(), anyString()); - } - } - - private static void sendSynchronizePropertyEvent(Element element, UI ui, - String eventType, Serializable value) throws Exception { - new MapSyncRpcHandler().handle(ui, - createSyncPropertyInvocation(element, eventType, value)); - } - - private static JsonObject createSyncPropertyInvocation(Element element, - String property, Serializable value) { - return createSyncPropertyInvocation(element.getNode(), property, value); - } - - private static JsonObject createSyncPropertyInvocation(StateNode node, - String property, Serializable value) { - // Copied from ServerConnector - JsonObject message = Json.createObject(); - message.put(JsonConstants.RPC_NODE, node.getId()); - message.put(JsonConstants.RPC_FEATURE, - NodeFeatureRegistry.getId(ElementPropertyMap.class)); - message.put(JsonConstants.RPC_PROPERTY, property); - message.put(JsonConstants.RPC_PROPERTY_VALUE, - JsonCodec.encodeWithoutTypeInfo(value)); - - return message; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/NavigationRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/NavigationRpcHandlerTest.java deleted file mode 100644 index f8c6c833dab..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/NavigationRpcHandlerTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.vaadin.flow.server.communication.rpc; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.page.History; -import com.vaadin.flow.router.RouterLink; -import com.vaadin.flow.shared.JsonConstants; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class NavigationRpcHandlerTest { - - private UI ui; - private History.HistoryStateChangeHandler historyStateChangeHandler; - private NavigationRpcHandler rpcHandler; - private JsonObject invocation; - - @Before - public void setup() { - ui = new UI(); - historyStateChangeHandler = Mockito - .mock(History.HistoryStateChangeHandler.class); - ui.getPage().getHistory() - .setHistoryStateChangeHandler(historyStateChangeHandler); - - ui.add(new RouterLink()); - - rpcHandler = new NavigationRpcHandler(); - invocation = Json.createObject(); - invocation.put(JsonConstants.RPC_NAVIGATION_LOCATION, "foo"); - } - - @Test - public void handleRouterLinkClick_navigationTriggered() { - invocation.put(JsonConstants.RPC_NAVIGATION_ROUTERLINK, true); - rpcHandler.handle(ui, invocation); - - Mockito.verify(historyStateChangeHandler, Mockito.times(1)) - .onHistoryStateChange( - Mockito.any(History.HistoryStateChangeEvent.class)); - } - - @Test - public void handleRouterLinkClick_uiIsInert_navigationTriggered() { - ui.addModal(new RouterLink()); - ui.getInternals().getStateTree().collectChanges(nodeChange -> { - }); - - invocation.put(JsonConstants.RPC_NAVIGATION_ROUTERLINK, true); - rpcHandler.handle(ui, invocation); - - Mockito.verify(historyStateChangeHandler, Mockito.times(1)) - .onHistoryStateChange( - Mockito.any(History.HistoryStateChangeEvent.class)); - } - - @Test - public void handleHistoryChange_uiIsInert_navigationTriggered() { - ui.addModal(new RouterLink()); - rpcHandler.handle(ui, invocation); - - Mockito.verify(historyStateChangeHandler, Mockito.times(1)) - .onHistoryStateChange( - Mockito.any(History.HistoryStateChangeEvent.class)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java deleted file mode 100644 index 7cdebcb7b0f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/PublishedServerEventHandlerRpcHandlerTest.java +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.util.List; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.ClientCallable; -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Composite; -import com.vaadin.flow.component.EventData; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.internal.AllowInert; -import com.vaadin.flow.component.internal.PendingJavaScriptInvocation; -import com.vaadin.flow.component.internal.UIInternals.JavaScriptInvocation; -import com.vaadin.flow.component.polymertemplate.EventHandler; -import com.vaadin.flow.dom.DisabledUpdateMode; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinSession; -import com.vaadin.flow.shared.JsonConstants; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; -import elemental.json.JsonValue; - -@NotThreadSafe -public class PublishedServerEventHandlerRpcHandlerTest { - - private VaadinService service; - - private VaadinSession session; - - @Tag("a") - public static class ComponentWithCompute extends Component { - - private boolean isInvoked; - - protected void intMethod(int i) { - } - - @ClientCallable - private void method() { - isInvoked = true; - } - - @ClientCallable - @AllowInert - private void methodThatCanBeCalledWhenInert() { - isInvoked = true; - } - - @ClientCallable - private int compute(int input) { - if (input < 0) { - throw new ArithmeticException(); - } else { - return (int) Math.sqrt(input); - } - } - - } - - @Tag(Tag.DIV) - public static class EnabledHandler extends Component { - - private boolean isInvoked; - - @ClientCallable(DisabledUpdateMode.ALWAYS) - private void operation() { - isInvoked = true; - } - - } - - enum Title { - MR, MRS; - } - - @Tag(Tag.DIV) - public static class DecoderParameters extends Component { - - private boolean isInvoked; - - @ClientCallable - private void method(Long longValue, Title title) { - isInvoked = true; - } - } - - public static class ComponentWithNoClientCallableMethod - extends ComponentWithCompute { - - /** - * No {@link ClientCallable} annotation. - */ - public void operation() { - } - } - - public static class CompositeOfComponentWithCompute - extends Composite { - } - - public static class CompositeOfComposite - extends Composite { - } - - public static class MethodWithVarArgParameter extends ComponentWithCompute { - - private String[] varArg; - - @ClientCallable - protected void varArgMethod(@EventData("foo") String... args) { - varArg = args; - } - - } - - public static class MethodWithParameters extends ComponentWithCompute { - - private int intArg; - private boolean booleanArg; - private String strArg; - private boolean[] arrayArg; - private Double[] doubleArg; - private Integer[] varArg; - private int[][] doubleArray; - private JsonValue jsonValue; - - @Override - @ClientCallable - protected void intMethod(@EventData("foo") int i) { - intArg = i; - } - - @EventHandler - protected void booleanMethod(@EventData("foo") boolean value) { - booleanArg = value; - } - - @ClientCallable - protected void method1(@EventData("foo") String str, - @EventData("bar") boolean[] array) { - strArg = str; - arrayArg = array; - } - - @ClientCallable - protected void method2(@EventData("foo") Double[] arg1, - @EventData("bar") Integer... varArg) { - doubleArg = arg1; - this.varArg = varArg; - } - - @ClientCallable - protected void method3(@EventData("foo") int[][] array) { - doubleArray = array; - } - - @ClientCallable - protected void method4(@EventData("foo") JsonValue value) { - jsonValue = value; - } - } - - @Before - public void setUp() throws Exception { - Assert.assertNull(System.getSecurityManager()); - - MockServletServiceSessionSetup setup = new MockServletServiceSessionSetup(); - - service = setup.getService(); - - MockDeploymentConfiguration configuration = setup - .getDeploymentConfiguration(); - configuration.setProductionMode(false); - - VaadinService.setCurrent(service); - - session = setup.getSession(); - Mockito.when(session.hasLock()).thenReturn(true); - } - - @After - public void tearDown() { - service = null; - VaadinService.setCurrent(null); - } - - @Test - public void methodIsInvoked() { - ComponentWithCompute component = new ComponentWithCompute(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "method", Json.createArray(), -1); - - Assert.assertTrue(component.isInvoked); - } - - @Test - public void methodIsNotInvokedWhenInert() { - ComponentWithCompute component = new ComponentWithCompute(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "method", Json.createArray(), -1, true); - - Assert.assertFalse(component.isInvoked); - } - - @Test - public void methodIsInvokedWhenInertAndInertAllowed() { - ComponentWithCompute component = new ComponentWithCompute(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "methodThatCanBeCalledWhenInert", - Json.createArray(), -1, true); - - Assert.assertTrue(component.isInvoked); - } - - @Test - public void methodIsInvokedOnCompositeContent() { - CompositeOfComponentWithCompute composite = new CompositeOfComponentWithCompute(); - ComponentWithCompute component = composite.getContent(); - PublishedServerEventHandlerRpcHandler.invokeMethod(composite, - composite.getClass(), "method", Json.createArray(), -1); - - Assert.assertTrue(component.isInvoked); - } - - @Test - public void methodIsInvokectOnCompositeOfComposite() { - CompositeOfComposite composite = new CompositeOfComposite(); - ComponentWithCompute component = composite.getContent().getContent(); - PublishedServerEventHandlerRpcHandler.invokeMethod(composite, - composite.getClass(), "method", Json.createArray(), -1); - - Assert.assertTrue(component.isInvoked); - } - - @Test - public void methodWithDecoderParameters_convertableValues_methodIsInvoked() { - JsonArray params = Json.createArray(); - params.set(0, "264"); - params.set(1, "MRS"); - - DecoderParameters component = new DecoderParameters(); - UI ui = new UI(); - - ui.getInternals().setSession(session); - - ui.add(component); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "method", params, -1); - - Assert.assertTrue(component.isInvoked); - } - - @Test(expected = IllegalArgumentException.class) - public void methodWithDecoderParameters_nonConvertableValues_methodIsInvoked() { - JsonArray params = Json.createArray(); - params.set(0, "264.1"); - params.set(1, "MR"); - - UI ui = new UI(); - ui.getInternals().setSession(session); - - DecoderParameters component = new DecoderParameters(); - ui.add(component); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "method", params, -1); - } - - @Test(expected = IllegalArgumentException.class) - public void methodWithoutArgs_argsProvided() { - JsonArray args = Json.createArray(); - args.set(0, true); - ComponentWithCompute component = new ComponentWithCompute(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "method", args, -1); - } - - @Test - public void promiseSuccess() { - int promiseId = 4; - - JsonArray args = Json.createArray(); - args.set(0, 36); - - ComponentWithCompute component = new ComponentWithCompute(); - UI ui = new UI(); - ui.getInternals().setSession(session); - ui.add(component); - - // Get rid of attach invocations - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - ui.getInternals().dumpPendingJavaScriptInvocations(); - - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "compute", args, promiseId); - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - List pendingJavaScriptInvocations = ui - .getInternals().dumpPendingJavaScriptInvocations(); - Assert.assertEquals(1, pendingJavaScriptInvocations.size()); - - JavaScriptInvocation invocation = pendingJavaScriptInvocations.get(0) - .getInvocation(); - Assert.assertTrue("Invocation does not look like a promise callback", - invocation.getExpression() - .contains(JsonConstants.RPC_PROMISE_CALLBACK_NAME)); - - List parameters = invocation.getParameters(); - Assert.assertEquals( - "Expected three paramters: promiseId, value, target", 3, - parameters.size()); - Assert.assertEquals( - "Promise id should match the value passed to invokeMethod", - Integer.valueOf(promiseId), parameters.get(0)); - Assert.assertEquals("Promise value should be sqrt(36) = 6", - Integer.valueOf(6), parameters.get(1)); - Assert.assertEquals("Target should be the component's element", - component.getElement(), parameters.get(2)); - } - - @Test - public void promiseFailure() { - int promiseId = 4; - - JsonArray args = Json.createArray(); - args.set(0, -36); - - ComponentWithCompute component = new ComponentWithCompute(); - UI ui = new UI(); - ui.getInternals().setSession(session); - ui.add(component); - - // Get rid of attach invocations - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - ui.getInternals().dumpPendingJavaScriptInvocations(); - - try { - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "compute", args, promiseId); - Assert.fail("Exception should be thrown"); - } catch (RuntimeException e) { - Assert.assertTrue(e.getCause() instanceof ArithmeticException); - } - - ui.getInternals().getStateTree().runExecutionsBeforeClientResponse(); - List pendingJavaScriptInvocations = ui - .getInternals().dumpPendingJavaScriptInvocations(); - Assert.assertEquals(1, pendingJavaScriptInvocations.size()); - - JavaScriptInvocation invocation = pendingJavaScriptInvocations.get(0) - .getInvocation(); - Assert.assertTrue("Invocation does not look like a promise callback", - invocation.getExpression() - .contains(JsonConstants.RPC_PROMISE_CALLBACK_NAME)); - - List parameters = invocation.getParameters(); - Assert.assertEquals("Expected two paramters: promiseId, target", 2, - parameters.size()); - Assert.assertEquals( - "Promise id should match the value passed to invokeMethod", - Integer.valueOf(promiseId), parameters.get(0)); - Assert.assertEquals("Target should be the component's element", - component.getElement(), parameters.get(1)); - } - - @Test - public void methodWithVarArg_acceptNoValues() { - JsonArray array = Json.createArray(); - - MethodWithVarArgParameter component = new MethodWithVarArgParameter(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "varArgMethod", array, -1); - - Assert.assertEquals(0, component.varArg.length); - } - - @Test - public void methodWithSeveralArgsAndVarArg_acceptNoValues() { - JsonArray array = Json.createArray(); - - JsonArray firstArg = Json.createArray(); - firstArg.set(0, 5.6d); - firstArg.set(1, 78.36d); - - array.set(0, firstArg); - - MethodWithParameters component = new MethodWithParameters(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "method2", array, -1); - - Assert.assertArrayEquals( - new Double[] { firstArg.getNumber(0), firstArg.getNumber(1) }, - component.doubleArg); - - Assert.assertNotNull(component.varArg); - Assert.assertEquals(0, component.varArg.length); - } - - @Test - public void methodWithVarArg_acceptOneValue() { - JsonArray array = Json.createArray(); - - array.set(0, "foo"); - - MethodWithVarArgParameter component = new MethodWithVarArgParameter(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "varArgMethod", array, -1); - - Assert.assertEquals(1, component.varArg.length); - Assert.assertEquals("foo", component.varArg[0]); - } - - @Test - public void methodWithVarArg_arrayIsCorrectlyHandled() { - JsonArray array = Json.createArray(); - - JsonArray value = Json.createArray(); - value.set(0, "foo"); - array.set(0, value); - - MethodWithVarArgParameter component = new MethodWithVarArgParameter(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "varArgMethod", array, -1); - - Assert.assertArrayEquals(new String[] { value.getString(0) }, - component.varArg); - } - - @Test - public void nullValueAreAcceptedForPrimitive() { - JsonArray array = Json.createArray(); - array.set(0, Json.createNull()); - MethodWithParameters component = new MethodWithParameters(); - component.intArg = -1; - component.booleanArg = true; - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "intMethod", array, -1); - - Assert.assertEquals(0, component.intArg); - - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "booleanMethod", array, -1); - - Assert.assertFalse(component.booleanArg); - } - - @Test(expected = IllegalStateException.class) - public void noClientCallableMethodException() { - ComponentWithNoClientCallableMethod component = new ComponentWithNoClientCallableMethod(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "operation", Json.createArray(), -1); - } - - @Test(expected = IllegalStateException.class) - public void noMethodException() { - ComponentWithNoClientCallableMethod component = new ComponentWithNoClientCallableMethod(); - PublishedServerEventHandlerRpcHandler.invokeMethod(component, - component.getClass(), "operation1", Json.createArray(), -1); - } - - @Test - public void enabledElement_methodIsInvoked() { - UI ui = new UI(); - ComponentWithCompute component = new ComponentWithCompute(); - ui.add(component); - - requestInvokeMethod(component); - - Assert.assertTrue(component.isInvoked); - } - - @Test - public void disabledElement_ClientCallableIsNotInvoked() { - UI ui = new UI(); - ComponentWithCompute component = new ComponentWithCompute(); - ui.add(component); - - component.getElement().setEnabled(false); - - requestInvokeMethod(component); - - Assert.assertFalse(component.isInvoked); - } - - @Test - public void disabledElement_clientDelegateAllowsRPC_methodIsInvoked() { - UI ui = new UI(); - EnabledHandler component = new EnabledHandler(); - ui.add(component); - - component.getElement().setEnabled(false); - - Assert.assertFalse(component.isInvoked); - - requestInvokeMethod(component, "operation"); - - Assert.assertTrue(component.isInvoked); - } - - private void requestInvokeMethod(Component component) { - requestInvokeMethod(component, "method"); - } - - private void requestInvokeMethod(Component component, String method) { - JsonObject json = Json.createObject(); - json.put(JsonConstants.RPC_TEMPLATE_EVENT_METHOD_NAME, method); - - new PublishedServerEventHandlerRpcHandler() - .handleNode(component.getElement().getNode(), json); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/ReturnChannelHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/ReturnChannelHandlerTest.java deleted file mode 100644 index 5a63ac2aa77..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/ReturnChannelHandlerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.util.concurrent.atomic.AtomicReference; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.dom.DisabledUpdateMode; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.function.SerializableConsumer; -import com.vaadin.flow.internal.StateNode; -import com.vaadin.flow.internal.nodefeature.ElementChildrenList; -import com.vaadin.flow.internal.nodefeature.ReturnChannelMap; -import com.vaadin.flow.internal.nodefeature.ReturnChannelRegistration; -import com.vaadin.flow.server.communication.ReturnChannelHandler; -import com.vaadin.flow.shared.JsonConstants; -import com.vaadin.tests.util.MockUI; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; - -public class ReturnChannelHandlerTest { - private MockUI ui = new MockUI(); - - private AtomicReference observedArguments = new AtomicReference<>(); - private SerializableConsumer observingConsumer = arguments -> { - Assert.assertNotNull("Arguments should not be null", arguments); - Assert.assertNull("There should be no previous arguments", - observedArguments.getAndSet(arguments)); - }; - - private JsonArray args = Json.createArray(); - - @Test - public void happyPath_everythingWorks() { - ReturnChannelRegistration registration = registerUiChannel(); - - handleMessage(registration); - - Assert.assertSame( - "Handler should have been invoked with the given arguments.", - args, observedArguments.get()); - } - - @Test - public void noReturnChannelMap_invocationIgnored() { - StateNode nodeWithoutMap = new StateNode(); - - ui.getElement().getNode().getFeature(ElementChildrenList.class).add(0, - nodeWithoutMap); - - handleMessage(nodeWithoutMap.getId(), 0); - - // Nothing to assert, just checking that no exception is thrown - } - - @Test - public void returnChannelMapNotInitialized_noInitializedAfterInvocation() { - handleMessage(ui.getElement().getNode().getId(), 0); - - Assert.assertFalse("Feature should not be initialized", - ui.getElement().getNode() - .getFeatureIfInitialized(ReturnChannelMap.class) - .isPresent()); - } - - @Test - public void unregisteredChannel_invocationIgnored() { - ReturnChannelRegistration registration = registerUiChannel(); - registration.remove(); - - handleMessage(registration); - - Assert.assertNull("Channel handler should not be called", - observedArguments.get()); - } - - @Test - public void disabledElement_defaultRegistration_invocationIgnored() { - ReturnChannelRegistration registration = registerUiChannel(); - - ui.setEnabled(false); - - handleMessage(registration); - - Assert.assertNull("Channel handler should not be called", - observedArguments.get()); - } - - @Test - public void disabledElement_registrationAlwaysAllowed_invocationProcessed() { - ReturnChannelRegistration registration = registerUiChannel(); - registration.setDisabledUpdateMode(DisabledUpdateMode.ALWAYS); - - ui.setEnabled(false); - - handleMessage(registration); - - Assert.assertNotNull("Channel handler should be called", - observedArguments.get()); - } - - @Test - public void modalComponent_registrationExists_invocationProcessed() { - ReturnChannelRegistration registration = registerUiChannel(); - - Div modal = new Div(); - ui.addModal(modal); - - handleMessage(registration); - - Assert.assertNotNull("Channel handler should be called", - observedArguments.get()); - } - - @Test - public void modalComponent_unregisteredChannel_invocationIgnored() { - ReturnChannelRegistration registration = registerUiChannel(); - registration.remove(); - - Div modal = new Div(); - ui.addModal(modal); - - handleMessage(registration); - - Assert.assertNull("Channel handler should not be called", - observedArguments.get()); - } - - private void handleMessage(ReturnChannelRegistration registration) { - handleMessage(registration.getStateNodeId(), - registration.getChannelId()); - } - - private ReturnChannelRegistration registerUiChannel() { - ReturnChannelRegistration registration = ui.getElement().getNode() - .getFeature(ReturnChannelMap.class) - .registerChannel(observingConsumer); - return registration; - } - - private void handleMessage(int nodeId, int channelId) { - JsonObject invocationJson = createInvocationJson(nodeId, channelId); - - new ReturnChannelHandler().handle(ui, invocationJson); - } - - private JsonObject createInvocationJson(int stateNodeId, int channelId) { - JsonObject invocationJson = Json.createObject(); - - invocationJson.put(JsonConstants.RPC_NODE, stateNodeId); - invocationJson.put(JsonConstants.RPC_CHANNEL, channelId); - invocationJson.put(JsonConstants.RPC_CHANNEL_ARGUMENTS, args); - - return invocationJson; - } - - @Tag("div") - private class Div extends Component { - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/StringToNumberDecoderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/StringToNumberDecoderTest.java deleted file mode 100644 index a1604736a14..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/communication/rpc/StringToNumberDecoderTest.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.communication.rpc; - -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Assert; -import org.junit.Test; - -import elemental.json.Json; - -public class StringToNumberDecoderTest { - - private StringToNumberDecoder decoder = new StringToNumberDecoder(); - - @Test - public void isApplicable_applicableToStringAndNumber() { - Assert.assertTrue( - decoder.isApplicable(Json.create("foo"), Number.class)); - } - - @Test - public void isApplicable_notApplicableToBooleanAndNumber() { - Assert.assertFalse( - decoder.isApplicable(Json.create(true), Number.class)); - } - - @Test - public void isApplicable_notApplicableToStringAndString() { - Assert.assertFalse( - decoder.isApplicable(Json.create("foo"), String.class)); - } - - @Test - public void isApplicable_notApplicableToStringAndAtomicInteger() { - Assert.assertFalse( - decoder.isApplicable(Json.create("foo"), AtomicInteger.class)); - } - - @Test - public void isApplicable_applicableToStringAndLong() { - Assert.assertTrue(decoder.isApplicable(Json.create("foo"), Long.class)); - } - - @Test - public void stringToInteger_convertableString_valueIsConverted() - throws RpcDecodeException { - Integer expected = 37; - Integer value = decoder.decode(Json.create(String.valueOf(expected)), - Integer.class); - Assert.assertEquals(expected, value); - } - - @Test(expected = RpcDecodeException.class) - public void stringToInteger_nonConvertableString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("abc"), Integer.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToInteger_doubleString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("4.2"), Integer.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToInteger_longString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create(String.valueOf(Long.MAX_VALUE)), - Integer.class); - } - - @Test - public void stringToLong_convertableString_valueIsConverted() - throws RpcDecodeException { - Long expected = 37l; - Long value = decoder.decode(Json.create(String.valueOf(expected)), - Long.class); - Assert.assertEquals(expected, value); - } - - @Test(expected = RpcDecodeException.class) - public void stringToLong_nonConvertableString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("abc"), Long.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToLong_doubleString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("4.2"), Long.class); - } - - @Test - public void stringToShort_convertableString_valueIsConverted() - throws RpcDecodeException { - Short expected = 37; - Short value = decoder.decode(Json.create(String.valueOf(expected)), - Short.class); - Assert.assertEquals(expected, value); - } - - @Test(expected = RpcDecodeException.class) - public void stringToShort_nonConvertableString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("abc"), Short.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToShort_intString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create(Integer.MAX_VALUE), Short.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToShort_doubleString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("4.2"), Short.class); - } - - @Test - public void stringToByte_convertableString_valueIsConverted() - throws RpcDecodeException { - Byte expected = 37; - Byte value = decoder.decode(Json.create(String.valueOf(expected)), - Byte.class); - Assert.assertEquals(expected, value); - } - - @Test(expected = RpcDecodeException.class) - public void stringToByte_nonConvertableString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("abc"), Byte.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToByte_intString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create(Short.MAX_VALUE), Byte.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToByte_doubleString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("4.2"), Byte.class); - } - - @Test - public void stringToFloat_convertableString_valueIsConverted() - throws RpcDecodeException { - Float expected = 37.72f; - Float value = decoder.decode(Json.create(String.valueOf(expected)), - Float.class); - Assert.assertEquals(expected, value); - } - - @Test(expected = RpcDecodeException.class) - public void stringToFloat_doubleString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create(String.valueOf(Double.MIN_NORMAL)), - Float.class); - } - - @Test(expected = RpcDecodeException.class) - public void stringToFloat_nonConvertableString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("abc"), Float.class); - } - - @Test - public void stringToDouble_convertableString_valueIsConverted() - throws RpcDecodeException { - Double expected = 823.6349d; - Double value = decoder.decode(Json.create(String.valueOf(expected)), - Double.class); - Assert.assertEquals(expected, value); - } - - @Test - public void stringToDouble_minDoubleString_valueIsConverted() - throws RpcDecodeException { - // the value is represented in the specific notation. Check that it's - // not a problem - Double expected = Double.MIN_NORMAL; - Double value = decoder.decode(Json.create(String.valueOf(expected)), - Double.class); - Assert.assertEquals(expected, value); - } - - @Test(expected = RpcDecodeException.class) - public void stringToDoublet_nonConvertableString_exceptionIsThrown() - throws RpcDecodeException { - decoder.decode(Json.create("abc"), Double.class); - } - - @Test - public void stringToNumber_convertableString_valueIsConverted() - throws RpcDecodeException { - Double expected = 823.6349d; - Number value = decoder.decode(Json.create(String.valueOf(expected)), - Number.class); - Assert.assertEquals(expected, value); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java deleted file mode 100644 index 2dac2d7dc65..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdateImportsTest.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.OpenOption; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; -import org.slf4j.Logger; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public abstract class AbstractNodeUpdateImportsTest extends NodeUpdateTestUtil { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private File importsFile; - private File generatedPath; - private File frontendDirectory; - private File nodeModulesPath; - private TaskUpdateImports updater; - - private MockLogger logger; - - @Before - public void setup() throws Exception { - File tmpRoot = temporaryFolder.getRoot(); - - logger = new MockLogger(); - - frontendDirectory = new File(tmpRoot, DEFAULT_FRONTEND_DIR); - nodeModulesPath = new File(tmpRoot, NODE_MODULES); - generatedPath = new File(tmpRoot, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - importsFile = new File(generatedPath, IMPORTS_NAME); - - ClassFinder classFinder = getClassFinder(); - updater = new TaskUpdateImports(classFinder, getScanner(classFinder), - finder -> null, tmpRoot, generatedPath, frontendDirectory, null, - null, false, TARGET, true, false, - Mockito.mock(FeatureFlags.class)) { - @Override - Logger log() { - return logger; - } - }; - - assertTrue(nodeModulesPath.mkdirs()); - createExpectedImports(frontendDirectory, nodeModulesPath); - assertTrue( - new File( - new File( - new File(frontendDirectory, - FrontendUtils.GENERATED), - FrontendUtils.JAR_RESOURCES_FOLDER), - "ExampleConnector.js").exists()); - } - - protected abstract FrontendDependenciesScanner getScanner( - ClassFinder finder); - - @Test - public void generateImportsFile_fileContainsThemeLinesAndExpectedImportsAndCssImportLinesAndLogReports() - throws Exception { - List expectedLines = new ArrayList<>(Arrays.asList( - "export const addCssBlock = function(block, before = false) {", - " const tpl = document.createElement('template');", - " tpl.innerHTML = block;", - " document.head[before ? 'insertBefore' : 'appendChild'](tpl.content, document.head.firstChild);", - "};", - "addCssBlock('', true);", - "document.documentElement.setAttribute('theme', 'dark');")); - expectedLines.addAll(getExpectedImports()); - - // An import without `.js` extension - expectedLines.add( - "import '@vaadin/vaadin-mixed-component/theme/lumo/vaadin-something-else'"); - // An import not found in node_modules - expectedLines.add("import 'unresolved/component';"); - - expectedLines.add( - "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css?inline'"); - expectedLines - .add("import $cssFromFile_1 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_2 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_3 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_4 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_5 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_6 from 'Frontend/foo.css?inline';"); - expectedLines.add( - "import { css, unsafeCSS, registerStyles } from '@vaadin/vaadin-themable-mixin';"); - expectedLines.add("addCssBlock(``);"); - expectedLines.add("addCssBlock(``);"); - expectedLines.add( - "addCssBlock(``);"); - expectedLines.add("registerStyles('', $css_3, {moduleId: 'baz'});"); - expectedLines.add( - "registerStyles('', $css_4, {include: 'bar', moduleId: 'baz'});"); - expectedLines.add( - "registerStyles('foo-bar', $css_5, {moduleId: 'flow_css_mod_5'});"); - expectedLines.add( - "registerStyles('foo-bar', $css_6, {include: 'bar', moduleId: 'flow_css_mod_6'});"); - - assertFalse(importsFile.exists()); - - updater.execute(); - assertTrue(importsFile.exists()); - - assertContainsImports(true, expectedLines.toArray(new String[0])); - - String output = logger.getLogs(); - assertContains(output, true, - "Use the './' prefix for files in JAR files: 'ExampleConnector.js'", - "Use the './' prefix for files in the '" - + frontendDirectory.getPath() - + "' folder: 'vaadin-mixed-component/theme/lumo/vaadin-mixed-component.js'"); - - // Using regex match because of the ➜ character in TC - assertContains(output, true, - "Failed to find the following imports in the `node_modules` tree:\n - unresolved/component"); - } - - @Test - public void noChanges_generatedJsFileIsNotUpdated() throws Exception { - updater.execute(); - long timestamp1 = importsFile.lastModified(); - - // need to sleep because timestamp is in seconds - sleep(1000); - updater.execute(); - long timestamp2 = importsFile.lastModified(); - - Assert.assertEquals(timestamp1, timestamp2); - } - - @Test - public void removeJsModuleImportFromFile_importIsReadedAfterRegeneration() - throws Exception { - updater.execute(); - removeImports("@vaadin/vaadin-lumo-styles/sizing.js", - "./local-template.js"); - assertContainsImports(false, "@vaadin/vaadin-lumo-styles/sizing.js", - "./local-template.js"); - - updater.execute(); - assertContainsImports(true, "@vaadin/vaadin-lumo-styles/sizing.js", - "./local-template.js"); - } - - @Test - public void addModuleImportManuallyIntoGeneratedFile_importIsRemovedAfterRegeneration() - throws Exception { - updater.execute(); - addImports("./added-import.js"); - assertContainsImports(true, "./added-import.js"); - - updater.execute(); - assertContainsImports(false, "./added-import.js"); - } - - @Test - public void addAndRemoveJsModuleImports_addedImportIsNotPreseredAfterRegeneration() - throws Exception { - updater.execute(); - - removeImports("@vaadin/vaadin-lumo-styles/sizing.js", - "./local-template.js"); - addImports("./added-import.js"); - - assertContainsImports(false, "@vaadin/vaadin-lumo-styles/sizing.js", - "./local-template.js"); - assertContainsImports(true, "./added-import.js"); - - updater.execute(); - - assertContainsImports(false, "./added-import.js"); - } - - @Test - public void addJsModules_themeModulesAreOnTop() throws Exception { - updater.execute(); - - addImports("styles/styles.js"); - - assertImportOrder("@vaadin/vaadin-lumo-styles/color.js", - "Frontend/foo.js"); - assertImportOrder("@vaadin/vaadin-lumo-styles/color.js", - "styles/styles.js"); - } - - private void assertContainsImports(boolean contains, String... imports) - throws IOException { - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - for (String line : imports) { - assertContains(content, contains, addWebpackPrefix(line)); - } - } - - private void assertContains(String content, boolean contains, - String... checks) { - for (String importString : checks) { - boolean result = content.contains(importString); - String message = "\n " + (contains ? "NOT " : "") + "FOUND '" - + importString + " IN: \n" + content; - if (contains) { - assertTrue(message, result); - } else { - assertFalse(message, result); - } - } - } - - private void assertImportOrder(String... imports) throws IOException { - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - int curIndex = -1; - for (String line : imports) { - String prefixed = addWebpackPrefix(line); - int nextIndex = content.indexOf(prefixed); - assertTrue("import '" + prefixed + "' not found", nextIndex != -1); - assertTrue("import '" + prefixed + "' appears in the wrong order", - curIndex <= nextIndex); - curIndex = nextIndex; - } - } - - private void removeImports(String... imports) throws IOException { - List importsList = Arrays.asList(imports); - - List current = FileUtils.readLines(importsFile, - Charset.defaultCharset()); - - Set removed = current - .stream().filter(line -> importsList.stream() - .map(this::addWebpackPrefix).anyMatch(line::contains)) - .collect(Collectors.toSet()); - - current.removeAll(removed); - - String content = String.join("\n", current); - - replaceJsFile(content + "\n"); - } - - private void addImports(String... imports) throws IOException { - String content = Arrays.stream(imports).map(this::addWebpackPrefix) - .map(s -> "import '" + s + "';") - .collect(Collectors.joining("\n")); - - replaceJsFile(content + "\n", StandardOpenOption.APPEND); - } - - private void replaceJsFile(String content, OpenOption... options) - throws IOException { - Files.write(Paths.get(importsFile.toURI()), - content.getBytes(StandardCharsets.UTF_8), options); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdatePackagesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdatePackagesTest.java deleted file mode 100644 index b54afc8edfc..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractNodeUpdatePackagesTest.java +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.Platform; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; -import com.vaadin.flow.testutil.FrontendStubs; - -import elemental.json.Json; -import elemental.json.JsonObject; -import static com.vaadin.flow.server.Constants.PACKAGE_JSON; -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEP_NAME_FLOW_DEPS; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEP_NAME_FLOW_JARS; -import static com.vaadin.flow.server.frontend.NodeUpdater.VAADIN_DEP_KEY; -import static com.vaadin.flow.server.frontend.TaskUpdatePackages.VAADIN_APP_PACKAGE_HASH; -import static elemental.json.impl.JsonUtil.stringify; -import static java.nio.charset.StandardCharsets.UTF_8; - -public abstract class AbstractNodeUpdatePackagesTest - extends NodeUpdateTestUtil { - - private static final String DEPENDENCIES = "dependencies"; - private static final String DEV_DEPENDENCIES = "devDependencies"; - private static final String VAADIN_VERSION = "vaadinVersion"; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private TaskUpdatePackages packageUpdater; - private TaskGeneratePackageJson packageCreator; - private File baseDir; - private File generatedDir; - - private File packageJson; - - private ClassFinder classFinder; - - private File mainNodeModules; - private File packageLock; - private File appNodeModules; - private FeatureFlags featureFlags; - private File jarResourceFolder = null; - - @Before - public void setup() throws Exception { - baseDir = temporaryFolder.getRoot(); - - featureFlags = Mockito.mock(FeatureFlags.class); - - generatedDir = new File(baseDir, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - - FrontendStubs.createStubNode(true, true, baseDir.getAbsolutePath()); - - packageCreator = new TaskGeneratePackageJson(baseDir, generatedDir, - TARGET, featureFlags); - - classFinder = Mockito.spy(getClassFinder()); - File versions = temporaryFolder.newFile(); - FileUtils.write(versions, "{}", StandardCharsets.UTF_8); - Mockito.when( - classFinder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versions.toURI().toURL()); - - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, false, TARGET, featureFlags); - packageJson = new File(baseDir, PACKAGE_JSON); - - mainNodeModules = new File(baseDir, FrontendUtils.NODE_MODULES); - appNodeModules = new File(generatedDir, FrontendUtils.NODE_MODULES); - packageLock = new File(baseDir, "package-lock.json"); - - } - - protected abstract FrontendDependenciesScanner getScanner( - ClassFinder finder); - - @Test - public void should_CreatePackageJson() { - Assert.assertFalse(packageJson.exists()); - packageCreator.execute(); - Assert.assertTrue(packageJson.exists()); - } - - @Test - public void should_not_ModifyPackageJson_WhenAlreadyExists() { - packageCreator.execute(); - Assert.assertTrue(packageCreator.modified); - - packageCreator.execute(); - Assert.assertFalse(packageCreator.modified); - } - - @Test - public void should_AddNewDependencies() throws Exception { - packageCreator.execute(); - packageUpdater.execute(); - Assert.assertTrue(packageCreator.modified); - Assert.assertTrue(packageUpdater.modified); - assertMainPackageJsonContent(); - } - - @Test - public void pnpmIsInUse_packageJsonContainsFlowDeps_removeFlowDeps() - throws IOException { - // use package updater with disabled PNPM - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, false, TARGET, featureFlags); - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - // Add flowDeps - JsonObject json = packageUpdater.getPackageJson(); - getDependencies(json).put(DEP_NAME_FLOW_DEPS, "target/frontend"); - json.put(VAADIN_APP_PACKAGE_HASH, - "e05bfd4b6c6bd20c806b3a0ad1be521bfd775c9b6f8f9c997b0ad1fda834805b"); - Files.write(packageJson.toPath(), - Collections.singletonList(json.toJson())); - - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, true, TARGET, featureFlags); - packageUpdater.execute(); - - assertPackageJsonFlowDeps(); - } - - @Test - public void pnpmIsInUse_packageJsonContainsFlowFrontend_removeFlowFrontend() - throws IOException { - // use package updater with disabled PNPM - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, false, TARGET, featureFlags); - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - // Add old dep - JsonObject json = packageUpdater.getPackageJson(); - getDependencies(json).put(DEP_NAME_FLOW_JARS, "target/flow-frontend"); - json.put(VAADIN_APP_PACKAGE_HASH, - "e05bfd4b6c6bd20c806b3a0ad1be521bfd775c9b6f8f9c997b0ad1fda834805b"); - Files.write(packageJson.toPath(), - Collections.singletonList(json.toJson())); - - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, jarResourceFolder, - generatedDir, false, true, TARGET, featureFlags); - packageUpdater.execute(); - - assertPackageJsonFlowDeps(); - } - - @Test - public void pnpmIsInUse_packageLockExists_removePackageLock() - throws IOException { - // use package updater with disabled PNPM - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, false, TARGET, featureFlags); - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - Files.write(packageLock.toPath(), Collections.singletonList("{}")); - - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, true, TARGET, featureFlags); - packageUpdater.execute(); - Assert.assertFalse("npm package-lock should be removed for pnpm", - packageLock.exists()); - } - - @Test - public void pnpmIsInUse_packageJsonModified_removePnpmLock() - throws IOException { - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, true, TARGET, featureFlags); - packageCreator.execute(); - File pnpmLock = new File(baseDir, "pnpm-lock.yaml"); - pnpmLock.createNewFile(); - packageUpdater.execute(); - Assert.assertFalse(pnpmLock.exists()); - } - - @Test - public void npmIsInUse_packageJsonContainsFlowDeps_removeFlowDeps() - throws IOException { - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - JsonObject packJsonObject = getPackageJson(packageJson); - JsonObject deps = packJsonObject.get(DEPENDENCIES); - deps.put(DEP_NAME_FLOW_DEPS, "foobar"); - - writePackageJson(packageJson, packJsonObject); - - packageUpdater.execute(); - - assertPackageJsonFlowDeps(); - } - - @Test - public void npmIsInUse_packageJsonContainsFlowFrontend_removeFlowFrontend() - throws IOException { - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - JsonObject packJsonObject = getPackageJson(packageJson); - JsonObject deps = packJsonObject.get(DEPENDENCIES); - deps.put(DEP_NAME_FLOW_JARS, "foobar"); - - writePackageJson(packageJson, packJsonObject); - - packageUpdater.execute(); - - assertPackageJsonFlowDeps(); - } - - @Test - public void npmIsInUse_packageLockJsonContainsNonPMPMDeps_packageLockNotRemoved() - throws IOException { - // use package updater with disabled PNPM - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - Files.write(packageLock.toPath(), Collections.singletonList("{ }")); - - packageUpdater.execute(); - Assert.assertTrue(packageLock.exists()); - } - - // Some npm-dependency pinning tests are in TaskRunNpmInstallTest - - @Test - public void unmatchedDevDependency_devDependencyIsRemoved() - throws IOException { - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - // Change the version - JsonObject json = packageUpdater.getPackageJson(); - final String old_dependency = "old_dependency"; - json.getObject(VAADIN_DEP_KEY).getObject(DEV_DEPENDENCIES) - .put(old_dependency, "1.1.1"); - json.getObject(DEV_DEPENDENCIES).put(old_dependency, "1.1.1"); - - Files.write(packageJson.toPath(), - Collections.singletonList(json.toJson())); - - // run it again with existing generated package.json and mismatched - // versions - packageUpdater.execute(); - - json = packageUpdater.getPackageJson(); - Assert.assertFalse("Old dev dependency should be removed from vaadin", - json.getObject(VAADIN_DEP_KEY).getObject(DEV_DEPENDENCIES) - .hasKey(old_dependency)); - Assert.assertFalse( - "Old dev dependency should be removed from devDependencies", - json.getObject(DEV_DEPENDENCIES).hasKey(old_dependency)); - } - - @Test // #10032 - public void oldVaadinDevDependency_missmatchWithDevDependency_vaadinDependencyIsUpdated() - throws IOException { - // Generate package json in a proper format first - packageCreator.execute(); - - // Change the version - JsonObject json = packageUpdater.getPackageJson(); - final String key = "vite"; - final String version = packageUpdater.getDefaultDevDependencies() - .get(key); - json.getObject(VAADIN_DEP_KEY).getObject(DEV_DEPENDENCIES).put(key, - "v2.8.0"); - json.getObject(DEV_DEPENDENCIES).put(key, version); - - Files.write(packageJson.toPath(), - Collections.singletonList(json.toJson())); - - // run it again to see that versions are updated - packageCreator.execute(); - - json = packageUpdater.getPackageJson(); - Assert.assertEquals( - "Vaadin dependency should be updated to latest DevDependency", - version, json.getObject(VAADIN_DEP_KEY) - .getObject(DEV_DEPENDENCIES).getString(key)); - Assert.assertEquals("DevDependency should stay the same as it was", - version, json.getObject(DEV_DEPENDENCIES).getString(key)); - } - - @Test - public void versionsDoNotMatch_inVaadinJson_cleanUpNpm() - throws IOException { - // Generate package json in a proper format first - packageCreator.execute(); - - makeNodeModulesAndPackageLock(); - - packageUpdater.updateVaadinJsonContents( - Collections.singletonMap(VAADIN_VERSION, "1.1.1")); - - try (MockedStatic platform = Mockito - .mockStatic(Platform.class)) { - platform.when(Platform::getVaadinVersion) - .thenReturn(Optional.of("1.2.3")); - packageUpdater.execute(); - assertCleanUp(); - } - } - - @Test - public void versionsDoNotMatch_inVaadinJson_cleanUpPnpm() - throws IOException { - packageUpdater = new TaskUpdatePackages(classFinder, - Mockito.mock(FrontendDependencies.class), baseDir, generatedDir, - jarResourceFolder, false, true, TARGET, featureFlags); - - // Generate package json in a proper format first - packageCreator.execute(); - - makeNodeModulesAndPackageLock(); - - packageUpdater.updateVaadinJsonContents( - Collections.singletonMap(VAADIN_VERSION, "1.1.1")); - - try (MockedStatic platform = Mockito - .mockStatic(Platform.class)) { - platform.when(Platform::getVaadinVersion) - .thenReturn(Optional.of("1.2.3")); - packageUpdater.execute(); - // nothing is removed except package-lock - Assert.assertTrue(mainNodeModules.exists()); - Assert.assertTrue(appNodeModules.exists()); - // package-lock is removed - Assert.assertFalse(packageLock.exists()); - } - } - - @Test - public void versionsMatch_noCleanUp() throws IOException { - // TODO: Fixme - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - // packages.put(VAADIN_CORE, "1.1.1"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - // Generate package json in a proper format first - packageCreator.execute(); - - makeNodeModulesAndPackageLock(); - - Files.write(packageLock.toPath(), - Collections.singletonList(stringify(makePackageLock("1.1.1")))); - - packageUpdater.execute(); - - // nothing is removed - Assert.assertTrue(mainNodeModules.exists()); - Assert.assertTrue(appNodeModules.exists()); - Assert.assertTrue(packageLock.exists()); - } - - @Test - public void versionsMatch_forceCleanUp_cleanUp() throws IOException { - // Generate package json in a proper format first - packageCreator.execute(); - packageUpdater.execute(); - - makeNodeModulesAndPackageLock(); - - ClassFinder classFinder = getClassFinder(); - // create a new package updater, with forced clean up enabled - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, true, false, TARGET, featureFlags); - packageUpdater.execute(); - - // clean up happened - assertCleanUp(); - } - - @Test - public void generatePackageJson_sameDependencies_updaterIsNotModified() { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - // generate it one more time, the content will be different since - // packageCreator has not added its content - packageUpdater.execute(); - - Assert.assertFalse( - "Modification flag should be false when no dependencies changed.", - packageUpdater.modified); - } - - @Test - public void generatePackageJson_sameDependenciesInDifferentOrder_updaterIsNotModified() - throws IOException { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - // Shuffle the dependencies. - JsonObject json = getPackageJson(this.packageJson); - JsonObject dependencies = json.getObject(DEPENDENCIES); - List dependencyKeys = Arrays.asList(dependencies.keys()); - - Collections.shuffle(dependencyKeys); - - JsonObject newDependencies = Json.createObject(); - dependencyKeys.forEach( - key -> newDependencies.put(key, dependencies.getString(key))); - - json.put(DEPENDENCIES, newDependencies); - - Files.write(this.packageJson.toPath(), - Collections.singletonList(stringify(json))); - - // generate it one more time, the content will be different since - // packageCreator has not added its content - packageUpdater.execute(); - - Assert.assertFalse( - "Modification flag should be false when no dependencies changed.", - packageUpdater.modified); - } - - @Test - public void generatePackageJson_removedDependencies_updaterIsModified() { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - packages.remove("@vaadin/vaadin-checkbox"); - - // generate it one more time, the content will be different since - // packageCreator has not added its content - packageUpdater.execute(); - - Assert.assertTrue( - "Modification flag should be true when dependency removed.", - packageUpdater.modified); - } - - @Test - public void generatePackageJson_addedDependencies_updaterIsModified() { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - packages.put("@vaadin/vaadin-list-box", "1.1.1"); - - packageUpdater.execute(); - - Assert.assertTrue( - "Modification flag should be true when dependency added.", - packageUpdater.modified); - } - - @Test - public void generatePackageJson_noDependencies_updaterIsNotModified() { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - Assert.assertTrue( - "Modification flag should be true as we have added default dependencies.", - packageUpdater.modified); - - // generate it one more time - packageUpdater.execute(); - - Assert.assertFalse( - "Modification flag should be false when there has never been dependencies.", - packageUpdater.modified); - } - - @Test - public void updatedPackageJson_noDependencies_creatorAndUpdatedIsMarkedModified() { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - Assert.assertTrue( - "Modification flag should be true when main package was created.", - packageCreator.modified); - Assert.assertTrue( - "Modification flag should be true as we should have updated the hash for default dependencies.", - packageUpdater.modified); - } - - @Test - public void userAddedDependencies_notCleanedByUpdater() throws IOException { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - JsonObject json = getPackageJson(packageJson); - json.getObject(DEPENDENCIES).put("@custom/timer", "3.3.0"); - - Files.write(packageJson.toPath(), - Collections.singletonList(json.toJson())); - - packageUpdater.execute(); - - JsonObject dependencies = getPackageJson(packageJson) - .getObject(DEPENDENCIES); - Assert.assertTrue(dependencies.hasKey("@custom/timer")); - Assert.assertEquals("3.3.0", dependencies.getString("@custom/timer")); - } - - @Test - public void legacyPackageJson_isCleanedCorrectly_pnpm() throws IOException { - String legacyPackageContent = getLegacyPackageContent(); - - Files.write(packageJson.toPath(), - Collections.singletonList(legacyPackageContent)); - - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, true, TARGET, featureFlags); - packageUpdater.execute(); - - assertPackageJsonFlowDeps(); - } - - @Test - public void legacyPackageJson_isCleanedCorrectly_npm() throws IOException { - String legacyPackageContent = getLegacyPackageContent(); - - Files.write(packageJson.toPath(), - Collections.singletonList(legacyPackageContent)); - - packageUpdater = new TaskUpdatePackages(classFinder, - getScanner(classFinder), baseDir, generatedDir, - jarResourceFolder, false, false, TARGET, featureFlags); - packageUpdater.execute(); - - assertPackageJsonFlowDeps(); - } - - @Test - public void frameworkManagedPackages_versionsAreUpdated() - throws IOException { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - JsonObject dependencies = getPackageJson(packageJson) - .getObject(DEPENDENCIES); - for (Map.Entry entry : packages.entrySet()) { - Assert.assertTrue(dependencies.hasKey(entry.getKey())); - Assert.assertEquals(entry.getValue(), - dependencies.getString(entry.getKey())); - } - - packages.clear(); - packages.put("@polymer/iron-list", "3.1.0"); - packages.put("@vaadin/vaadin-confirm-dialog", "2.0.0"); - packages.put("@vaadin/vaadin-checkbox", "3.1.1"); - packages.put("@polymer/iron-icon", "3.0.3"); - packages.put("@vaadin/vaadin-time-picker", "2.0.3"); - - packageUpdater.execute(); - - dependencies = getPackageJson(packageJson).getObject(DEPENDENCIES); - for (Map.Entry entry : packages.entrySet()) { - Assert.assertTrue(dependencies.hasKey(entry.getKey())); - Assert.assertEquals(entry.getValue(), - dependencies.getString(entry.getKey())); - } - } - - @Test - public void removedFrameworkDependencies_dependencyIsRemoved() - throws IOException { - FrontendDependencies frontendDependencies = Mockito - .mock(FrontendDependencies.class); - - Map packages = new HashMap<>(); - packages.put("@polymer/iron-list", "3.0.2"); - packages.put("@vaadin/vaadin-confirm-dialog", "1.1.4"); - packages.put("@vaadin/vaadin-checkbox", "2.2.10"); - packages.put("@polymer/iron-icon", "3.0.1"); - packages.put("@vaadin/vaadin-time-picker", "2.0.2"); - - Mockito.when(frontendDependencies.getPackages()).thenReturn(packages); - - packageUpdater = new TaskUpdatePackages(classFinder, - frontendDependencies, baseDir, generatedDir, jarResourceFolder, - false, false, TARGET, featureFlags); - - packageCreator.execute(); - packageUpdater.execute(); - - packages.remove("@vaadin/vaadin-checkbox"); - - JsonObject dependencies = getPackageJson(packageJson) - .getObject(DEPENDENCIES); - Assert.assertTrue("vaadin-checkbox is missing from the dependencies", - dependencies.hasKey("@vaadin/vaadin-checkbox")); - - dependencies = getPackageJson(packageJson).getObject(VAADIN_DEP_KEY) - .getObject(DEPENDENCIES); - Assert.assertTrue("vaadin-checkbox is missing from vaadin.dependencies", - dependencies.hasKey("@vaadin/vaadin-checkbox")); - - // generate it one more time, this should remove the checkbox - packageUpdater.execute(); - - dependencies = getPackageJson(packageJson).getObject(DEPENDENCIES); - Assert.assertFalse( - "vaadin-checkbox is still available in the dependencies", - dependencies.hasKey("@vaadin/vaadin-checkbox")); - - dependencies = getPackageJson(packageJson).getObject(VAADIN_DEP_KEY) - .getObject(DEPENDENCIES); - Assert.assertFalse( - "vaadin-checkbox is still available in vaadin.dependencies", - dependencies.hasKey("@vaadin/vaadin-checkbox")); - - } - - public String getLegacyPackageContent() { - return "{\n" + " \"name\": \"no-name\",\n" - + " \"license\": \"UNLICENSED\",\n" + " \"vaadin\": {\n" - + " \"dependencies\": {\n" - + " \"@vaadin/router\": \"^1.6.0\",\n" - + " \"@polymer/polymer\": \"3.4.1\",\n" - + " \"@vaadin/vaadin-ordered-layout\": \"1.1.0\",\n" - + " \"@vaadin/vaadin-combo-box\": \"5.0.11\",\n" - + " \"@vaadin/vaadin-lumo-styles\": \"1.6.0\",\n" - + " \"@vaadin/vaadin-material-styles\": \"1.3.2\"\n" - + " },\n" + " \"devDependencies\": {\n" - + " \"webpack-dev-server\": \"3.10.3\"\n" + " },\n" - + " \"hash\": \"72bdea1adb5aa0d1259db10a6f76872d996db31d2c312d0c7849eb39de92835e\"\n" - + " },\n" + " \"dependencies\": {\n" - + " \"@vaadin/router\": \"^1.6.0\",\n" - + " \"@polymer/polymer\": \"3.4.1\",\n" - + " \"@vaadin/flow-deps\": \"./target/frontend\",\n" - + " \"@vaadin/vaadin-ordered-layout\": \"1.1.0\",\n" - + " \"@vaadin/vaadin-combo-box\": \"5.0.11\",\n" - + " \"@vaadin/vaadin-lumo-styles\": \"1.6.0\",\n" - + " \"@vaadin/vaadin-material-styles\": \"1.3.2\"\n" - + " },\n" + " \"devDependencies\": {\n" - + " \"webpack-dev-server\": \"3.10.3\"\n" + " },\n" - + "\"vaadinAppPackageHash\": \"e05bfd4b6c6bd20c806b3a0ad1be521bfd775c9b6f8f9c997b0ad1fda834805b\"\n" - + "}\n"; - } - - private void makeNodeModulesAndPackageLock() throws IOException { - // Make two node_modules folders and package lock - mainNodeModules.mkdirs(); - appNodeModules.mkdirs(); - Files.write(packageLock.toPath(), Collections.singletonList("{}")); - - // self control - Assert.assertTrue(mainNodeModules.exists()); - Assert.assertTrue(appNodeModules.exists()); - Assert.assertTrue(packageLock.exists()); - } - - private void assertCleanUp() { - Assert.assertFalse(mainNodeModules.exists()); - Assert.assertFalse(appNodeModules.exists()); - Assert.assertTrue("package-lock should not be removed", - packageLock.exists()); - } - - private void assertMainPackageJsonContent() throws IOException { - JsonObject json = packageUpdater.getPackageJson(); - Assert.assertTrue(json.hasKey("name")); - Assert.assertTrue(json.hasKey("license")); - - JsonObject dependencies = json.getObject(DEPENDENCIES); - for (Map.Entry entry : packageUpdater - .getDefaultDependencies().entrySet()) { - Assert.assertTrue("Missing '" + entry.getKey() + "' package", - dependencies.hasKey(entry.getKey())); - } - - JsonObject devDependencies = json.getObject(DEV_DEPENDENCIES); - for (Map.Entry entry : packageUpdater - .getDefaultDevDependencies().entrySet()) { - Assert.assertTrue("Missing '" + entry.getKey() + "' package", - devDependencies.hasKey(entry.getKey())); - } - - Assert.assertFalse(dependencies.hasKey(DEP_NAME_FLOW_JARS)); - } - - private JsonObject getDependencies(JsonObject json) { - return json.getObject(DEPENDENCIES); - } - - private JsonObject makePackageLock(String version) { - JsonObject object = Json.createObject(); - JsonObject deps = Json.createObject(); - JsonObject shrinkWrap = Json.createObject(); - object.put(DEPENDENCIES, deps); - shrinkWrap.put("version", version); - return object; - } - - private void assertPackageJsonFlowDeps() throws IOException { - JsonObject packJsonObject = getPackageJson(packageJson); - JsonObject deps = packJsonObject.get(DEPENDENCIES); - // No Flow deps - Assert.assertFalse(deps.hasKey(DEP_NAME_FLOW_DEPS)); - // No Flow resources - Assert.assertFalse(deps.hasKey(DEP_NAME_FLOW_JARS)); - // No old package hash - Assert.assertFalse(deps.hasKey(VAADIN_APP_PACKAGE_HASH)); - // Contains initially generated default polymer dep - Assert.assertTrue(deps.hasKey("@polymer/polymer")); - // Contains new hash - Assert.assertTrue(packJsonObject.getObject("vaadin").hasKey("hash")); - } - - JsonObject getPackageJson(File packageFile) throws IOException { - JsonObject packageJson = null; - if (packageFile.exists()) { - String fileContent = FileUtils.readFileToString(packageFile, - UTF_8.name()); - packageJson = Json.parse(fileContent); - } - return packageJson; - } - - void writePackageJson(File packageJsonFile, JsonObject packageJson) - throws IOException { - FileUtils.writeStringToFile(packageJsonFile, packageJson.toJson(), - UTF_8.name()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractTaskClientGeneratorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractTaskClientGeneratorTest.java deleted file mode 100644 index c56cafb84c6..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractTaskClientGeneratorTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Test; - -public class AbstractTaskClientGeneratorTest { - - private static final String TEST_STRING = "Hello world"; - - @Test - public void writeIfChanged_writesWithChanges() throws Exception { - File f = File.createTempFile("writeIfChanged", "aaa"); - FileUtils.write(f, TEST_STRING, StandardCharsets.UTF_8); - - Assert.assertTrue(AbstractTaskClientGenerator.writeIfChanged(f, - TEST_STRING + "2")); - } - - @Test - public void writeIfChanged_doesNotWriteWithoutChanges() throws Exception { - File f = File.createTempFile("writeIfChanged", "aaa"); - FileUtils.write(f, TEST_STRING, StandardCharsets.UTF_8); - Assert.assertFalse( - AbstractTaskClientGenerator.writeIfChanged(f, TEST_STRING)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java deleted file mode 100644 index 8e399aa1ae9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/AbstractUpdateImportsTest.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; -import org.mockito.internal.util.collections.Sets; -import org.slf4j.Logger; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.CssData; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.ThemeDefinition; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES; -import static com.vaadin.flow.server.frontend.FrontendUtils.TOKEN_FILE; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public abstract class AbstractUpdateImportsTest extends NodeUpdateTestUtil { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Route(value = "simplecss") - @CssImport("./foo.css") - public static class SimpleCssImport extends Component { - - } - - private File tmpRoot; - private File generatedPath; - private File frontendDirectory; - private File nodeModulesPath; - private UpdateImports updater; - - private MockLogger logger; - - private static final String ERROR_MSG = "foo-bar-baz"; - - private FeatureFlags featureFlags; - - private class UpdateImports extends AbstractUpdateImports { - - private final ClassFinder finder; - private final FrontendDependenciesScanner scanner; - private List resultingLines; - - UpdateImports(ClassFinder classFinder, - FrontendDependenciesScanner scanner, File npmDirectory, - File tokenFile, boolean productionMode, - FeatureFlags featureFlags) { - super(frontendDirectory, npmDirectory, generatedPath, tokenFile, - productionMode, false, featureFlags); - this.scanner = scanner; - finder = classFinder; - } - - @Override - protected void writeImportLines(List lines) { - resultingLines = lines; - } - - @Override - protected Collection getThemeLines() { - return Arrays.asList("theme-line-foo", "theme-line-bar"); - } - - @Override - protected List getModules() { - return scanner.getModules(); - } - - @Override - protected Set getScripts() { - return scanner.getScripts(); - } - - @Override - protected URL getResource(String name) { - return finder.getResource(name); - } - - @Override - protected Collection getGeneratedModules() { - return Arrays.asList("generated-modules-foo", - "generated-modules-bar"); - } - - @Override - protected ThemeDefinition getThemeDefinition() { - return scanner.getThemeDefinition(); - } - - @Override - protected AbstractTheme getTheme() { - return scanner.getTheme(); - } - - @Override - protected Set getCss() { - return scanner.getCss(); - } - - @Override - protected Logger getLogger() { - return logger; - } - - @Override - protected String getImportsNotFoundMessage() { - return ERROR_MSG; - } - } - - @Before - public void setup() throws Exception { - tmpRoot = temporaryFolder.getRoot(); - - logger = new MockLogger(); - - frontendDirectory = new File(tmpRoot, DEFAULT_FRONTEND_DIR); - nodeModulesPath = new File(tmpRoot, NODE_MODULES); - generatedPath = new File(tmpRoot, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - File tokenFile = new File(tmpRoot, TOKEN_FILE); - - ClassFinder classFinder = getClassFinder(); - featureFlags = Mockito.mock(FeatureFlags.class); - updater = new UpdateImports(classFinder, getScanner(classFinder), - tmpRoot, tokenFile, true, featureFlags); - assertTrue(nodeModulesPath.mkdirs()); - createExpectedImports(frontendDirectory, nodeModulesPath); - assertTrue( - new File( - new File( - new File(frontendDirectory, - FrontendUtils.GENERATED), - FrontendUtils.JAR_RESOURCES_FOLDER), - "ExampleConnector.js").exists()); - } - - protected abstract FrontendDependenciesScanner getScanner( - ClassFinder finder); - - @Test - public void importsFilesAreNotFound_throws() { - deleteExpectedImports(frontendDirectory, nodeModulesPath); - exception.expect(IllegalStateException.class); - updater.run(); - } - - @Test - public void getModuleLines_npmPackagesDontExist_logExplanation() { - boolean atLeastOneRemoved = false; - for (String imprt : getExpectedImports()) { - if (imprt.startsWith("@vaadin") && imprt.endsWith(".js")) { - assertTrue(resolveImportFile(nodeModulesPath, nodeModulesPath, - imprt).delete()); - atLeastOneRemoved = true; - } - } - assertTrue(atLeastOneRemoved); - updater.run(); - - MatcherAssert.assertThat(logger.getLogs(), - CoreMatchers.allOf( - CoreMatchers.containsString( - "@vaadin/vaadin-lumo-styles/spacing.js"), - CoreMatchers.containsString(ERROR_MSG))); - } - - @Test - public void getModuleLines_oneFrontendDependencyDoesntExist_throwExceptionAndlogExplanation() { - String fooFileName = "./foo.js"; - assertFileRemoved(fooFileName, frontendDirectory); - - try { - updater.run(); - Assert.fail("Execute should have failed with missing file"); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), - CoreMatchers - .containsString(getFormattedFrontendErrorMessage( - Sets.newSet(fooFileName)))); - } - - } - - @Test - public void getModuleLines_oneFrontendDependencyAndFrontendDirectoryDontExist_throwExceptionAdvisingUserToRunPrepareFrontend() - throws Exception { - ClassFinder classFinder = getClassFinder(); - updater = new UpdateImports(classFinder, getScanner(classFinder), - tmpRoot, null, true, featureFlags); - - Files.move(frontendDirectory.toPath(), - new File(tmpRoot, "_frontend").toPath()); - - try { - updater.run(); - Assert.fail( - "Execute should have failed with advice to run `prepare-frontend`"); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), CoreMatchers.containsString( - "Unable to locate frontend resources and missing token file. " - + "Please run the `prepare-frontend` Vaadin plugin goal before deploying the application")); - } - } - - @Test - public void getModuleLines_multipleFrontendDependencyDoesntExist_throwExceptionAndlogExplanation() { - String localTemplateFileName = "./local-template.js"; - String fooFileName = "./foo.js"; - - assertFileRemoved(localTemplateFileName, frontendDirectory); - assertFileRemoved(fooFileName, frontendDirectory); - - try { - updater.run(); - Assert.fail("Execute should have failed with missing files"); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), CoreMatchers - .containsString(getFormattedFrontendErrorMessage( - Sets.newSet(localTemplateFileName, fooFileName)))); - } - - } - - private void assertFileRemoved(String fileName, File directory) { - assertTrue(String.format( - "File `%s` was not removed from, or does not exist in, `%s`", - fileName, directory), - resolveImportFile(directory, directory, fileName).delete()); - } - - private String getFormattedFrontendErrorMessage( - Set resourcesNotFound) { - String prefix = "Failed to find the following files: "; - - String suffix = String.format("%n Locations searched were:" - + "%n - `%s` in this project" - + "%n - `%s` in included JARs" - + "%n - `%s` in included JARs" - + "%n%n Please, double check that those files exist. If you use a custom directory " - + "for your resource files instead of default " - + "`frontend` folder then make sure you it's correctly configured " - + "(e.g. set '%s' property)", frontendDirectory.getPath(), - Constants.RESOURCES_FRONTEND_DEFAULT, - Constants.COMPATIBILITY_RESOURCES_FRONTEND_DEFAULT, - FrontendUtils.PARAM_FRONTEND_DIR); - - return String.format("%n%n %s%n - %s%n %s%n%n", prefix, - String.join("\n - ", resourcesNotFound), suffix); - } - - @Test - public void generateLines_resultingLinesContainsThemeLinesAndExpectedImportsAndCssLinesAndGeneratedImportsAndLoggerReports() - throws Exception { - List expectedLines = new ArrayList<>( - Arrays.asList("theme-line-foo", "theme-line-bar")); - getExpectedImports().stream().filter(imp -> imp.equals("/foo.css")) - .forEach(imp -> expectedLines - .add("import '" + addWebpackPrefix(imp) + "';")); - - // An import without `.js` extension - expectedLines.add( - "import '@vaadin/vaadin-mixed-component/theme/lumo/vaadin-something-else';"); - // An import not found in node_modules - expectedLines.add("import 'unresolved/component';"); - - expectedLines.add( - "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css?inline';"); - expectedLines - .add("import $cssFromFile_1 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_2 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_3 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_4 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_5 from 'Frontend/foo.css?inline';"); - expectedLines - .add("import $cssFromFile_6 from 'Frontend/foo.css?inline';"); - expectedLines.add("addCssBlock(``);"); - expectedLines.add("addCssBlock(``);"); - expectedLines.add( - "addCssBlock(``);"); - expectedLines.add("registerStyles('', $css_3, {moduleId: 'baz'});"); - expectedLines.add( - "registerStyles('', $css_4, {include: 'bar', moduleId: 'baz'});"); - expectedLines.add( - "registerStyles('foo-bar', $css_5, {moduleId: 'flow_css_mod_5'});"); - expectedLines.add( - "registerStyles('foo-bar', $css_6, {include: 'bar', moduleId: 'flow_css_mod_6'});"); - - expectedLines.add("import 'generated-modules-foo';"); - expectedLines.add("import 'generated-modules-bar';"); - - updater.run(); - - for (String line : expectedLines) { - Assert.assertTrue( - "\n" + line + " IS NOT FOUND IN: \n" - + updater.resultingLines, - updater.resultingLines.contains(line)); - } - - // All generated module ids are distinct - Pattern moduleIdPattern = Pattern - .compile(".*moduleId: '(flow_css_mod_[^']*)'.*"); - List moduleIds = updater.resultingLines.stream() - .map(moduleIdPattern::matcher).filter(Matcher::matches) - .map(m -> m.group(1)).collect(Collectors.toList()); - long uniqueModuleIds = moduleIds.stream().distinct().count(); - Assert.assertTrue("expected modules", moduleIds.size() > 0); - Assert.assertEquals("duplicates in generated " + moduleIds, - moduleIds.size(), uniqueModuleIds); - - String output = logger.getLogs(); - - MatcherAssert.assertThat(output, CoreMatchers.containsString( - "Use the './' prefix for files in JAR files: 'ExampleConnector.js'")); - MatcherAssert.assertThat(output, CoreMatchers - .containsString("Use the './' prefix for files in the '" - + frontendDirectory.getPath() - + "' folder: 'vaadin-mixed-component/theme/lumo/vaadin-mixed-component.js'")); - - // Using regex match because of the ➜ character in TC - MatcherAssert.assertThat(output, CoreMatchers.containsString( - "Failed to find the following imports in the `node_modules` tree:\n - unresolved/component")); - - MatcherAssert.assertThat(output, - CoreMatchers.not(CoreMatchers.containsString( - "changing 'frontend://foo-dir/javascript-lib.js' to './foo-dir/javascript-lib.js'"))); - } - - @Test - public void cssFileNotFound_throws() { - assertTrue(resolveImportFile(frontendDirectory, nodeModulesPath, - "@vaadin/vaadin-mixed-component/bar.css").delete()); - exception.expect(IllegalStateException.class); - updater.run(); - } - - @Test - public void generate_containsLumoThemeFiles() { - updater.run(); - - assertContainsImports(true, "@vaadin/vaadin-lumo-styles/color.js", - "@vaadin/vaadin-lumo-styles/typography.js", - "@vaadin/vaadin-lumo-styles/sizing.js", - "@vaadin/vaadin-lumo-styles/spacing.js", - "@vaadin/vaadin-lumo-styles/style.js", - "@vaadin/vaadin-lumo-styles/icons.js"); - } - - // flow #6408 - @Test - public void jsModuleOnRouterLayout_shouldBe_addedAfterLumoStyles() { - updater.run(); - - assertContainsImports(true, "Frontend/common-js-file.js"); - - assertImportOrder("@vaadin/vaadin-lumo-styles/color.js", - "Frontend/common-js-file.js"); - assertImportOrder( - "@vaadin/vaadin-mixed-component/theme/lumo/vaadin-something-else.js", - "Frontend/common-js-file.js"); - } - - @Test - public void jsModulesOrderIsPreservedAnsAfterJsModules() { - updater.run(); - - assertImportOrder("jsmodule/g.js", "javascript/a.js", "javascript/b.js", - "javascript/c.js"); - } - - @Test - public void importingBinaryFile_importVisitorShouldNotFail() - throws IOException, URISyntaxException { - // Add a binary image import to 'commmon-js-file.js' which should not - // fail the import visitor and should be ignored - File newFile = resolveImportFile(frontendDirectory, nodeModulesPath, - "./common-js-file.js"); - Files.copy( - Paths.get(getClass().getClassLoader().getResource("dice.jpg") - .toURI()), - new File(newFile.getParentFile(), "dice.jpg").toPath()); - Files.write(newFile.toPath(), - Collections.singleton("import './dice.jpg'")); - - updater.run(); - } - - @Route(value = "") - private static class MainView extends Component { - NodeTestComponents.TranslatedImports translatedImports; - NodeTestComponents.LocalP3Template localP3Template; - NodeTestComponents.JavaScriptOrder javaScriptOrder; - } - - @Test - public void plainCssImportWorks() throws MalformedURLException { - Class[] testClasses = { SimpleCssImport.class }; - ClassFinder classFinder = getClassFinder(testClasses); - - updater = new UpdateImports(classFinder, getScanner(classFinder), - tmpRoot, new File(tmpRoot, TOKEN_FILE), true, featureFlags); - updater.run(); - - Assert.assertTrue("Should import unsafeCSS", - updater.getCssLines().stream() - .anyMatch(line -> line.matches("import.*unsafeCSS.*"))); - Assert.assertTrue("Should use unsafeCSS", - updater.getCssLines().stream().anyMatch(line -> line - .matches(".*unsafeCSS\\(\\$cssFromFile_.*"))); - } - - @Test - public void assertFullSortOrder() throws MalformedURLException { - Class[] testClasses = { MainView.class, - NodeTestComponents.TranslatedImports.class, - NodeTestComponents.LocalP3Template.class, - NodeTestComponents.JavaScriptOrder.class, UI.class }; - ClassFinder classFinder = getClassFinder(testClasses); - - updater = new UpdateImports(classFinder, getScanner(classFinder), - tmpRoot, new File(tmpRoot, TOKEN_FILE), true, featureFlags); - updater.run(); - - // Imports are collected as - // - theme and css - // - JsModules (external e.g. in node_modules/) - // - JavaScript - // - Generated webcompoents - // - JsModules (internal e.g. in frontend/) - List expectedImports = new ArrayList<>(); - expectedImports.addAll(updater.getExportLines()); - expectedImports.addAll(updater.getThemeLines()); - - getAnntotationsAsStream(JsModule.class, testClasses) - .map(JsModule::value).map(this::updateToImport).sorted() - .forEach(expectedImports::add); - getAnntotationsAsStream(JavaScript.class, testClasses) - .map(JavaScript::value).map(this::updateToImport).sorted() - .forEach(expectedImports::add); - - List internals = expectedImports.stream() - .filter(importValue -> importValue - .contains(FrontendUtils.FRONTEND_FOLDER_ALIAS)) - .sorted().collect(Collectors.toList()); - updater.getGeneratedModules().stream().map(this::updateToImport) - .forEach(expectedImports::add); - // Remove internals from the full list - expectedImports.removeAll(internals); - // Add internals to end of list - expectedImports.addAll(internals); - - Assert.assertEquals(expectedImports, updater.resultingLines); - } - - private Stream getAnntotationsAsStream( - Class annotation, Class... classes) { - Stream stream = Stream.empty(); - for (Class clazz : classes) { - stream = Stream.concat(stream, - Stream.of(clazz.getAnnotationsByType(annotation))); - } - return stream; - } - - private String updateToImport(String value) { - if (value.startsWith("./")) { - value = value.replace("./", FrontendUtils.FRONTEND_FOLDER_ALIAS); - } - return String.format("import '%s';", value); - } - - private void assertContainsImports(boolean contains, String... imports) { - for (String line : imports) { - boolean result = updater.resultingLines - .contains("import '" + addWebpackPrefix(line) + "';"); - String message = "\n " + (contains ? "NOT " : "") + "FOUND '" - + line + " IN: \n" + updater.resultingLines; - if (contains) { - assertTrue(message, result); - } else { - assertFalse(message, result); - } - } - } - - private void assertImportOrder(String... imports) { - int curIndex = -1; - for (String line : imports) { - String prefixed = addWebpackPrefix(line); - int nextIndex = updater.resultingLines - .indexOf("import '" + prefixed + "';"); - assertTrue("import '" + prefixed + "' not found", nextIndex != -1); - assertTrue("import '" + prefixed + "' appears in the wrong order", - curIndex <= nextIndex); - curIndex = nextIndex; - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/ComponentFlagsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/ComponentFlagsTest.java deleted file mode 100644 index 5e7c8ac0345..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/ComponentFlagsTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; - -import net.jcip.annotations.NotThreadSafe; - -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.frontend.NodeTestComponents.FlagView; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -@NotThreadSafe -public class ComponentFlagsTest extends NodeUpdateTestUtil { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private FeatureFlags featureFlags; - private File propertiesDir; - - private File importsFile; - private File generatedPath; - private File frontendDirectory; - private File nodeModulesPath; - private File tmpRoot; - private Class[] testClasses = { FlagView.class }; - - @Before - public void before() throws IOException { - - tmpRoot = temporaryFolder.getRoot(); - propertiesDir = temporaryFolder.newFolder(); - - featureFlags = new FeatureFlags(Mockito.mock(Lookup.class)); - featureFlags.setPropertiesLocation(propertiesDir); - - frontendDirectory = new File(tmpRoot, DEFAULT_FRONTEND_DIR); - nodeModulesPath = new File(tmpRoot, NODE_MODULES); - generatedPath = new File(tmpRoot, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - importsFile = new File(generatedPath, IMPORTS_NAME); - - assertTrue(nodeModulesPath.mkdirs()); - createExpectedImports(frontendDirectory, nodeModulesPath); - } - - protected FrontendDependenciesScanner getScanner(ClassFinder finder, - FeatureFlags featureFlags) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(false, finder, true, false, featureFlags); - } - - @Test - public void should_ExcludeExperimentalComponent_WhenFlagDisabled() - throws IOException { - createUpdater().execute(); - - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertFalse(content.contains("experimental-Connector.js")); - } - - @Test - public void should_ExcludeExperimentalComponent_WhenFlagFoo() - throws IOException { - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=FOO\n"); - featureFlags.loadProperties(); - - createUpdater().execute(); - - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertFalse(content.contains("experimental-Connector.js")); - } - - @Test - public void should_IncludeExperimentalComponent_WhenFlagEnabled() - throws IOException { - createFeatureFlagsFile( - "com.vaadin.experimental.exampleFeatureFlag=true\n"); - featureFlags.loadProperties(); - - createUpdater().execute(); - - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - assertTrue(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertTrue(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertTrue(content.contains("experimental-Connector.js")); - } - - private void createFeatureFlagsFile(String data) throws IOException { - FileUtils.write( - new File(propertiesDir, FeatureFlags.PROPERTIES_FILENAME), data, - StandardCharsets.UTF_8); - } - - private TaskUpdateImports createUpdater() throws IOException { - ClassFinder classFinder = getClassFinder(testClasses); - - return new TaskUpdateImports(classFinder, - getScanner(classFinder, featureFlags), finder -> null, tmpRoot, - generatedPath, frontendDirectory, null, null, false, TARGET, - true, false, featureFlags); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/EmptyByteScannerDataTestComponents.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/EmptyByteScannerDataTestComponents.java deleted file mode 100644 index 38056bfcdcc..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/EmptyByteScannerDataTestComponents.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.util.Collections; -import java.util.List; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.Theme; - -/** - * Byte scanner will not be able to find anything from this class - * - */ -public class EmptyByteScannerDataTestComponents { - - @JsModule("./common-js-file.js") - @JavaScript("ExampleConnector.js") - @CssImport(value = "./foo.css", id = "baz", include = "bar") - @Theme(themeClass = HiddenTheme.class) - public static class MainLayout extends Component { - } - - @JsModule("@vaadin/vaadin-lumo-styles/icons.js") - public static class HiddenTheme implements AbstractTheme { - - @Override - public String getBaseUrl() { - return "src/"; - } - - @Override - public String getThemeUrl() { - return "hidden-theme/"; - } - - @Override - public List getHeaderInlineContents() { - return Collections - .singletonList("foo"); - } - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/ExtraNodeTestComponents.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/ExtraNodeTestComponents.java deleted file mode 100644 index 61c0a171c1b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/ExtraNodeTestComponents.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; - -public class ExtraNodeTestComponents { - - @JsModule("@polymer/a.js") - public class ExtraJsModuleComponent extends Component { - } - - @JsModule("@polymer/b.js") - public class ExtraJsModuleComponent2 extends Component { - } - - @JsModule("@polymer/c.js") - public class ExtraJsModuleComponent3 extends Component { - } - - @JsModule("@polymer/D.js") - public class ExtraJsModuleComponent4 extends Component { - } - - @JsModule("@polymer/e.js") - public class ExtraJsModuleComponent5 extends Component { - } - - @JavaScript("./extra-javascript.js") - public class ExtraJavaScriptComponent extends Component { - } - - @CssImport(value = "./extra-css.css", themeFor = "extra-foo", include = "extra-bar") - public static class ExtraCssImport extends Component { - } - - @CssImport(value = "./a-css.css", include = "a-a") - public static class ExtraCssImport2 extends Component { - } - - @CssImport(value = "./b-css.css") - public static class ExtraCssImport3 extends Component { - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendResourcesAreCopiedAfterCleaningTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendResourcesAreCopiedAfterCleaningTest.java deleted file mode 100644 index dfb6d0c5ba4..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendResourcesAreCopiedAfterCleaningTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.Collections; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.testutil.TestUtils; - -import static com.vaadin.flow.server.Constants.TARGET; - -public class FrontendResourcesAreCopiedAfterCleaningTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File npmFolder; - - private File testJar = TestUtils - .getTestJar("jar-with-frontend-resources.jar"); - - @Before - public void setup() throws IOException, ExecutionFailedException { - npmFolder = temporaryFolder.getRoot(); - - } - - @Test - public void frontendResources_should_beCopiedFromJars_when_TaskUpdatePackagesRemovesThem() - throws IOException, ExecutionFailedException { - copyResources(); - assertCopiedFrontendFileAmount(8); - - performPackageClean(); - assertCopiedFrontendFileAmount(0); - - copyResources(); - assertCopiedFrontendFileAmount(8); - } - - private void assertCopiedFrontendFileAmount(int fileCount) - throws IOException { - File dir = getJarFrontendResourcesFolder(); - FileUtils.forceMkdir(dir); - List files = TestUtils.listFilesRecursively(dir); - - Assert.assertEquals("Should have frontend files", fileCount, - files.size()); - } - - private File getJarFrontendResourcesFolder() { - return new File(npmFolder, - Paths.get("frontend", FrontendUtils.GENERATED, - FrontendUtils.JAR_RESOURCES_FOLDER).toString()); - } - - private void copyResources() throws ExecutionFailedException { - ClassFinder classFinder = new ClassFinder.DefaultClassFinder( - FrontendResourcesAreCopiedAfterCleaningTest.class - .getClassLoader()); - Lookup mockLookup = Mockito.mock(Lookup.class); - Mockito.doReturn(classFinder).when(mockLookup) - .lookup(ClassFinder.class); - NodeTasks.Builder builder = new NodeTasks.Builder(mockLookup, npmFolder, - TARGET); - - builder.withEmbeddableWebComponents(false).enableImportsUpdate(false) - .createMissingPackageJson(true).enableImportsUpdate(true) - .runNpmInstall(false).enablePackagesUpdate(true) - .withJarFrontendResourcesFolder(getJarFrontendResourcesFolder()) - .copyResources(Collections.singleton(testJar)).build() - .execute(); - } - - private void performPackageClean() throws ExecutionFailedException { - ClassFinder classFinder = new ClassFinder.DefaultClassFinder( - FrontendResourcesAreCopiedAfterCleaningTest.class - .getClassLoader()); - Lookup mockLookup = Mockito.mock(Lookup.class); - Mockito.doReturn(classFinder).when(mockLookup) - .lookup(ClassFinder.class); - NodeTasks.Builder builder = new NodeTasks.Builder(mockLookup, npmFolder, - TARGET); - builder.withEmbeddableWebComponents(false).enableImportsUpdate(false) - .createMissingPackageJson(true).enableImportsUpdate(true) - .runNpmInstall(false).enableNpmFileCleaning(true) - .withJarFrontendResourcesFolder(getJarFrontendResourcesFolder()) - .copyResources(Collections.emptySet()) - .enablePackagesUpdate(true).build().execute(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsLocatorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsLocatorTest.java deleted file mode 100644 index bb1db65dba2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsLocatorTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.util.Optional; - -import org.junit.Assume; -import org.junit.Test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class FrontendToolsLocatorTest { - private final FrontendToolsLocator locator = new FrontendToolsLocator(); - - @Test - public void toolLocated() { - Optional echoLocation = locator.tryLocateTool("mvn"); - assertTrue("Should be able to find 'mvn' binary", - echoLocation.isPresent()); - } - - @Test - public void toolLocated_verificationFailed() { - Assume.assumeFalse("Cannot run the test on Windows", - locator.isWindows()); - Optional sedLocation = locator.tryLocateTool("sed"); - assertFalse( - "Sed location should not be available due to lack of '-v' flag support", - sedLocation.isPresent()); - } - - @Test - public void toolNotLocated() { - Optional unknownToolLocation = locator - .tryLocateTool("sdhajgsdiasg!"); - assertFalse("Unknown tool should not be found in the system", - unknownToolLocation.isPresent()); - } - - @Test - public void nonExistentTool_notVerified() { - assertFalse("Non-existent tool should not be a valid one", - locator.verifyTool(new File("whatever!"))); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java deleted file mode 100644 index 1ebb6c81e31..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendToolsTest.java +++ /dev/null @@ -1,920 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import static com.vaadin.flow.server.frontend.FrontendTools.NPM_BIN_PATH; -import static com.vaadin.flow.testutil.FrontendStubs.createStubNode; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.Properties; -import java.util.function.Supplier; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; -import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; -import org.apache.commons.compress.utils.Lists; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.TemporaryFolder; -import org.slf4j.LoggerFactory; - -import com.vaadin.flow.function.SerializableSupplier; -import com.vaadin.flow.internal.Pair; -import com.vaadin.flow.server.frontend.installer.Platform; -import com.vaadin.flow.server.frontend.installer.ProxyConfig; -import com.vaadin.flow.testcategory.SlowTests; -import com.vaadin.flow.testutil.FrontendStubs; - -import net.jcip.annotations.NotThreadSafe; - -@NotThreadSafe -@Category(SlowTests.class) -public class FrontendToolsTest { - - private static final String SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED = "18.0.0"; - - public static final String DEFAULT_NODE = FrontendUtils.isWindows() - ? "node\\node.exe" - : "node/node"; - - public static final String NPM_CLI_STRING = FrontendUtils.isWindows() - ? "node\\node_modules\\npm\\bin\\npm-cli.js" - : "node/lib/node_modules/npm/bin/npm-cli.js"; - - private static final String OLD_PNPM_VERSION = "4.5.0"; - - private static final String SUPPORTED_PNPM_VERSION = "5.15.0"; - - private String baseDir; - - private String vaadinHomeDir; - - @Rule - public final TemporaryFolder tmpDir = new TemporaryFolder(); - - @Rule - public final TemporaryFolder tmpDirWithNpmrc = new TemporaryFolder(); - - private final FrontendToolsLocator frontendToolsLocator = new FrontendToolsLocator(); - - private FrontendTools tools; - private FrontendToolsSettings settings; - - @Before - public void setup() throws IOException { - baseDir = tmpDir.newFolder().getAbsolutePath(); - vaadinHomeDir = tmpDir.newFolder().getAbsolutePath(); - settings = new FrontendToolsSettings(baseDir, () -> vaadinHomeDir); - tools = new FrontendTools(settings); - } - - @Test - public void installNode_NodeIsInstalledToTargetDirectory() - throws FrontendUtils.UnknownVersionException { - String nodeExecutable = tools - .installNode(FrontendTools.DEFAULT_NODE_VERSION, null); - Assert.assertNotNull(nodeExecutable); - - List nodeVersionCommand = new ArrayList<>(); - nodeVersionCommand.add(nodeExecutable); - nodeVersionCommand.add("--version"); - FrontendVersion node = FrontendUtils.getVersion("node", - nodeVersionCommand); - Assert.assertEquals( - new FrontendVersion(FrontendTools.DEFAULT_NODE_VERSION) - .getFullVersion(), - node.getFullVersion()); - - settings.setBaseDir(vaadinHomeDir); - settings.setAlternativeDirGetter(null); - - FrontendTools newTools = new FrontendTools(settings); - List npmVersionCommand = new ArrayList<>( - newTools.getNpmExecutable()); - npmVersionCommand.add("--version"); - FrontendVersion npm = FrontendUtils.getVersion("npm", - npmVersionCommand); - final FrontendVersion npmDefault = new FrontendVersion( - FrontendTools.DEFAULT_NPM_VERSION); - - Assert.assertEquals("Major version should match", - npmDefault.getMajorVersion(), npm.getMajorVersion()); - Assert.assertEquals("Minor version should match", - npmDefault.getMinorVersion(), npm.getMinorVersion()); - } - - @Test - public void nodeIsBeingLocated_updateTooOldNode_NodeInstalledToTargetDirectoryIsUpdated() - throws FrontendUtils.UnknownVersionException { - FrontendVersion updatedNodeVersion = getUpdatedAlternativeNodeVersion( - "7.7.3", () -> tools.getNodeExecutable()); - - Assert.assertEquals( - "Failed to update the old Node version when being located", - new FrontendVersion(FrontendTools.DEFAULT_NODE_VERSION) - .getFullVersion(), - updatedNodeVersion.getFullVersion()); - } - - @Test - public void nodeIsBeingLocated_supportedNodeInstalled_autoUpdateFalse_NodeNotUpdated() - throws FrontendUtils.UnknownVersionException { - settings.setAutoUpdate(false); - FrontendVersion updatedNodeVersion = getUpdatedAlternativeNodeVersion( - SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED, - () -> tools.getNodeExecutable()); - - Assert.assertEquals( - "Locate Node version: Node version updated even if it should not have been touched.", - SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED, - updatedNodeVersion.getFullVersion()); - } - - @Test - public void nodeIsBeingLocated_supportedNodeInstalled_autoUpdateTrue_NodeUpdated() - throws FrontendUtils.UnknownVersionException { - FrontendVersion updatedNodeVersion = getUpdatedAlternativeNodeVersion( - SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED, - () -> tools.getNodeExecutable()); - - Assert.assertEquals( - "Locate Node version: Node version was not auto updated.", - new FrontendVersion(FrontendTools.DEFAULT_NODE_VERSION) - .getFullVersion(), - updatedNodeVersion.getFullVersion()); - } - - @Test - public void nodeIsBeingLocated_unsupportedNodeInstalled_defaultNodeVersionInstalledToAlternativeDirectory() - throws FrontendUtils.UnknownVersionException, IOException { - // Unsupported node version - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NODE).withVersion("8.9.3").build(); - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo.none(); - createStubNode(nodeStub, npmStub, baseDir); - - List nodeVersionCommand = new ArrayList<>(); - nodeVersionCommand.add(tools.getNodeExecutable()); - nodeVersionCommand.add("--version"); - FrontendVersion usedNodeVersion = FrontendUtils.getVersion("node", - nodeVersionCommand); - - Assert.assertEquals( - "Locate unsupported Node version: Default Node version was not used.", - new FrontendVersion(FrontendTools.DEFAULT_NODE_VERSION) - .getFullVersion(), - usedNodeVersion.getFullVersion()); - } - - @Test - public void nodeIsBeingLocated_unsupportedNodeInstalled_fallbackToNodeInstalledToAlternativeDirectory() - throws IOException, FrontendUtils.UnknownVersionException { - // Unsupported node version - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NODE).withVersion("8.9.3").build(); - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo.none(); - createStubNode(nodeStub, npmStub, baseDir); - - tools.installNode(FrontendTools.DEFAULT_NODE_VERSION, null); - - List nodeVersionCommand = new ArrayList<>(); - nodeVersionCommand.add(tools.getNodeExecutable()); - nodeVersionCommand.add("--version"); - FrontendVersion usedNodeVersion = FrontendUtils.getVersion("node", - nodeVersionCommand); - - Assert.assertEquals( - "Locate unsupported Node version: Expecting Node in alternative directory to be used, but was not.", - FrontendTools.DEFAULT_NODE_VERSION.replace("v", ""), - usedNodeVersion.getFullVersion()); - } - - @Test - public void forceAlternativeDirectory_updateTooOldNode_NodeInstalledToTargetDirectoryIsUpdated() - throws FrontendUtils.UnknownVersionException { - FrontendVersion updatedNodeVersion = getUpdatedAlternativeNodeVersion( - "7.7.3", () -> tools.forceAlternativeNodeExecutable()); - - Assert.assertEquals( - "Failed to update the old Node version when alternative directory forced", - new FrontendVersion(FrontendTools.DEFAULT_NODE_VERSION) - .getFullVersion(), - updatedNodeVersion.getFullVersion()); - } - - @Test - public void forceAlternativeDirectory_supportedNodeInstalled_autoUpdateFalse_NodeNotUpdated() - throws FrontendUtils.UnknownVersionException { - settings.setAutoUpdate(false); - FrontendVersion updatedNodeVersion = getUpdatedAlternativeNodeVersion( - SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED, - () -> tools.forceAlternativeNodeExecutable()); - - Assert.assertEquals( - "Force alternative directory: Node version updated even if it should not have been touched.", - SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED, - updatedNodeVersion.getFullVersion()); - } - - @Test - public void forceAlternativeDirectory_supportedNodeInstalled_autoUpdateTrue_NodeUpdated() - throws FrontendUtils.UnknownVersionException { - FrontendVersion updatedNodeVersion = getUpdatedAlternativeNodeVersion( - SUPPORTED_NODE_BUT_OLDER_THAN_AUTOINSTALLED, - () -> tools.forceAlternativeNodeExecutable()); - - Assert.assertEquals( - "Force alternative directory: Node version was not auto updated.", - new FrontendVersion(FrontendTools.DEFAULT_NODE_VERSION) - .getFullVersion(), - updatedNodeVersion.getFullVersion()); - } - - private FrontendVersion getUpdatedAlternativeNodeVersion( - String oldNodeVersion, - SerializableSupplier nodeUpdateCommand) - throws FrontendUtils.UnknownVersionException { - settings.setForceAlternativeNode(true); - tools = new FrontendTools(settings); - - String toBeInstalled = "v" + oldNodeVersion; - String nodeExecutable = tools.installNode(toBeInstalled, null); - Assert.assertNotNull(nodeExecutable); - - List nodeVersionCommand = new ArrayList<>(); - nodeVersionCommand.add(nodeExecutable); - nodeVersionCommand.add("--version"); - FrontendVersion node = FrontendUtils.getVersion("node", - nodeVersionCommand); - Assert.assertEquals("Wrong node version installed", oldNodeVersion, - node.getFullVersion()); - - nodeExecutable = nodeUpdateCommand.get(); - nodeVersionCommand = new ArrayList<>(); - nodeVersionCommand.add(nodeExecutable); - nodeVersionCommand.add("--version"); - return FrontendUtils.getVersion("node", nodeVersionCommand); - } - - private void prepareNodeDownloadableZipAt(String baseDir, String version) - throws IOException { - Platform platform = Platform.guess(); - String nodeExec = platform.isWindows() ? "node.exe" : "node"; - String prefix = "node-" + version + "-" - + platform.getNodeClassifier(new FrontendVersion(version)); - - File downloadDir = new File(baseDir, version); - FileUtils.forceMkdir(downloadDir); - File archiveFile = new File(downloadDir, - prefix + "." + platform.getArchiveExtension()); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - if (platform.getArchiveExtension().equals("zip")) { - try (ZipOutputStream zipOutputStream = new ZipOutputStream( - Files.newOutputStream(tempArchive))) { - zipOutputStream - .putNextEntry(new ZipEntry(prefix + "/" + nodeExec)); - zipOutputStream.closeEntry(); - zipOutputStream.putNextEntry( - new ZipEntry(prefix + "/node_modules/npm/bin/npm")); - zipOutputStream.closeEntry(); - zipOutputStream.putNextEntry( - new ZipEntry(prefix + "/node_modules/npm/bin/npm.cmd")); - zipOutputStream.closeEntry(); - } - } else { - try (OutputStream fo = Files.newOutputStream(tempArchive); - OutputStream gzo = new GzipCompressorOutputStream(fo); - ArchiveOutputStream o = new TarArchiveOutputStream(gzo)) { - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/bin/" + nodeExec), - prefix + "/bin/" + nodeExec)); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/bin/npm"), prefix + "/bin/npm")); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/lib/node_modules/npm/bin/npm"), - prefix + "/lib/node_modules/npm/bin/npm")); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/lib/node_modules/npm/bin/npm.cmd"), - prefix + "/lib/node_modules/npm/bin/npm.cmd")); - o.closeArchiveEntry(); - } - } - } - - @Test - public void installNodeFromFileSystem_NodeIsInstalledToTargetDirectory() - throws IOException { - prepareNodeDownloadableZipAt(baseDir, - FrontendTools.DEFAULT_NODE_VERSION); - - String nodeExecutable = installNodeToTempFolder(); - Assert.assertNotNull(nodeExecutable); - - String npmInstallPath = NPM_BIN_PATH + "npm"; - - Assert.assertTrue("npm should have been copied to node_modules", - new File(vaadinHomeDir, npmInstallPath).exists()); - } - - @Test - public void installNodeFromFileSystem_ForceAlternativeNodeExecutableInstallsToTargetDirectory() - throws Exception { - Assert.assertFalse("npm should not yet be present", - new File(vaadinHomeDir, NPM_BIN_PATH + "npm").exists()); - - settings.setNodeDownloadRoot(new File(baseDir).toURI()); - settings.setNodeVersion("v12.10.0"); - tools = new FrontendTools(settings); - prepareNodeDownloadableZipAt(baseDir, "v12.10.0"); - tools.forceAlternativeNodeExecutable(); - - String npmInstallPath = NPM_BIN_PATH + "npm"; - - Assert.assertTrue("npm should have been copied to node_modules", - new File(vaadinHomeDir, npmInstallPath).exists()); - } - - @Test - public void homeNodeIsNotForced_useGlobalNode() - throws IOException, FrontendUtils.UnknownVersionException { - createStubNode(true, true, vaadinHomeDir); - - // Validate the global node to be applicable for testing. - Pair nodeCommands; - if (FrontendUtils.isWindows()) { - nodeCommands = new Pair<>("node.exe", "node/node.exe"); - } else { - nodeCommands = new Pair<>("node", "node/node"); - } - File file = new File(baseDir, nodeCommands.getSecond()); - if (!file.exists()) { - file = frontendToolsLocator.tryLocateTool(nodeCommands.getFirst()) - .orElse(null); - List versionCommand = Lists.newArrayList(); - versionCommand.add(file.getAbsolutePath()); - versionCommand.add("--version"); // NOSONAR - final FrontendVersion installedNodeVersion = FrontendUtils - .getVersion("node", versionCommand); - if (installedNodeVersion - .isOlderThan(FrontendTools.SUPPORTED_NODE_VERSION)) { - LoggerFactory.getLogger(FrontendToolsTest.class).info( - "Global version of node is {} which is older than the supported version {}", - installedNodeVersion.getFullVersion(), - FrontendTools.SUPPORTED_NODE_VERSION.getFullVersion()); - return; - } - } - - assertThat(tools.getNodeExecutable(), containsString("node")); - assertThat(tools.getNodeExecutable(), - not(containsString(DEFAULT_NODE))); - assertThat(tools.getNodeExecutable(), - not(containsString(NPM_CLI_STRING))); - assertThat(tools.getNodeExecutable(), - not(containsString(vaadinHomeDir))); - assertThat(tools.getNodeExecutable(), not(containsString(baseDir))); - - assertEquals(4, tools.getNpmExecutable().size()); - assertThat(tools.getNpmExecutable().get(0), containsString("npm")); - assertThat(tools.getNpmExecutable().get(1), - containsString("--no-update-notifier")); - assertThat(tools.getNpmExecutable().get(2), - containsString("--no-audit")); - assertThat(tools.getNpmExecutable().get(3), - containsString("--scripts-prepend-node-path=true")); - } - - @Test - public void getNpmExecutable_removesPnpmLock() throws IOException { - File file = new File(baseDir, "pnpm-lock.yaml"); - file.createNewFile(); - - tools.getNpmExecutable(); - - Assert.assertFalse(file.exists()); - } - - @Test - public void getPnpmExecutable_executableIsAvailable() { - List executable = tools.getPnpmExecutable(); - // command line should contain --shamefully-hoist=true option - Assert.assertTrue(executable.contains("--shamefully-hoist=true")); - Assert.assertTrue( - executable.stream().anyMatch(cmd -> cmd.contains("pnpm"))); - } - - @Test - public void validateNodeAndNpmVersion_pnpmLockIsNotRemoved() - throws IOException { - File file = new File(baseDir, "pnpm-lock.yaml"); - file.createNewFile(); - - tools.validateNodeAndNpmVersion(); - - Assert.assertTrue(file.exists()); - } - - @Test(expected = IllegalStateException.class) - public void ensureNodeExecutableInHome_vaadinHomeNodeIsAFolder_throws() - throws IOException { - File node = new File(vaadinHomeDir, - FrontendUtils.isWindows() ? "node/node.exe" : "node/node"); - FileUtils.forceMkdir(node); - - tools.forceAlternativeNodeExecutable(); - } - - @Test - public void getProxies_noNpmrc_shouldReturnEmptyList() { - File npmrc = new File(baseDir + "/.npmrc"); - if (npmrc.exists()) - npmrc.delete(); - - List proxyList = tools.getProxies(); - Assert.assertTrue(proxyList.isEmpty()); - } - - @Test - public synchronized void getProxies_systemPropertiesAndNpmrcWithProxySetting_shouldReturnAllProxies() - throws IOException { - File npmrc = new File(tmpDirWithNpmrc.newFolder("test2"), ".npmrc"); - - settings.setBaseDir(npmrc.getParent()); - settings.setAlternativeDirGetter(null); - - FrontendTools tools = new FrontendTools(settings); - - Properties properties = new Properties(); - properties.put(FrontendTools.NPMRC_PROXY_PROPERTY_KEY, - "http://httpuser:httppassword@httphost:8080"); - properties.put(FrontendTools.NPMRC_HTTPS_PROXY_PROPERTY_KEY, - "http://httpsuser:httpspassword@httpshost:8081"); - properties.put(FrontendTools.NPMRC_NOPROXY_PROPERTY_KEY, - "192.168.1.1,vaadin.com,mycompany.com"); - try (FileOutputStream fileOutputStream = new FileOutputStream(npmrc)) { - properties.store(fileOutputStream, null); - } - - List proxyList = null; - try { - System.setProperty(FrontendUtils.SYSTEM_NOPROXY_PROPERTY_KEY, - "somethingelse,someotherip,75.41.41.33"); - System.setProperty(FrontendUtils.SYSTEM_HTTP_PROXY_PROPERTY_KEY, - "http://anotheruser:anotherpassword@aanotherhost:9090"); - System.setProperty(FrontendUtils.SYSTEM_HTTPS_PROXY_PROPERTY_KEY, - "http://anotherusers:anotherpasswords@aanotherhosts:9091/"); - - proxyList = tools.getProxies(); - } finally { - System.clearProperty(FrontendUtils.SYSTEM_NOPROXY_PROPERTY_KEY); - System.clearProperty(FrontendUtils.SYSTEM_HTTP_PROXY_PROPERTY_KEY); - System.clearProperty(FrontendUtils.SYSTEM_HTTPS_PROXY_PROPERTY_KEY); - } - - Assert.assertEquals(4, proxyList.size()); - - // The first two items should be system proxies - ProxyConfig.Proxy systemHttpsProxy = proxyList.get(0).id.startsWith( - "https-proxy") ? proxyList.get(0) : proxyList.get(1); - ProxyConfig.Proxy systemProxy = proxyList.get(0).id.startsWith( - "https-proxy") ? proxyList.get(1) : proxyList.get(0); - - // Items 2 and 3 should be npmrc proxies - ProxyConfig.Proxy npmrcHttpsProxy = proxyList.get(2).id.startsWith( - "https-proxy") ? proxyList.get(2) : proxyList.get(3); - ProxyConfig.Proxy npmrcProxy = proxyList.get(2).id.startsWith( - "https-proxy") ? proxyList.get(3) : proxyList.get(2); - - Assert.assertEquals("http", systemProxy.protocol); - Assert.assertEquals("anotheruser", systemProxy.username); - Assert.assertEquals("anotherpassword", systemProxy.password); - Assert.assertEquals("aanotherhost", systemProxy.host); - Assert.assertEquals(9090, systemProxy.port); - Assert.assertEquals("somethingelse|someotherip|75.41.41.33", - systemProxy.nonProxyHosts); - - Assert.assertEquals("http", systemHttpsProxy.protocol); - Assert.assertEquals("anotherusers", systemHttpsProxy.username); - Assert.assertEquals("anotherpasswords", systemHttpsProxy.password); - Assert.assertEquals("aanotherhosts", systemHttpsProxy.host); - Assert.assertEquals(9091, systemHttpsProxy.port); - Assert.assertEquals("somethingelse|someotherip|75.41.41.33", - systemHttpsProxy.nonProxyHosts); - - Assert.assertEquals("http", npmrcHttpsProxy.protocol); - Assert.assertEquals("httpsuser", npmrcHttpsProxy.username); - Assert.assertEquals("httpspassword", npmrcHttpsProxy.password); - Assert.assertEquals("httpshost", npmrcHttpsProxy.host); - Assert.assertEquals(8081, npmrcHttpsProxy.port); - Assert.assertEquals("192.168.1.1|vaadin.com|mycompany.com", - npmrcHttpsProxy.nonProxyHosts); - - Assert.assertEquals("http", npmrcProxy.protocol); - Assert.assertEquals("httpuser", npmrcProxy.username); - Assert.assertEquals("httppassword", npmrcProxy.password); - Assert.assertEquals("httphost", npmrcProxy.host); - Assert.assertEquals(8080, npmrcProxy.port); - Assert.assertEquals("192.168.1.1|vaadin.com|mycompany.com", - npmrcProxy.nonProxyHosts); - } - - @Test - public synchronized void getProxies_npmrcWithProxySettingNoNoproxy_shouldReturnNullNoproxy() - throws IOException { - File npmrc = new File(tmpDirWithNpmrc.newFolder("test1"), ".npmrc"); - Properties properties = new Properties(); - properties.put(FrontendTools.NPMRC_PROXY_PROPERTY_KEY, - "http://httpuser:httppassword@httphost:8080"); - properties.put(FrontendTools.NPMRC_HTTPS_PROXY_PROPERTY_KEY, - "http://httpsuser:httpspassword@httpshost:8081"); - try (FileOutputStream fileOutputStream = new FileOutputStream(npmrc)) { - properties.store(fileOutputStream, null); - } - - settings.setBaseDir(npmrc.getParent()); - settings.setAlternativeDirGetter(null); - - FrontendTools tools = new FrontendTools(settings); - - List proxyList = tools.getProxies(); - Assert.assertEquals(2, proxyList.size()); - ProxyConfig.Proxy httpsProxy = proxyList.get(0).id.startsWith( - "https-proxy") ? proxyList.get(0) : proxyList.get(1); - ProxyConfig.Proxy httpProxy = proxyList.get(0).id.startsWith( - "https-proxy") ? proxyList.get(1) : proxyList.get(0); - - Assert.assertEquals("http", httpProxy.protocol); - Assert.assertEquals("httpuser", httpProxy.username); - Assert.assertEquals("httppassword", httpProxy.password); - Assert.assertEquals("httphost", httpProxy.host); - Assert.assertEquals(8080, httpProxy.port); - Assert.assertNull(httpProxy.nonProxyHosts); - - Assert.assertEquals("http", httpsProxy.protocol); - Assert.assertEquals("httpsuser", httpsProxy.username); - Assert.assertEquals("httpspassword", httpsProxy.password); - Assert.assertEquals("httpshost", httpsProxy.host); - Assert.assertEquals(8081, httpsProxy.port); - Assert.assertNull(httpsProxy.nonProxyHosts); - } - - @Test - public synchronized void getProxies_npmrcWithProxySetting_shouldReturnProxiesList() - throws IOException { - File npmrc = new File(tmpDirWithNpmrc.newFolder("test1"), ".npmrc"); - Properties properties = new Properties(); - properties.put(FrontendTools.NPMRC_PROXY_PROPERTY_KEY, - "http://httpuser:httppassword@httphost:8080"); - properties.put(FrontendTools.NPMRC_HTTPS_PROXY_PROPERTY_KEY, - "http://httpsuser:httpspassword@httpshost:8081"); - properties.put(FrontendTools.NPMRC_NOPROXY_PROPERTY_KEY, - "192.168.1.1,vaadin.com,mycompany.com"); - try (FileOutputStream fileOutputStream = new FileOutputStream(npmrc)) { - properties.store(fileOutputStream, null); - } - - settings.setBaseDir(npmrc.getParent()); - settings.setAlternativeDirGetter(null); - - FrontendTools tools = new FrontendTools(settings); - - List proxyList = tools.getProxies(); - Assert.assertEquals(2, proxyList.size()); - ProxyConfig.Proxy httpsProxy = proxyList.get(0).id.startsWith( - "https-proxy") ? proxyList.get(0) : proxyList.get(1); - ProxyConfig.Proxy httpProxy = proxyList.get(0).id.startsWith( - "https-proxy") ? proxyList.get(1) : proxyList.get(0); - - Assert.assertEquals("http", httpProxy.protocol); - Assert.assertEquals("httpuser", httpProxy.username); - Assert.assertEquals("httppassword", httpProxy.password); - Assert.assertEquals("httphost", httpProxy.host); - Assert.assertEquals(8080, httpProxy.port); - Assert.assertEquals("192.168.1.1|vaadin.com|mycompany.com", - httpProxy.nonProxyHosts); - - Assert.assertEquals("http", httpsProxy.protocol); - Assert.assertEquals("httpsuser", httpsProxy.username); - Assert.assertEquals("httpspassword", httpsProxy.password); - Assert.assertEquals("httpshost", httpsProxy.host); - Assert.assertEquals(8081, httpsProxy.port); - Assert.assertEquals("192.168.1.1|vaadin.com|mycompany.com", - httpsProxy.nonProxyHosts); - } - - @Test - public void should_useProjectNodeFirst() throws Exception { - Assume.assumeFalse( - "Skipping test on windows until a fake node.exe that isn't caught by Window defender can be created.", - FrontendUtils.isWindows()); - createStubNode(true, true, baseDir); - - assertNodeCommand(() -> baseDir); - } - - @Test - public void should_useProjectNpmFirst() throws Exception { - Assume.assumeFalse( - "Skipping test on windows until a fake node.exe that isn't caught by Window defender can be created.", - FrontendUtils.isWindows()); - createStubNode(false, true, baseDir); - - assertNpmCommand(() -> baseDir); - } - - @Test - public void forceHomeNode_useHomeNpmFirst() throws Exception { - Assume.assumeFalse( - "Skipping test on windows until a fake node.exe that isn't caught by Window defender can be created.", - FrontendUtils.isWindows()); - settings.setForceAlternativeNode(true); - tools = new FrontendTools(settings); - - createStubNode(true, true, vaadinHomeDir); - assertNpmCommand(() -> vaadinHomeDir); - } - - @Test - public void getSuitablePnpm_tooOldGlobalVersionInstalled_throws() { - settings.setUseGlobalPnpm(true); - tools = new FrontendTools(settings); - try { - installGlobalPnpm(OLD_PNPM_VERSION); - IllegalStateException exception = Assert.assertThrows( - IllegalStateException.class, () -> tools.getSuitablePnpm()); - Assert.assertTrue( - "Unexpected exception message content '" - + exception.getMessage() + "'", - exception.getMessage().contains( - "Found too old globally installed 'pnpm'. Please upgrade 'pnpm' to at least 5.0.0")); - } finally { - uninstallGlobalPnpm(OLD_PNPM_VERSION); - } - } - - @Test - public void getSuitablePnpm_tooOldGlobalVersionInstalledAndSkipVersionCheck_accepted() { - settings.setUseGlobalPnpm(true); - settings.setIgnoreVersionChecks(true); - tools = new FrontendTools(settings); - try { - installGlobalPnpm(OLD_PNPM_VERSION); - List pnpmCommand = tools.getSuitablePnpm(); - Assert.assertTrue( - "expected old global pnpm version accepted when skip version flag is set", - pnpmCommand.get(pnpmCommand.size() - 1).contains("pnpm")); - } finally { - uninstallGlobalPnpm(OLD_PNPM_VERSION); - } - } - - @Test - public void getSuitablePnpm_supportedGlobalVersionInstalled_accepted() { - settings.setUseGlobalPnpm(true); - tools = new FrontendTools(settings); - try { - installGlobalPnpm(SUPPORTED_PNPM_VERSION); - List pnpmCommand = tools.getSuitablePnpm(); - Assert.assertTrue("expected supported global pnpm version accepted", - pnpmCommand.get(pnpmCommand.size() - 1).contains("pnpm")); - } finally { - uninstallGlobalPnpm(SUPPORTED_PNPM_VERSION); - } - } - - @Test - public void getSuitablePnpm_useGlobalPnpm_noPnpmInstalled_throws() { - Optional pnpm = frontendToolsLocator.tryLocateTool("pnpm"); - Assume.assumeFalse("Skip this test once globally installed pnpm is " - + "discovered", pnpm.isPresent()); - - settings.setNodeDownloadRoot(URI.create(baseDir)); - settings.setUseGlobalPnpm(true); - tools = new FrontendTools(settings); - - IllegalStateException exception = Assert.assertThrows( - IllegalStateException.class, () -> tools.getSuitablePnpm()); - Assert.assertTrue( - "Unexpected exception message content '" - + exception.getMessage() + "'", - exception.getMessage().contains( - "Vaadin is configured to use a globally installed " - + "pnpm ('pnpm.global=true'), but pnpm was not found " - + "on your system.")); - } - - @Test - public void folderIsAcceptableByNpm_npmCacheDirWithWhitespaces_falseForWindows() - throws IOException { - Assume.assumeTrue("This test is only for Windows, since the issue with " - + "whitespaces in npm processed directories reproduces only on " - + "Windows", FrontendUtils.isWindows()); - // given - // dir with whitespaces - File npmCacheDir = tmpDir.newFolder("Foo Bar"); - - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo.none(); - // Old npm version - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NPM).withVersion("6.0.0").build(); - createStubNode(nodeStub, npmStub, baseDir); - - // when - boolean accepted = tools.folderIsAcceptableByNpm(npmCacheDir); - - // then - Assert.assertFalse(accepted); - } - - @Test - public void folderIsAcceptableByNpm_npmCacheDirWithWhitespaces_trueForNonWindows() - throws IOException { - Assume.assumeFalse( - "This test is for the rest of OS rather than Windows, since " - + "the issue with whitespaces in directories processed by npm, " - + "is not reproduced on them", - FrontendUtils.isWindows()); - - // given - // dir with whitespaces - File npmCacheDir = tmpDir.newFolder("Foo Bar"); - - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo.none(); - // Old npm version - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NPM).withVersion("6.0.0").build(); - createStubNode(nodeStub, npmStub, baseDir); - - // when - boolean accepted = tools.folderIsAcceptableByNpm(npmCacheDir); - - // then - Assert.assertTrue(accepted); - } - - @Test - public void folderIsAcceptableByNpm_npmCacheNoWhitespaces_trueForWindows() - throws IOException { - Assume.assumeTrue("This test is only for Windows, since the issue with " - + "whitespaces in npm processed directories reproduces only on " - + "Windows", FrontendUtils.isWindows()); - - // given - // dir with no whitespaces - File npmCacheDir = tmpDir.newFolder("FooBar"); - - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo.none(); - // Old npm version - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NPM).withVersion("6.0.0").build(); - createStubNode(nodeStub, npmStub, baseDir); - - // when - boolean accepted = tools.folderIsAcceptableByNpm(npmCacheDir); - - // then - Assert.assertTrue(accepted); - } - - @Test - public void folderIsAcceptableByNpm_npm7_trueForWindows() - throws IOException { - Assume.assumeTrue("This test is only for Windows, since the issue with " - + "whitespaces in npm processed directories reproduces only on " - + "Windows", FrontendUtils.isWindows()); - - // given - // dir with whitespaces - File npmCacheDir = tmpDir.newFolder("Foo Bar"); - - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo.none(); - // Acceptable npm version - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NPM).withVersion("7.0.0").build(); - createStubNode(nodeStub, npmStub, baseDir); - - // when - boolean accepted = tools.folderIsAcceptableByNpm(npmCacheDir); - - // then - Assert.assertTrue(accepted); - } - - @Test - public void getNpmCacheDir_returnsCorrectPath() throws IOException, - InterruptedException, FrontendUtils.CommandExecutionException { - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo.none(); - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NPM).withCacheDir("/foo/bar") - .build(); - createStubNode(nodeStub, npmStub, baseDir); - - File npmCacheDir = tools.getNpmCacheDir(); - - Assert.assertNotNull(npmCacheDir); - String npmCachePath = npmCacheDir.getPath(); - - Assert.assertEquals("foo/bar", - npmCachePath - .substring(FilenameUtils.getPrefixLength(npmCachePath)) - .replace("\\", "/")); - } - - private void assertNpmCommand(Supplier path) throws IOException { - createStubNode(false, true, vaadinHomeDir); - - assertThat(tools.getNodeExecutable(), containsString("node")); - - List npmExecutable = tools.getNpmExecutable(); - assertThat(npmExecutable.get(0), containsString("node")); - assertThat(npmExecutable.get(1), containsString(NPM_CLI_STRING)); - assertThat(npmExecutable.get(1), containsString(path.get())); - } - - private void assertNodeCommand(Supplier path) throws IOException { - createStubNode(true, true, vaadinHomeDir); - - assertThat(tools.getNodeExecutable(), containsString(DEFAULT_NODE)); - assertThat(tools.getNodeExecutable(), containsString(path.get())); - List npmExecutable = tools.getNpmExecutable(); - assertThat(npmExecutable.get(0), containsString(path.get())); - assertThat(npmExecutable.get(0), containsString(DEFAULT_NODE)); - assertThat(npmExecutable.get(1), containsString(NPM_CLI_STRING)); - } - - private void installGlobalPnpm(String pnpmVersion) { - Optional npmInstalled = frontendToolsLocator - .tryLocateTool(getCommand("npm")); - if (!npmInstalled.isPresent()) { - installNodeToTempFolder(); - } - doInstallPnpmGlobally(pnpmVersion, false); - } - - private String installNodeToTempFolder() { - return tools.installNode(FrontendTools.DEFAULT_NODE_VERSION, - new File(baseDir).toPath().toUri()); - } - - private void uninstallGlobalPnpm(String pnpmVersion) { - doInstallPnpmGlobally(pnpmVersion, true); - } - - private void doInstallPnpmGlobally(String pnpmVersion, boolean uninstall) { - final String pnpmPackageSpecifier = "pnpm" - + (uninstall ? "" : "@" + pnpmVersion); - final List installPnpmCommand = Arrays.asList(getCommand("npm"), - uninstall ? "rm" : "install", "-g", pnpmPackageSpecifier); - try { - FrontendUtils.executeCommand(installPnpmCommand); - } catch (FrontendUtils.CommandExecutionException e) { - throw new RuntimeException(String.format( - "Pnpm installation failed, pnpm version='%s', uninstall='%s'", - pnpmVersion, uninstall), e); - } - } - - private String getCommand(String name) { - return FrontendUtils.isWindows() ? name + ".cmd" : name; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendUtilsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendUtilsTest.java deleted file mode 100644 index 4fbab32aace..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendUtilsTest.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.function.DeploymentConfiguration; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.MockVaadinServletService; -import com.vaadin.flow.server.ServiceException; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServlet; -import com.vaadin.flow.server.VaadinServletService; -import com.vaadin.flow.server.frontend.installer.NodeInstaller; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; -import com.vaadin.tests.util.MockDeploymentConfiguration; - -import elemental.json.Json; -import elemental.json.JsonObject; -import static com.vaadin.flow.server.Constants.PACKAGE_JSON; -import static com.vaadin.flow.server.Constants.STATISTICS_JSON_DEFAULT; -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES; -import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_STATISTICS_JSON; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEPENDENCIES; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class FrontendUtilsTest { - - private static final String USER_HOME = "user.home"; - - private static Class CACHE_KEY; - - static { - try { - CACHE_KEY = Class.forName( - "com.vaadin.flow.server.frontend.FrontendUtils$Stats"); - } catch (ClassNotFoundException e) { - Assert.fail("Could not access cache key for stats.json!"); - } - } - - @Rule - public final TemporaryFolder tmpDir = new TemporaryFolder(); - - @Test - public void parseValidVersions() { - FrontendVersion sixPointO = new FrontendVersion(6, 0); - - FrontendVersion requiredVersionTen = new FrontendVersion(10, 0); - assertFalse( - FrontendUtils.isVersionAtLeast(sixPointO, requiredVersionTen)); - assertFalse(FrontendUtils.isVersionAtLeast(sixPointO, - new FrontendVersion(6, 1))); - assertTrue(FrontendUtils.isVersionAtLeast(new FrontendVersion("10.0.0"), - requiredVersionTen)); - assertTrue(FrontendUtils.isVersionAtLeast(new FrontendVersion("10.0.2"), - requiredVersionTen)); - assertTrue(FrontendUtils.isVersionAtLeast(new FrontendVersion("10.2.0"), - requiredVersionTen)); - } - - @Test - public void validateLargerThan_passesForNewVersion() { - FrontendUtils.validateToolVersion("test", new FrontendVersion("10.0.2"), - new FrontendVersion(10, 0)); - FrontendUtils.validateToolVersion("test", new FrontendVersion("10.1.2"), - new FrontendVersion(10, 0)); - FrontendUtils.validateToolVersion("test", new FrontendVersion("11.0.2"), - new FrontendVersion(10, 0)); - } - - @Test - public void validateLargerThan_throwsForOldVersion() { - try { - FrontendUtils.validateToolVersion("test", - new FrontendVersion(7, 5, 0), new FrontendVersion(10, 0)); - Assert.fail("No exception was thrown for old version"); - } catch (IllegalStateException e) { - Assert.assertTrue(e.getMessage().contains( - "Your installed 'test' version (7.5.0) is too old. Supported versions are 10.0+")); - } - } - - @Test - public void parseValidToolVersions() throws IOException { - Assert.assertEquals("10.11.12", - FrontendUtils.parseVersionString("v10.11.12")); - Assert.assertEquals("8.0.0", - FrontendUtils.parseVersionString("v8.0.0")); - Assert.assertEquals("8.0.0", FrontendUtils.parseVersionString("8.0.0")); - Assert.assertEquals("6.9.0", FrontendUtils.parseVersionString( - "Aktive Codepage: 1252\n" + "6.9.0\n" + "")); - } - - @Test(expected = IOException.class) - public void parseEmptyToolVersions() throws IOException { - FrontendUtils.parseVersionString(" \n"); - } - - @Test - public void assetsByChunkIsCorrectlyParsedFromStats() - throws IOException, ServiceException { - VaadinService service = setupStatsAssetMocks("ValidStats.json"); - - String statsAssetsByChunkName = FrontendUtils - .getStatsAssetsByChunkName(service); - - Assert.assertEquals( - "{\"bundle\": \"build/vaadin-bundle-1111.cache.js\",\"export\": \"build/vaadin-export-2222.cache.js\"}", - statsAssetsByChunkName); - } - - @Test - public void formattingError_assetsByChunkIsCorrectlyParsedFromStats() - throws IOException, ServiceException { - VaadinService service = setupStatsAssetMocks("MissFormatStats.json"); - - String statsAssetsByChunkName = FrontendUtils - .getStatsAssetsByChunkName(service); - - Assert.assertEquals( - "{\"bundle\": \"build/vaadin-bundle-1111.cache.js\"}", - statsAssetsByChunkName); - } - - @Test - public void noStatsFile_assetsByChunkReturnsNull() - throws IOException, ServiceException { - VaadinService service = getServiceWithResource(null); - - String statsAssetsByChunkName = FrontendUtils - .getStatsAssetsByChunkName(service); - - Assert.assertNull(statsAssetsByChunkName); - } - - @Test - public void should_getUnixRelativePath_when_givenTwoPaths() { - Path sourcePath = Mockito.mock(Path.class); - Path relativePath = Mockito.mock(Path.class); - Mockito.when(sourcePath.relativize(Mockito.any())) - .thenReturn(relativePath); - Mockito.when(relativePath.toString()) - .thenReturn("this\\is\\windows\\path"); - - String relativeUnixPath = FrontendUtils.getUnixRelativePath(sourcePath, - tmpDir.getRoot().toPath()); - Assert.assertEquals( - "Should replace windows path separator with unix path separator", - "this/is/windows/path", relativeUnixPath); - Mockito.when(relativePath.toString()).thenReturn("this/is/unix/path"); - - relativeUnixPath = FrontendUtils.getUnixRelativePath(sourcePath, - tmpDir.getRoot().toPath()); - Assert.assertEquals( - "Should keep the same path when it uses unix path separator", - "this/is/unix/path", relativeUnixPath); - } - - @Test - public void faultyStatsFileReturnsNull() - throws IOException, ServiceException { - VaadinService service = setupStatsAssetMocks("InvalidStats.json"); - - String statsAssetsByChunkName = FrontendUtils - .getStatsAssetsByChunkName(service); - - Assert.assertNull(statsAssetsByChunkName); - } - - @Test - public synchronized void getVaadinHomeDirectory_noVaadinFolder_folderIsCreated() - throws IOException { - String originalHome = System.getProperty(USER_HOME); - File home = tmpDir.newFolder(); - System.setProperty(USER_HOME, home.getPath()); - try { - File vaadinDir = new File(home, ".vaadin"); - if (vaadinDir.exists()) { - FileUtils.deleteDirectory(vaadinDir); - } - File vaadinHomeDirectory = FrontendUtils.getVaadinHomeDirectory(); - Assert.assertTrue(vaadinHomeDirectory.exists()); - Assert.assertTrue(vaadinHomeDirectory.isDirectory()); - - // access it one more time - vaadinHomeDirectory = FrontendUtils.getVaadinHomeDirectory(); - Assert.assertEquals(".vaadin", vaadinDir.getName()); - } finally { - System.setProperty(USER_HOME, originalHome); - } - } - - @Test(expected = IllegalStateException.class) - public synchronized void getVaadinHomeDirectory_vaadinFolderIsAFile_throws() - throws IOException { - String originalHome = System.getProperty(USER_HOME); - File home = tmpDir.newFolder(); - System.setProperty(USER_HOME, home.getPath()); - try { - File vaadinDir = new File(home, ".vaadin"); - if (vaadinDir.exists()) { - FileUtils.deleteDirectory(vaadinDir); - } - vaadinDir.createNewFile(); - FrontendUtils.getVaadinHomeDirectory(); - } finally { - System.setProperty(USER_HOME, originalHome); - } - } - - @Test - public void commandToString_longCommand_resultIsWrapped() { - List command = Arrays.asList("./node/node", - "./node_modules/webpack-dev-server/bin/webpack-dev-server.js", - "--config", "./webpack.config.js", "--port 57799", - "--env watchDogPort=57798", "-d", "--inline=false"); - String wrappedCommand = FrontendUtils.commandToString(".", command); - Assert.assertEquals("\n" + "./node/node \\ \n" - + " ./node_modules/webpack-dev-server/bin/webpack-dev-server.js \\ \n" - + " --config ./webpack.config.js --port 57799 \\ \n" - + " --env watchDogPort=57798 -d --inline=false \n", - wrappedCommand); - } - - @Test - public void commandToString_commandContainsBaseDir_baseDirIsReplaced() { - List command = Arrays.asList("./node/node", - "/somewhere/not/disclosable/node_modules/webpack-dev-server/bin/webpack-dev-server.js"); - String wrappedCommand = FrontendUtils - .commandToString("/somewhere/not/disclosable", command); - Assert.assertEquals("\n" + "./node/node \\ \n" - + " ./node_modules/webpack-dev-server/bin/webpack-dev-server.js \n", - wrappedCommand); - } - - @Test - public void getStatsAssetsByChunkName_getStatsFromClassPath_delegateToGetApplicationResource() - throws IOException { - VaadinServletService service = mockServletService(); - - ResourceProvider provider = mockResourceProvider(service); - - FrontendUtils.getStatsAssetsByChunkName(service); - - Mockito.verify(provider).getApplicationResource("foo"); - } - - @Test - public void getStatsAssetsByChunkName_getStatsFromClassPath_populatesStatsCache() - throws IOException, ServiceException { - VaadinService service = setupStatsAssetMocks("ValidStats.json"); - - assertNull("Stats cache should not be present", - service.getContext().getAttribute(CACHE_KEY)); - - // Populates cache - FrontendUtils.getStatsAssetsByChunkName(service); - - assertNotNull("Stats cache should be created", - service.getContext().getAttribute(CACHE_KEY)); - } - - @Test - public void clearCachedStatsContent_clearsCache() - throws IOException, ServiceException { - VaadinService service = setupStatsAssetMocks("ValidStats.json"); - - assertNull("Stats cache should not be present", - service.getContext().getAttribute(CACHE_KEY)); - // Can be invoked without cache - throws no exception - FrontendUtils.clearCachedStatsContent(service); - - // Populates cache - FrontendUtils.getStatsAssetsByChunkName(service); - - // Clears cache - FrontendUtils.clearCachedStatsContent(service); - - assertNull("Stats cache should not be present", - service.getContext().getAttribute(CACHE_KEY)); - } - - @Test - public void deleteNodeModules_nopIfNotExists() throws IOException { - File nodeModules = new File(tmpDir.getRoot(), "node_modules"); - FrontendUtils.deleteNodeModules(nodeModules); - } - - @Test(expected = IOException.class) - public void deleteNodeModules_throwsIfNotNamedNodeModules() - throws IOException { - File myModules = new File(tmpDir.getRoot(), "my_modules"); - myModules.mkdirs(); - FrontendUtils.deleteNodeModules(myModules); - } - - @Test - public void deleteNodeModules_canDeleteSymlinksAndNotFollowThem() - throws IOException { - - // Test fails on Windows due to UAC FileSystemException - Assume.assumeFalse(FrontendUtils.isWindows()); - - File externalDir = new File(tmpDir.getRoot(), "external"); - File externalLicense = new File(externalDir, "LICENSE"); - - externalLicense.getParentFile().mkdirs(); - externalLicense.createNewFile(); - - File nodeModules = new File(tmpDir.getRoot(), "node_modules"); - File containing = new File(nodeModules, ".pnpm/a/node_modules/dep"); - containing.mkdirs(); - File license = new File(containing, "LICENSE"); - license.createNewFile(); - - File linking = new File(nodeModules, ".pnpm/b/node_modules/dep"); - linking.getParentFile().mkdirs(); - Files.createSymbolicLink(linking.toPath(), - new File("../../a/node_modules/dep").toPath()); - - File linkingExternal = new File(nodeModules, - ".pnpm/b/node_modules/external"); - Files.createSymbolicLink(linkingExternal.toPath(), - new File("../../../../external").toPath()); - - Assert.assertTrue(nodeModules.exists()); - Assert.assertTrue(linking.exists()); - Assert.assertTrue(new File(linking, "LICENSE").exists()); - Assert.assertTrue(new File(linkingExternal, "LICENSE").exists()); - - FrontendUtils.deleteNodeModules(nodeModules); - - Assert.assertFalse(nodeModules.exists()); - Assert.assertTrue(externalLicense.exists()); - } - - @Test - public void symlinkByNpm_deleteDirectory_doesNotDeleteSymlinkFolderFiles() - throws IOException, ExecutionFailedException { - File npmFolder = tmpDir.newFolder(); - - File generatedPath = new File(npmFolder, "generated"); - generatedPath.mkdir(); - - File symbolic = new File(npmFolder, "symbolic"); - symbolic.mkdir(); - File linkFolderFile = new File(symbolic, "symbol.txt"); - linkFolderFile.createNewFile(); - - final JsonObject packageJson = Json.createObject(); - packageJson.put(DEPENDENCIES, Json.createObject()); - - packageJson.getObject(DEPENDENCIES).put("@symbolic/link", - "./" + symbolic.getName()); - - FileUtils.writeStringToFile(new File(npmFolder, PACKAGE_JSON), - packageJson.toJson(), StandardCharsets.UTF_8); - - ClassFinder finder = Mockito.mock(ClassFinder.class); - - Logger logger = Mockito.spy(LoggerFactory.getLogger(NodeUpdater.class)); - - NodeUpdater nodeUpdater = new NodeUpdater(finder, - Mockito.mock(FrontendDependencies.class), npmFolder, - generatedPath, TARGET, Mockito.mock(FeatureFlags.class)) { - - @Override - public void execute() { - } - - @Override - Logger log() { - return logger; - } - - }; - - new TaskRunNpmInstall(nodeUpdater, false, false, - FrontendTools.DEFAULT_NODE_VERSION, - URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT), false, - false, Collections.emptyList()).execute(); - - FrontendUtils.deleteNodeModules(new File(npmFolder, "node_modules")); - - Assert.assertTrue("Linked folder contents should not be removed.", - linkFolderFile.exists()); - } - - private ResourceProvider mockResourceProvider(VaadinService service) { - DeploymentConfiguration config = Mockito - .mock(DeploymentConfiguration.class); - - VaadinContext context = Mockito.mock(VaadinContext.class); - Lookup lookup = Mockito.mock(Lookup.class); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(lookup); - - ResourceProvider provider = Mockito.mock(ResourceProvider.class); - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(provider); - - Mockito.when(service.getDeploymentConfiguration()).thenReturn(config); - Mockito.when(service.getContext()).thenReturn(context); - - Mockito.when(config.isProductionMode()).thenReturn(true); - - Mockito.when(config.getStringProperty(SERVLET_PARAMETER_STATISTICS_JSON, - VAADIN_SERVLET_RESOURCES + STATISTICS_JSON_DEFAULT)) - .thenReturn("foo"); - return provider; - } - - private VaadinService setupStatsAssetMocks(String statsFile) - throws IOException, ServiceException { - String stats = IOUtils.toString(FrontendUtilsTest.class.getClassLoader() - .getResourceAsStream(statsFile), StandardCharsets.UTF_8); - - return getServiceWithResource(stats); - } - - private VaadinService getServiceWithResource(String content) - throws ServiceException, IOException { - MockDeploymentConfiguration configuration = new MockDeploymentConfiguration(); - configuration.setProductionMode(true); - MockVaadinServletService service = new MockVaadinServletService( - configuration); - - VaadinContext context = service.getContext(); - - Lookup lookup = Mockito.mock(Lookup.class); - context.setAttribute(Lookup.class, lookup); - - ResourceProvider provider = Mockito.mock(ResourceProvider.class); - - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(provider); - - if (content != null) { - File tmpFile = tmpDir.newFile(); - try (FileOutputStream outputStream = new FileOutputStream( - tmpFile)) { - IOUtils.write(content, outputStream, StandardCharsets.UTF_8); - } - Mockito.when(provider.getApplicationResource( - VAADIN_SERVLET_RESOURCES + STATISTICS_JSON_DEFAULT)) - .thenReturn(tmpFile.toURI().toURL()); - } - - return service; - } - - private VaadinServletService mockServletService() { - VaadinServletService service = Mockito.mock(VaadinServletService.class); - - VaadinServlet servlet = Mockito.mock(VaadinServlet.class); - Mockito.when(service.getServlet()).thenReturn(servlet); - return service; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendVersionTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendVersionTest.java deleted file mode 100644 index 2e79c4a8961..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/FrontendVersionTest.java +++ /dev/null @@ -1,280 +0,0 @@ -package com.vaadin.flow.server.frontend; - -import org.junit.Assert; -import org.junit.Test; - -import static com.helger.commons.mock.CommonsAssert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -public class FrontendVersionTest { - - @Test - public void stringParser_returnsExpectedVersions() { - FrontendVersion frontendVersion = new FrontendVersion("1.0.1"); - assertVersion(frontendVersion, 1, 0, 1, ""); - - frontendVersion = new FrontendVersion("6.10"); - assertVersion(frontendVersion, 6, 10, 0, ""); - - frontendVersion = new FrontendVersion("6.10-SNAPSHOT"); - assertVersion(frontendVersion, 6, 10, 0, "SNAPSHOT"); - - frontendVersion = new FrontendVersion("6.5.3.alpha1"); - assertVersion(frontendVersion, 6, 5, 3, "alpha1"); - } - - @Test - public void versionConstructors_returnExpectedVersions() { - FrontendVersion frontendVersion = new FrontendVersion(1, 2); - assertVersion(frontendVersion, 1, 2, 0, ""); - - frontendVersion = new FrontendVersion(1, 2, 5); - assertVersion(frontendVersion, 1, 2, 5, ""); - - frontendVersion = new FrontendVersion(1, 2, 5, "beta3"); - assertVersion(frontendVersion, 1, 2, 5, "beta3"); - } - - @Test - public void testFrontedEquality() { - FrontendVersion fromString = new FrontendVersion("1.1.0"); - FrontendVersion fromConstructor = new FrontendVersion(1, 1); - - assertTrue("Parsed string didn't equal constructor", - fromString.equals(fromConstructor)); - assertTrue("Constructor didn't equal parsed string", - fromConstructor.equals(fromString)); - - fromString = new FrontendVersion("1.1.alpha12"); - fromConstructor = new FrontendVersion(1, 1, 0, "alpha12"); - assertTrue("Major-Minor version with build identifier didn't match", - fromConstructor.equals(fromString)); - - fromString = new FrontendVersion("12.3.5.alpha12"); - fromConstructor = new FrontendVersion(12, 3, 5, "alpha12"); - assertTrue("Full version with build identifier didn't match", - fromString.equals(fromConstructor)); - } - - @Test - public void testIsEqualTo() { - FrontendVersion fromString = new FrontendVersion("1.1.0"); - FrontendVersion fromConstructor = new FrontendVersion(1, 1); - - assertTrue("Parsed string didn't equal constructor", - fromString.isEqualTo(fromConstructor)); - assertTrue("Constructor didn't equal parsed string", - fromConstructor.isEqualTo(fromString)); - - fromString = new FrontendVersion("1.1.alpha12"); - fromConstructor = new FrontendVersion(1, 1, 0, "alpha12"); - assertTrue("Major-Minor version with build identifier didn't match", - fromConstructor.isEqualTo(fromString)); - - fromString = new FrontendVersion("12.3.5.alpha12"); - fromConstructor = new FrontendVersion(12, 3, 5, "alpha12"); - assertTrue("Full version with build identifier didn't match", - fromString.isEqualTo(fromConstructor)); - } - - @Test // #12041 - public void testSimilarBuildIdentifiers() { - FrontendVersion version = new FrontendVersion("1.1.1-SNAPSHOT"); - FrontendVersion equals = new FrontendVersion("1.1.1-SNAPSHOT"); - - assertTrue("Versions be the same", version.isEqualTo(equals)); - assertFalse("Version should not be older", version.isOlderThan(equals)); - assertEquals("Versions should not have a difference", 0, - version.compareTo(equals)); - assertFalse("Version should not be newer", version.isNewerThan(equals)); - } - - @Test(expected = NumberFormatException.class) - public void faultyStringVersion_throwsException() { - new FrontendVersion("12.0b.1"); - } - - @Test(expected = NumberFormatException.class) - public void notANumber_throwsException() { - new FrontendVersion("a"); - } - - @Test(expected = NumberFormatException.class) - public void emptyString_throwsException() { - new FrontendVersion(""); - } - - @Test - public void onlyMajorVersion_allVersoinNumbersAreCalculated() { - assertVersion(new FrontendVersion("3"), 3, 0, 0, ""); - } - - @Test - public void versionHandlesTildeAndCaretVersions() { - assertVersion(new FrontendVersion("~1.3.0-beta1"), 1, 3, 0, "beta1"); - assertVersion(new FrontendVersion("~2.2"), 2, 2, 0, ""); - assertVersion(new FrontendVersion("^3.3.1"), 3, 3, 1, ""); - } - - @Test - public void olderVersionIsCalculatedCorrectly() { - FrontendVersion test = new FrontendVersion("2.2.0"); - - assertTrue("Should be older due to revision", - test.isOlderThan(new FrontendVersion("2.2.1"))); - assertTrue("Should be older due to minor", - test.isOlderThan(new FrontendVersion("2.3.0"))); - assertTrue("Should be older due to major", - test.isOlderThan(new FrontendVersion("3.2.0"))); - - assertFalse("Should be newer as target has buildIdentifier", - test.isOlderThan(new FrontendVersion("2.2.0-alpha1"))); - - assertFalse("Should be newer due to major", - test.isOlderThan(new FrontendVersion("1.2.0"))); - assertFalse("Should be newer due to minor", - test.isOlderThan(new FrontendVersion("2.1.0"))); - assertFalse("Should be newer due to minor", - test.isOlderThan(new FrontendVersion("2.1.2"))); - assertFalse("Should be newer due to minor", - test.isOlderThan(new FrontendVersion("1.5.2"))); - - assertFalse("Should be newer by major even with buildIdentifier", - test.isOlderThan(new FrontendVersion("1.2.0-alpha1"))); - } - - @Test - public void newerVersionIsCalculatedCorrectly() { - FrontendVersion test = new FrontendVersion("2.2.2"); - - assertTrue("Should be newer due to revision", - test.isNewerThan(new FrontendVersion("2.2.1"))); - assertTrue("Should be newer due to minor", - test.isNewerThan(new FrontendVersion("2.1.2"))); - assertTrue("Should be newer due to major", - test.isNewerThan(new FrontendVersion("1.2.2"))); - - assertTrue("Should be newer as target has buildIdentifier", - test.isNewerThan(new FrontendVersion("2.2.2-alpha1"))); - - assertFalse("Should be older due to major", - test.isNewerThan(new FrontendVersion("3.2.2"))); - assertFalse("Should be older due to minor", - test.isNewerThan(new FrontendVersion("2.3.2"))); - } - - @Test - public void olderVersionByBuildIdentifier() { - - FrontendVersion test = new FrontendVersion("2.0.0-RC1"); - - assertTrue("2.0.0 should be newer that RC1", - test.isOlderThan(new FrontendVersion("2.0.0"))); - assertTrue("RC2 should be newer that RC1", - test.isOlderThan(new FrontendVersion("2.0.0-RC2"))); - assertFalse("beta5 should be older than RC1", - test.isOlderThan(new FrontendVersion("2.0.0-beta5"))); - assertFalse("alpha4 should be older than RC1", - test.isOlderThan(new FrontendVersion("2.0.0-alpha4"))); - - test = new FrontendVersion("2.0.0"); - - assertFalse("RC2 should be older that 2.0.0", - test.isOlderThan(new FrontendVersion("2.0.0-RC2"))); - assertFalse("beta5 should be older than 2.0.0", - test.isOlderThan(new FrontendVersion("2.0.0-beta5"))); - assertFalse("alpha4 should be older than 2.0.0", - test.isOlderThan(new FrontendVersion("2.0.0-alpha4"))); - } - - @Test - public void newerVersionByBuildIdentifier() { - - FrontendVersion test = new FrontendVersion("2.0.0-alpha2"); - - assertTrue("alpha2 should be newer than alpha1", - test.isNewerThan(new FrontendVersion("2.0.0-alpha1"))); - assertFalse("alpha2 should be older than 2.0.0", - test.isNewerThan(new FrontendVersion("2.0.0"))); - assertFalse("alpha2 should be older than beta1", - test.isNewerThan(new FrontendVersion("2.0.0-beta1"))); - assertFalse("alpha2 should be older than RC1", - test.isNewerThan(new FrontendVersion("2.0.0-RC1"))); - - test = new FrontendVersion("2.0.0"); - - assertTrue("2.0.0 should be newer than alpha1", - test.isNewerThan(new FrontendVersion("2.0.0-alpha1"))); - assertTrue("2.0.0 should be older than beta1", - test.isNewerThan(new FrontendVersion("2.0.0-beta1"))); - assertTrue("2.0.0 should be older than RC1", - test.isNewerThan(new FrontendVersion("2.0.0-RC1"))); - } - - @Test - public void buildIdentifierNumbers_returnsAsExpected() { - - FrontendVersion test = new FrontendVersion("2.0.0-alpha6"); - assertTrue("2.0.0-alpha6 should be older than 2.0.0-alpha13", - test.isOlderThan(new FrontendVersion("2.0.0-alpha13"))); - - test = new FrontendVersion("2.0.0-alpha20"); - assertTrue("2.0.0-alpha20 should be newer than 2.0.0-alpha13", - test.isNewerThan(new FrontendVersion("2.0.0-alpha13"))); - assertFalse("2.0.0-alpha20 should be newer than 2.0.0-alpha13", - test.isOlderThan(new FrontendVersion("2.0.0-alpha13"))); - - assertTrue("2.0.0-alpha13 should not be older than 2.0.0-alpha20", - new FrontendVersion("2.0.0-alpha13").isOlderThan(test)); - assertFalse("2.0.0-alpha13 should not be older than 2.0.0-alpha20", - new FrontendVersion("2.0.0-alpha13").isNewerThan(test)); - - assertTrue("same versions should equal", - test.isEqualTo(new FrontendVersion("2.0.0.alpha20"))); - } - - @Test - public void testAgainstVersionWithValueInBuildInfo() { - FrontendVersion alpha3 = new FrontendVersion("2.0.0-alpha3"); - FrontendVersion five = new FrontendVersion("2.0.0.5"); - FrontendVersion fifteen = new FrontendVersion("2.0.0.15"); - - assertTrue("2.0.0-alpha3 should be older than 2.0.0.5", - alpha3.isOlderThan(five)); - assertFalse("2.0.0-alpha3 should be older than 2.0.0.5", - alpha3.isNewerThan(five)); - - assertTrue("2.0.0.5 should be newer than 2.0.0-alpha3", - five.isNewerThan(alpha3)); - assertFalse("2.0.0.5 should be newer than 2.0.0-alpha3", - five.isOlderThan(alpha3)); - - assertTrue("2.0.0.5 should be older than 2.0.0.15", - five.isOlderThan(fifteen)); - assertFalse("2.0.0.5 should be older than 2.0.0.15", - five.isNewerThan(fifteen)); - - assertTrue("2.0.0.15 should be newer than 2.0.0.5", - fifteen.isNewerThan(five)); - assertFalse("2.0.0.15 should be newer than 2.0.0.5", - fifteen.isOlderThan(five)); - - } - - private void assertVersion(FrontendVersion version, int major, int minor, - int revision, String build) { - Assert.assertEquals( - "Major version was wrong for " + version.getFullVersion(), - version.getMajorVersion(), major); - Assert.assertEquals( - "Minor version was wrong for " + version.getFullVersion(), - version.getMinorVersion(), minor); - Assert.assertEquals( - "Revision was wrong for " + version.getFullVersion(), - version.getRevision(), revision); - Assert.assertEquals( - "Build identifier was wrong for " + version.getFullVersion(), - version.getBuildIdentifier(), build); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/ImportExtractorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/ImportExtractorTest.java deleted file mode 100644 index 099dd202b41..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/ImportExtractorTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -public class ImportExtractorTest { - - @Test - public void removeComments_blockCommentsAreRemoved() { - ImportExtractor extractor = new ImportExtractor( - "/* comment \n sdf \n \n */import 'foo.js';"); - - Assert.assertEquals("import 'foo.js';", extractor.removeComments()); - } - - @Test - public void removeComments_lineCommentsAreRemoved() { - ImportExtractor extractor = new ImportExtractor( - "// sdfdsf \nimport from 'foo.js';\n //xxxxx \nimport {A} from bar.js;"); - Assert.assertEquals( - "\nimport from 'foo.js';\n" + " \n" - + "import {A} from bar.js;", - extractor.removeComments()); - } - - @Test - public void removeComments_blockCommentInsideImport() { - ImportExtractor extractor = new ImportExtractor( - "import from /*fdg \n */'foo.js';"); - Assert.assertEquals("import from 'foo.js';", - extractor.removeComments()); - } - - @Test - public void removeComments_lineCommentInsideImport() { - ImportExtractor extractor = new ImportExtractor( - "import from // xcvxcvcx\n//vcbcvbcv\n 'foo.js';"); - Assert.assertEquals("import from \n\n 'foo.js';", - extractor.removeComments()); - } - - @Test - public void getImportsWithBlockComment() { - ImportExtractor extractor = new ImportExtractor( - "/* comment \n sdf \n \n */ import /* ddddddd*/'foo.js';"); - List importedPaths = extractor.getImportedPaths(); - Assert.assertEquals(1, importedPaths.size()); - Assert.assertEquals("foo.js", importedPaths.get(0)); - } - - @Test - public void getImportsWithLineComments() { - ImportExtractor extractor = new ImportExtractor( - "// sdfdsf \n import from 'foo.js';\n //xxxxx \n import {A} // sdfsf\n from bar.js;"); - List importedPaths = extractor.getImportedPaths(); - Assert.assertEquals(2, importedPaths.size()); - Assert.assertEquals("foo.js", importedPaths.get(0)); - Assert.assertEquals("bar.js", importedPaths.get(1)); - } - - @Test - public void getImport_lineHasNoSemicolon() { - ImportExtractor extractor = new ImportExtractor( - "import {A} from 'foo.js'; import from 'bar.js'\n import from 'baz.js'"); - List importedPaths = extractor.getImportedPaths(); - Assert.assertEquals(3, importedPaths.size()); - Assert.assertEquals("foo.js", importedPaths.get(0)); - Assert.assertEquals("bar.js", importedPaths.get(1)); - Assert.assertEquals("baz.js", importedPaths.get(2)); - } - - @Test - public void getImports_thereAreNoImportsAtAll_noImportsFound() { - ImportExtractor extractor = new ImportExtractor( - "const container = document.createElement('template');\n" + "\n" - + " container.innerHTML = `\n" - + " \n" - + " \n" - + " `;\n" - + " document.head.appendChild(container.content);"); - - Assert.assertEquals(0, extractor.getImportedPaths().size()); - } - - @Test - public void getImports_onlyImportAsFirstStatementsAreCounted() { - ImportExtractor extractor = new ImportExtractor( - "import {A} from 'foo.js'; \n some text \n import from 'ignored.js';"); - - List importedPaths = extractor.getImportedPaths(); - Assert.assertEquals(1, importedPaths.size()); - Assert.assertEquals("foo.js", importedPaths.get(0)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/JarContentsManagerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/JarContentsManagerTest.java deleted file mode 100644 index 578486d3395..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/JarContentsManagerTest.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.jar.JarFile; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; - -import com.vaadin.flow.testutil.TestUtils; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; - -/** - * @author Vaadin Ltd - * @since 1.0. - */ -public class JarContentsManagerTest { - @Rule - public TemporaryFolder testDirectory = new TemporaryFolder(); - - @Rule - public final ExpectedException expectedException = ExpectedException.none(); - - private final JarContentsManager jarContentsManager = new JarContentsManager(); - private final File testJar = TestUtils.getTestJar(); - - @Test - public void getFileContents_directoryInsteadOfJar() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage(String.format( - "Expect '%s' to be an existing file", testDirectory.getRoot())); - - jarContentsManager.getFileContents(testDirectory.getRoot(), "test"); - } - - @Test - public void getFileContents_notAJarFile() throws IOException { - File testFile = testDirectory.newFile("test"); - - expectedException.expect(UncheckedIOException.class); - expectedException.expectMessage( - String.format("Failed to retrieve file '%s' from jar '%s'", - "test", testFile)); - - jarContentsManager.getFileContents(testFile, "test"); - } - - @Test - public void getFileContents_nonExistingJarFile() { - File test = new File("test"); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage( - String.format("Expect '%s' to be an existing file", test)); - - jarContentsManager.getFileContents(test, "test"); - } - - @Test - public void getFileContents_nonExistingFile() { - byte[] fileContents = jarContentsManager.getFileContents(testJar, - "blah"); - - assertNull("Expect to have non-empty file from jar", fileContents); - } - - @Test - public void getFileContents_existingFile() { - byte[] fileContents = jarContentsManager.getFileContents(testJar, - "META-INF/resources/webjars/paper-button/2.0.0/bower.json"); - - assertNotNull("Expect to have non-empty file from jar", fileContents); - assertTrue("Expect to have non-empty file from jar", - fileContents.length > 0); - } - - @Test - public void containsPath_directoryInsteadOfJar() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage(String.format( - "Expect '%s' to be an existing file", testDirectory.getRoot())); - - jarContentsManager.containsPath(testDirectory.getRoot(), "test"); - } - - @Test - public void containsPath_notAJarFile() throws IOException { - File testFile = testDirectory.newFile("test"); - - expectedException.expect(UncheckedIOException.class); - expectedException.expectMessage( - String.format("Failed to retrieve file '%s' from jar '%s'", - "test", testFile)); - - jarContentsManager.containsPath(testFile, "test"); - } - - @Test - public void containsPath_nonExistingJarFile() { - File test = new File("test"); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage( - String.format("Expect '%s' to be an existing file", test)); - - jarContentsManager.containsPath(test, "test"); - } - - @Test - public void containsPath_nonExistingPath() { - String nonExistingPath = "should not exist"; - - assertFalse( - String.format("Test jar '%s' should not contain path '%s'", - testJar, nonExistingPath), - jarContentsManager.containsPath(testJar, nonExistingPath)); - } - - @Test - public void containsPath_existingFile() { - String existingPath = "META-INF/resources/webjars/"; - - assertTrue( - String.format("Test jar '%s' should contain path '%s'", testJar, - existingPath), - jarContentsManager.containsPath(testJar, existingPath)); - } - - /* - * Test for issue: flow fails to serve static resources from latest webjars - * #6241 https://github.com/vaadin/flow/issues/6241 - */ - @Test - public void containsPath_missingDirectoryStructure_scansForMatch() { - String existingPathLocal = "META-INF/resources/webjars/"; - File testJarLocal = TestUtils.getTestJar("test-jar-issue-6241.jar"); - - assertTrue( - String.format("Test jar '%s' should contain path '%s'", testJar, - existingPathLocal), - jarContentsManager.containsPath(testJarLocal, - existingPathLocal)); - } - - @Test - public void findFiles_directoryInsteadOfJar() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage(String.format( - "Expect '%s' to be an existing file", testDirectory.getRoot())); - - jarContentsManager.findFiles(testDirectory.getRoot(), "test", "test"); - } - - @Test - public void findFiles_notAJarFile() throws IOException { - File testFile = testDirectory.newFile("test"); - - expectedException.expect(UncheckedIOException.class); - expectedException - .expectMessage("java.util.zip.ZipException: zip file is empty"); - - jarContentsManager.findFiles(testFile, "test", "test"); - } - - @Test - public void findFiles_nonExistingJarFile() { - File test = new File("test"); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage( - String.format("Expect '%s' to be an existing file", test)); - - jarContentsManager.findFiles(test, "test", "test"); - } - - @Test - public void findFiles_nonExistingFile() { - List result = jarContentsManager.findFiles(testJar, "blah", - "nope"); - - assertTrue("Expect to have empty results for non-existing file", - result.isEmpty()); - } - - @Test - public void findFiles_existingFiles() { - String resourceName = "vaadin-charts-webjar-6.0.0-alpha3.jar"; - String searchName = "bower.json"; - - List bowerJsons = jarContentsManager - .findFiles(TestUtils.getTestJar(resourceName), "", searchName); - - assertEquals( - String.format("Expect '%s' WebJar to contain two '%s' files", - resourceName, searchName), - 2, bowerJsons.size()); - assertTrue(String.format( - "Expect all found paths to end with the file name searched for: '%s'", - searchName), - bowerJsons.stream() - .allMatch(path -> path.endsWith('/' + searchName))); - } - - @Test - public void findFiles_existingFiles_baseDirectoryMatters() { - String resourceName = "vaadin-charts-webjar-6.0.0-alpha3.jar"; - String testPath = "META-INF/resources/webjars/highcharts/5.0.14/"; - String searchName = "bower.json"; - - List bowerJson = jarContentsManager.findFiles( - TestUtils.getTestJar(resourceName), testPath, searchName); - - assertEquals(String.format( - "Expect '%s' WebJar to contain one '%s' file in directory '%s'", - resourceName, searchName, testPath), 1, bowerJson.size()); - } - - @Test - public void copyFilesFromJar_nullJarFile() { - expectedException.expect(NullPointerException.class); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(null, null, - testDirectory.getRoot()); - } - - @Test - public void copyFilesFromJar_notAJarFile() throws IOException { - File testFile = testDirectory.newFile("test"); - - expectedException.expect(UncheckedIOException.class); - expectedException.expectMessage(String.format( - "Failed to extract files from jarFile '%s' to directory '%s'", - testFile, testDirectory.getRoot())); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testFile, null, - testDirectory.getRoot()); - } - - @Test - public void copyFilesFromJar_nonExistingJarFile() { - File test = new File("test"); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage( - String.format("Expect '%s' to be an existing file", test)); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(test, null, - testDirectory.getRoot()); - } - - @Test - public void copyFilesFromJar_directoryInsteadOfJar() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage(String.format( - "Expect '%s' to be an existing file", testDirectory.getRoot())); - - jarContentsManager.copyFilesFromJarTrimmingBasePath( - testDirectory.getRoot(), null, testDirectory.getRoot()); - } - - @Test - public void copyFilesFromJar_nullOutputDirectory() { - expectedException.expect(NullPointerException.class); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, null, - null); - } - - @Test - public void copyFilesFromJar_fileInsteadOfDirectory() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage(String - .format("Expect '%s' to be an existing directory", testJar)); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, null, - testJar); - } - - @Test - public void copyFilesFromJar_noBasePath_noExclusions() { - assertThat( - "Do not expect any files in temporary directory before the test", - TestUtils.listFilesRecursively(testDirectory.getRoot()).size(), - is(0)); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, null, - testDirectory.getRoot()); - - assertThat("Temporary directory should have files after jar copied", - TestUtils.listFilesRecursively(testDirectory.getRoot()).size(), - is(not(0))); - } - - @Test - public void copyFilesFromJar_noBasePath_excludeEverything() { - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, null, - testDirectory.getRoot(), "*"); - assertThat( - "Do not expect any files with filter that excludes everything", - TestUtils.listFilesRecursively(testDirectory.getRoot()).size(), - is(0)); - } - - @Test - public void copyFilesFromJar_withBasePath_noExclusions() - throws IOException { - String basePath = "META-INF/maven/"; - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, basePath, - testDirectory.getRoot()); - - List resultingPaths = TestUtils - .listFilesRecursively(testDirectory.getRoot()); - assertThat(String.format( - "Expect jar '%s' to contain files with base path '%s'", testJar, - basePath), resultingPaths.size(), is(not(0))); - assertTrue("Resulting paths should not contain base path = " + basePath, - resultingPaths.stream() - .noneMatch(path -> path.contains(basePath))); - } - - @Test - public void copyFilesFromJar_exclusionsWork() throws IOException { - String basePath = "META-INF/maven"; - - File notFilteredCopyingDirectory = testDirectory - .newFolder("notFiltered"); - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, basePath, - notFilteredCopyingDirectory); - List notFilteredPaths = TestUtils - .listFilesRecursively(notFilteredCopyingDirectory); - - File filteredCopyingDirectory = testDirectory.newFolder("filtered"); - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, basePath, - filteredCopyingDirectory, "*.xml"); - List filteredPaths = TestUtils - .listFilesRecursively(filteredCopyingDirectory); - - assertTrue( - "Filtered paths' count should be less than non filtered paths' count", - filteredPaths.size() < notFilteredPaths.size()); - assertTrue("Not filtered paths should contain xml files", - notFilteredPaths.stream() - .anyMatch(path -> path.endsWith(".xml"))); - assertTrue("Paths with '*.xml' exclusion should not contain xml files", - filteredPaths.stream() - .noneMatch(path -> path.endsWith(".xml"))); - } - - @Test - public void copyFilesFromJar_basePathAppendedWithTrailingSlash() - throws IOException { - String basePath1 = "META-INF/maven"; - File basePath1Directory = testDirectory.newFolder("basePath1"); - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, basePath1, - basePath1Directory); - List basePath1Paths = TestUtils - .listFilesRecursively(basePath1Directory); - - String basePath2 = basePath1 + '/'; - File basePath2Directory = testDirectory.newFolder("basePath2"); - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, basePath2, - basePath2Directory); - List basePath2Paths = TestUtils - .listFilesRecursively(basePath2Directory); - - assertEquals( - "Base path without trailing slash should be treated the same as base path with one", - basePath1Paths, basePath2Paths); - } - - @Test - public void copyFilesFromJar_copiedFromBasePathResultsAreContainedInAllPaths() - throws IOException { - File allFilesDirectory = testDirectory.newFolder("all"); - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, null, - allFilesDirectory); - List allPaths = TestUtils - .listFilesRecursively(allFilesDirectory); - - String basePath = "/META-INF/maven"; - File filteredFilesDirectory = testDirectory.newFolder("filtered"); - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, basePath, - filteredFilesDirectory); - List filteredPaths = TestUtils - .listFilesRecursively(filteredFilesDirectory); - List filteredPathsPrefixedByBasePath = filteredPaths.stream() - .map(path -> basePath + path).collect(Collectors.toList()); - - assertTrue("Filtered paths' count should be less than all paths' count", - filteredPaths.size() < allPaths.size()); - assertTrue("base path + filtered path should be contained in all paths", - allPaths.containsAll(filteredPathsPrefixedByBasePath)); - } - - @Test - public void copyFilesFromJar_casePreserved() { - File outputDirectory = testDirectory.getRoot(); - String jarDirectory = "META-INF/resources/webjars/paper-button/2.0.0/.github/"; - File testJar = TestUtils.getTestJar("paper-button-2.0.0.jar"); - List originalFiles = listFilesInJar(testJar, jarDirectory); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, - jarDirectory, outputDirectory); - - Set copiedFiles = new HashSet<>( - TestUtils.listFilesRecursively(outputDirectory)); - - assertEquals(String.format( - "Number of files in jar '%s' in jar directory '%s' and number of copied files should match.", - testJar, jarDirectory), originalFiles.size(), - copiedFiles.size()); - - copiedFiles.forEach(copiedFile -> assertTrue(String.format( - "Failed to find copied file '%s' in files '%s' from jar '%s'", - copiedFile, originalFiles, testJar), - originalFiles.stream() - .anyMatch(file -> file.endsWith(copiedFile)))); - } - - @Test - public void copyFilesFromJar_doNotUpdateFileIfContentIsTheSame() { - File outputDirectory = testDirectory.getRoot(); - String jarDirectory = "META-INF/resources/webjars/paper-button"; - File testJar = TestUtils.getTestJar("paper-button-2.0.0.jar"); - File jsonFile = copyFilesFromJar(outputDirectory, jarDirectory, - testJar); - - long timestamp = System.currentTimeMillis(); - Assert.assertTrue(FileUtils.isFileOlder(jsonFile, timestamp)); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, - jarDirectory, outputDirectory); - - // The file is still older - Assert.assertTrue(FileUtils.isFileOlder(jsonFile, timestamp)); - } - - @Test - public void copyFilesFromJar_updateFileIfContentIsNotTheSame() - throws IOException { - File outputDirectory = testDirectory.getRoot(); - String jarDirectory = "META-INF/resources/webjars/paper-button"; - File testJar = TestUtils.getTestJar("paper-button-2.0.0.jar"); - File jsonFile = copyFilesFromJar(outputDirectory, jarDirectory, - testJar); - - String originalContent = FileUtils - .readLines(jsonFile, StandardCharsets.UTF_8).stream() - .collect(Collectors.joining("")); - - String content = "{}"; - FileUtils.write(jsonFile, content, StandardCharsets.UTF_8); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, - jarDirectory, outputDirectory); - - Assert.assertNotEquals(content, - FileUtils.readLines(jsonFile, StandardCharsets.UTF_8).stream() - .collect(Collectors.joining(""))); - Assert.assertEquals(originalContent, - FileUtils.readLines(jsonFile, StandardCharsets.UTF_8).stream() - .collect(Collectors.joining(""))); - } - - private File copyFilesFromJar(File outputDirectory, String jarDirectory, - File testJar) { - List originalFiles = listFilesInJar(testJar, jarDirectory); - - Optional json = originalFiles.stream() - .filter(fileName -> fileName.endsWith(".json")).findFirst(); - - // self check - assert json.isPresent(); - - String jsonPath = json.get(); - jsonPath = jsonPath.substring(jarDirectory.length() + 1); - - jarContentsManager.copyFilesFromJarTrimmingBasePath(testJar, - jarDirectory, outputDirectory); - - File jsonFile = new File(outputDirectory, jsonPath); - - // self check - assert jsonFile.exists(); - return jsonFile; - } - - private List listFilesInJar(File jar, String jarDirectory) { - try (JarFile jarFile = new JarFile(jar, false)) { - return jarFile.stream().filter(file -> !file.isDirectory()) - .filter(file -> file.getName().startsWith(jarDirectory)) - .map(ZipEntry::getName).collect(Collectors.toList()); - } catch (IOException e) { - throw new RuntimeException( - String.format("Failed to list files in jarFile '%s'", jar), - e); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/MockLogger.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/MockLogger.java deleted file mode 100644 index d679b19d420..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/MockLogger.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend; - -import org.slf4j.Logger; -import org.slf4j.Marker; - -public class MockLogger implements Logger { - - StringBuilder logs = new StringBuilder(); - - public static String TRACE = "[Trace] "; - public static String DEBUG = "[Debug] "; - public static String WARN = "[Warning] "; - public static String ERROR = "[Error] "; - public static String INFO = "[Info] "; - - public String getLogs() { - return logs.toString().replaceAll("\r", ""); - } - - public void clearLogs() { - logs = new StringBuilder(); - } - - @Override - public String getName() { - return null; - } - - @Override - public boolean isTraceEnabled() { - return true; - } - - @Override - public void trace(String s) { - logs.append(TRACE).append(s).append("\n"); - } - - @Override - public void trace(String s, Object o) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(TRACE).append(s).append("\n"); - - } - - @Override - public void trace(String s, Object o, Object o1) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - s = s.replaceFirst("\\{\\}", - o1.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(TRACE).append(s).append("\n"); - - } - - @Override - public void trace(String s, Object... objects) { - logs.append(TRACE); - for (Object object : objects) { - s = s.replaceFirst("\\{\\}", - object.toString().replaceAll("\\\\", "\\\\\\\\")); - } - logs.append(s).append("\n"); - } - - @Override - public void trace(String s, Throwable throwable) { - logs.append(TRACE).append(s).append("\n"); - } - - @Override - public boolean isTraceEnabled(Marker marker) { - return true; - } - - @Override - public void trace(Marker marker, String s) { - throw new UnsupportedOperationException(); - } - - @Override - public void trace(Marker marker, String s, Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public void trace(Marker marker, String s, Object o, Object o1) { - throw new UnsupportedOperationException(); - } - - @Override - public void trace(Marker marker, String s, Object... objects) { - throw new UnsupportedOperationException(); - } - - @Override - public void trace(Marker marker, String s, Throwable throwable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isDebugEnabled() { - return true; - } - - @Override - public void debug(String s) { - logs.append(DEBUG).append(s).append("\n"); - } - - @Override - public void debug(String s, Object o) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(DEBUG).append(s).append("\n"); - } - - @Override - public void debug(String s, Object o, Object o1) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - s = s.replaceFirst("\\{\\}", - o1.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(DEBUG).append(s).append("\n"); - } - - @Override - public void debug(String s, Object... objects) { - logs.append(DEBUG); - for (Object object : objects) { - s = s.replaceFirst("\\{\\}", - object.toString().replaceAll("\\\\", "\\\\\\\\")); - } - logs.append(s).append("\n"); - } - - @Override - public void debug(String s, Throwable throwable) { - logs.append(DEBUG).append(s).append("\n"); - } - - @Override - public boolean isDebugEnabled(Marker marker) { - return true; - } - - @Override - public void debug(Marker marker, String s) { - throw new UnsupportedOperationException(); - } - - @Override - public void debug(Marker marker, String s, Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public void debug(Marker marker, String s, Object o, Object o1) { - throw new UnsupportedOperationException(); - } - - @Override - public void debug(Marker marker, String s, Object... objects) { - throw new UnsupportedOperationException(); - } - - @Override - public void debug(Marker marker, String s, Throwable throwable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isInfoEnabled() { - return true; - } - - @Override - public void info(String s) { - logs.append(INFO).append(s).append("\n"); - } - - @Override - public void info(String s, Object o) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(INFO).append(s).append("\n"); - } - - @Override - public void info(String s, Object o, Object o1) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - s = s.replaceFirst("\\{\\}", - o1.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(INFO).append(s).append("\n"); - } - - @Override - public void info(String s, Object... objects) { - logs.append(INFO); - for (Object object : objects) { - s = s.replaceFirst("\\{\\}", - object.toString().replaceAll("\\\\", "\\\\\\\\")); - } - logs.append(s).append("\n"); - } - - @Override - public void info(String s, Throwable throwable) { - logs.append(INFO).append(s).append("\n"); - } - - @Override - public boolean isInfoEnabled(Marker marker) { - return true; - } - - @Override - public void info(Marker marker, String s) { - throw new UnsupportedOperationException(); - } - - @Override - public void info(Marker marker, String s, Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public void info(Marker marker, String s, Object o, Object o1) { - throw new UnsupportedOperationException(); - } - - @Override - public void info(Marker marker, String s, Object... objects) { - throw new UnsupportedOperationException(); - } - - @Override - public void info(Marker marker, String s, Throwable throwable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isWarnEnabled() { - return true; - } - - @Override - public void warn(String s) { - logs.append(WARN).append(s).append("\n"); - } - - @Override - public void warn(String s, Object o) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(WARN).append(s).append("\n"); - } - - @Override - public void warn(String s, Object... objects) { - logs.append(WARN); - for (Object object : objects) { - s = s.replaceFirst("\\{\\}", - object.toString().replaceAll("\\\\", "\\\\\\\\")); - } - logs.append(s).append("\n"); - } - - @Override - public void warn(String s, Object o, Object o1) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - s = s.replaceFirst("\\{\\}", - o1.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(WARN).append(s).append("\n"); - } - - @Override - public void warn(String s, Throwable throwable) { - logs.append(WARN).append(s).append("\n"); - } - - @Override - public boolean isWarnEnabled(Marker marker) { - return true; - } - - @Override - public void warn(Marker marker, String s) { - throw new UnsupportedOperationException(); - } - - @Override - public void warn(Marker marker, String s, Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public void warn(Marker marker, String s, Object o, Object o1) { - throw new UnsupportedOperationException(); - } - - @Override - public void warn(Marker marker, String s, Object... objects) { - throw new UnsupportedOperationException(); - } - - @Override - public void warn(Marker marker, String s, Throwable throwable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isErrorEnabled() { - return true; - } - - @Override - public void error(String s) { - logs.append(ERROR).append(s).append("\n"); - } - - @Override - public void error(String s, Object o) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(ERROR).append(s).append("\n"); - } - - @Override - public void error(String s, Object o, Object o1) { - s = s.replaceFirst("\\{\\}", - o.toString().replaceAll("\\\\", "\\\\\\\\")); - s = s.replaceFirst("\\{\\}", - o1.toString().replaceAll("\\\\", "\\\\\\\\")); - logs.append(ERROR).append(s).append("\n"); - } - - @Override - public void error(String s, Object... objects) { - logs.append(ERROR); - for (Object object : objects) { - s = s.replaceFirst("\\{\\}", - object.toString().replaceAll("\\\\", "\\\\\\\\")); - } - logs.append(s).append("\n"); - } - - @Override - public void error(String s, Throwable throwable) { - logs.append(ERROR).append(s).append("\n"); - } - - @Override - public boolean isErrorEnabled(Marker marker) { - return true; - } - - @Override - public void error(Marker marker, String s) { - throw new UnsupportedOperationException(); - } - - @Override - public void error(Marker marker, String s, Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public void error(Marker marker, String s, Object o, Object o1) { - throw new UnsupportedOperationException(); - } - - @Override - public void error(Marker marker, String s, Object... objects) { - throw new UnsupportedOperationException(); - } - - @Override - public void error(Marker marker, String s, Throwable throwable) { - throw new UnsupportedOperationException(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksExecutionTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksExecutionTest.java deleted file mode 100644 index 6db414a2351..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksExecutionTest.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.vaadin.flow.server.frontend; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.ExecutionFailedException; - -import static com.vaadin.flow.server.Constants.TARGET; - -/** - * Test that commands in NodeTasks are always executed in a predefined order. - */ -@RunWith(Parameterized.class) -public class NodeTasksExecutionTest { - - private static final String DEV_SERVER_VITE = "VITE"; - private static final String DEV_SERVER_WEBPACK = "WEBPACK"; - - @Parameterized.Parameters(name = "{0}") - public static Collection devServers() { - return List.of(DEV_SERVER_VITE, DEV_SERVER_WEBPACK); - } - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Parameterized.Parameter - public String devServerImpl; - - private NodeTasks nodeTasks; - private List commandsMock; - private List> commandsOrder; - private List> executionOrder; - private List commands; - - @Before - public void init() throws Exception { - - // Make a builder that doesn't add any commands. - NodeTasks.Builder builder = new NodeTasks.Builder( - Mockito.mock(Lookup.class), null, TARGET); - builder.withProductionMode(false); - - if (DEV_SERVER_WEBPACK.equals(devServerImpl)) { - builder.useV14Bootstrap(true); - builder.setJavaResourceFolder(temporaryFolder.getRoot()); - createFeatureFlagsFile( - "com.vaadin.experimental.webpackForFrontendBuild=true"); - } - - nodeTasks = builder.build(); - - // get the private list of task execution order - final Field commandOrderField = NodeTasks.class - .getDeclaredField("commandOrder"); - commandOrderField.setAccessible(true); - commandsOrder = (List>) commandOrderField - .get(nodeTasks); - - executionOrder = new ArrayList<>(commandsOrder.size()); - commandsMock = mockCommandsRandomOrder(commandsOrder, executionOrder); - - // get the private commands list - final Field commandsField = NodeTasks.class - .getDeclaredField("commands"); - commandsField.setAccessible(true); - commands = (List) commandsField.get(nodeTasks); - - if (DEV_SERVER_VITE.equals(devServerImpl)) { - // With Vite we always have two default tasks that cannot be reomve - // by configuring builder - commands.clear(); - } - - Assert.assertEquals("No commands should be added initially, " - + "update mock builder so that we don't automatically add any tasks!", - 0, commands.size()); - } - - private void createFeatureFlagsFile(String contents) throws IOException { - Files.writeString(temporaryFolder - .newFile(FeatureFlags.PROPERTIES_FILENAME).toPath(), contents); - } - - @Test - public void nodeTasks_alwaysExecutedInDefinedOrder() - throws ExecutionFailedException { - - // Assemble the command list with random order - commands.addAll(commandsMock); - - nodeTasks.execute(); - - Assert.assertEquals("Amount of tasks executed was more than expected", - commandsOrder.size(), executionOrder.size()); - Assert.assertEquals("Tasks were executed in an unexpected order", - commandsOrder, executionOrder); - } - - @Test - public void nodeTasksContainsUnlistedCommand_throwsUnknownTaskException() { - // Assemble the command list with random order - commands.add(commandsMock.get(0)); - commands.add(new NewTask()); - - Assert.assertThrows( - "NodeTasks execution should fail due to unknown task in execution list", - UnknownTaskException.class, nodeTasks::execute); - } - - private class NewTask implements FallibleCommand { - @Override - public void execute() throws ExecutionFailedException { - } - } - - /** - * Generate mocks for each command and shuffle the list to simulate random - * add order in NodeTasks. - * - * @param commandsOrder - * commands to execute array - * @param executionOrder - * array to add execution into - * @return shuffled list of FallibleCommands to execute - * @throws ExecutionFailedException - * thrown by actual commands - */ - private List mockCommandsRandomOrder( - List> commandsOrder, - List> executionOrder) - throws ExecutionFailedException { - - List commands = new ArrayList<>(commandsOrder.size()); - - for (Class command : commandsOrder) { - final FallibleCommand mock = Mockito.mock(command); - commands.add(mock); - // When execute() is called add executing command to execution list. - Mockito.doAnswer(invocation -> { - executionOrder.add(command); - return null; - }).when(mock).execute(); - } - - Collections.shuffle(commands); - - return commands; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksHillaTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksHillaTest.java deleted file mode 100644 index 32484084946..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksHillaTest.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.frontend.NodeTasks.Builder; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; -import org.apache.commons.io.FileUtils; -import org.junit.*; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.*; -import static org.mockito.Mockito.*; - -public class NodeTasksHillaTest { - - @Rule - public MockitoRule rule = MockitoJUnit.rule(); - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private static final String USER_DIR = "user.dir"; - - private static String globalUserDirValue; - private static String globalFrontendDirValue; - private static String globalGeneratedDirValue; - - private String userDir; - - private File propertiesDir; - - @Mock - private Lookup lookup; - - @Mock - private EndpointGeneratorTaskFactory endpointGeneratorTaskFactory; - - @Mock - private TaskGenerateOpenAPI taskGenerateOpenAPI; - - @Mock - private TaskGenerateEndpoint taskGenerateEndpoint; - - @Mock - private TaskGenerateHilla taskGenerateHilla; - - private Builder builder; - - @Before - public void setup() throws Exception { - userDir = temporaryFolder.getRoot().getAbsolutePath(); - System.setProperty(USER_DIR, userDir); - System.clearProperty(PARAM_FRONTEND_DIR); - System.clearProperty(PARAM_GENERATED_DIR); - - propertiesDir = temporaryFolder.newFolder(); - - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(lookup).lookup(ClassFinder.class); - Mockito.doReturn(taskGenerateOpenAPI).when(endpointGeneratorTaskFactory) - .createTaskGenerateOpenAPI(any(), any(), any(), any()); - Mockito.doReturn(taskGenerateEndpoint) - .when(endpointGeneratorTaskFactory) - .createTaskGenerateEndpoint(any(), any(), any(), any()); - Mockito.doReturn(endpointGeneratorTaskFactory).when(lookup) - .lookup(EndpointGeneratorTaskFactory.class); - - Mockito.doReturn(taskGenerateHilla).when(lookup) - .lookup(TaskGenerateHilla.class); - - builder = new Builder(lookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder(new File(userDir, - FrontendUtils.GENERATED - + FrontendUtils.JAR_RESOURCES_FOLDER)) - .withFrontendGeneratedFolder(new File(userDir)) - .withEndpointSourceFolder(new File(userDir)) - .withEndpointGeneratedOpenAPIFile(new File(userDir)) - .setJavaResourceFolder(propertiesDir); - } - - @BeforeClass - public static void setupBeforeClass() { - globalUserDirValue = System.getProperty(USER_DIR); - globalFrontendDirValue = System.getProperty(PARAM_FRONTEND_DIR); - globalGeneratedDirValue = System.getProperty(PARAM_GENERATED_DIR); - } - - @AfterClass - public static void tearDownAfterClass() { - setPropertyIfPresent(USER_DIR, globalUserDirValue); - setPropertyIfPresent(PARAM_FRONTEND_DIR, globalFrontendDirValue); - setPropertyIfPresent(PARAM_GENERATED_DIR, globalGeneratedDirValue); - } - - @Test - public void should_useHillaEngine_whenEnabled() - throws ExecutionFailedException, IOException { - runEndpointTasks(true); - verifyHillaTask(true); - verifyOldGenerator(false); - } - - @Test - public void should_useOldGenerator_whenHillaGeneratorNotEnabled() - throws ExecutionFailedException, IOException { - runEndpointTasks(false); - verifyHillaTask(false); - verifyOldGenerator(true); - } - - @Test - public void should_notHillaEngine_whenOpenAPIFileIsNull() - throws ExecutionFailedException, IOException { - builder.withEndpointGeneratedOpenAPIFile(null); - - runEndpointTasks(true); - verifyHillaTask(false); - verifyOldGenerator(false); - } - - @Test - public void should_notUseOldGenerator_whenOpenAPIFileIsNull() - throws ExecutionFailedException, IOException { - builder.withEndpointGeneratedOpenAPIFile(null); - - runEndpointTasks(false); - verifyHillaTask(false); - verifyOldGenerator(false); - } - - private void runEndpointTasks(boolean withHillaTask) - throws ExecutionFailedException, IOException { - FileUtils.write( - new File(propertiesDir, FeatureFlags.PROPERTIES_FILENAME), - String.format("com.vaadin.experimental.hillaEngine=%s\n", - withHillaTask), - StandardCharsets.UTF_8); - - builder.build().execute(); - } - - private static void setPropertyIfPresent(String key, String value) { - if (value != null) { - System.setProperty(key, value); - } - } - - private void verifyHillaTask(boolean expected) - throws ExecutionFailedException { - Mockito.verify(taskGenerateHilla, expected ? times(1) : never()) - .execute(); - } - - private void verifyOldGenerator(boolean expected) - throws ExecutionFailedException { - Mockito.verify(endpointGeneratorTaskFactory, - expected ? times(1) : never()) - .createTaskGenerateEndpoint(any(), any(), any(), any()); - Mockito.verify(endpointGeneratorTaskFactory, - expected ? times(1) : never()) - .createTaskGenerateOpenAPI(any(), any(), any(), any()); - Mockito.verify(taskGenerateOpenAPI, expected ? times(1) : never()) - .execute(); - Mockito.verify(taskGenerateEndpoint, expected ? times(1) : never()) - .execute(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksViteTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksViteTest.java deleted file mode 100644 index 789fcde83bf..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksViteTest.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.stream.Collectors; - -import org.apache.commons.io.FileUtils; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.frontend.NodeTasks.Builder; -import com.vaadin.flow.server.frontend.NodeTestComponents.ExampleExperimentalComponent; -import com.vaadin.flow.server.frontend.NodeTestComponents.FlagView; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.VITE_GENERATED_CONFIG; -import static com.vaadin.flow.server.frontend.FrontendUtils.WEBPACK_CONFIG; -import static com.vaadin.flow.server.frontend.installer.Platform.ALPINE_RELEASE_FILE_PATH; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -public class NodeTasksViteTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private static final String USER_DIR = "user.dir"; - - private static String globalUserDirValue; - private static String globalFrontendDirValue; - private static String globalGeneratedDirValue; - - private String userDir; - - @Before - public void setup() { - userDir = temporaryFolder.getRoot().getAbsolutePath(); - System.setProperty(USER_DIR, userDir); - System.clearProperty(PARAM_FRONTEND_DIR); - System.clearProperty(PARAM_GENERATED_DIR); - } - - @BeforeClass - public static void setupBeforeClass() { - globalUserDirValue = System.getProperty(USER_DIR); - globalFrontendDirValue = System.getProperty(PARAM_FRONTEND_DIR); - globalGeneratedDirValue = System.getProperty(PARAM_GENERATED_DIR); - } - - @AfterClass - public static void tearDownAfterClass() { - setPropertyIfPresent(USER_DIR, globalUserDirValue); - setPropertyIfPresent(PARAM_FRONTEND_DIR, globalFrontendDirValue); - setPropertyIfPresent(PARAM_GENERATED_DIR, globalGeneratedDirValue); - } - - @Test - public void should_ExcludeExperimentalComponent_WhenFeatureDisabled() - throws Exception { - Class[] classes = { FlagView.class, - ExampleExperimentalComponent.class }; - - Lookup mockedLookup = Mockito.mock(Lookup.class); - ClassFinder finder = NodeUpdateTestUtil.getClassFinder(classes); - Mockito.doReturn(finder).when(mockedLookup).lookup(ClassFinder.class); - - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - - assertEquals(1, finder.getAnnotatedClasses(JsModule.class).size()); - assertEquals(1, finder.getAnnotatedClasses(JavaScript.class).size()); - - builder.build().execute(); - File importsFile = Paths - .get(userDir, TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME) - .toFile(); - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertFalse(content.contains("experimental-Connector.js")); - } - - @Test - public void should_IncludeExperimentalComponent_WhenFeatureEnabled() - throws Exception { - Class[] classes = { FlagView.class, - ExampleExperimentalComponent.class }; - - File propertiesDir = temporaryFolder.newFolder(); - FileUtils.write( - new File(propertiesDir, FeatureFlags.PROPERTIES_FILENAME), - "com.vaadin.experimental.exampleFeatureFlag=true\n", - StandardCharsets.UTF_8); - - Lookup mockedLookup = Mockito.mock(Lookup.class); - ClassFinder finder = NodeUpdateTestUtil.getClassFinder(classes); - Mockito.doReturn(finder).when(mockedLookup).lookup(ClassFinder.class); - - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - - builder.build().execute(); - File importsFile = Paths - .get(userDir, TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME) - .toFile(); - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - assertTrue(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertTrue(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertTrue(content.contains("experimental-Connector.js")); - } - - @Test - public void should_UseDefaultFolders() throws Exception { - Lookup mockedLookup = Mockito.mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - - Assert.assertEquals( - new File(userDir, DEFAULT_FRONTEND_DIR).getAbsolutePath(), - ((File) getFieldValue(builder, "frontendDirectory")) - .getAbsolutePath()); - Assert.assertEquals( - Paths.get(userDir, TARGET, DEFAULT_GENERATED_DIR).toFile() - .getAbsolutePath(), - ((File) getFieldValue(builder, "generatedFolder")) - .getAbsolutePath()); - - builder.build().execute(); - Assert.assertTrue( - Paths.get(userDir, TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME) - .toFile().exists()); - } - - @Test - public void should_generateServiceWorkerWhenPwa() throws Exception { - Lookup mockedLookup = mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - - Assert.assertEquals( - new File(userDir, DEFAULT_FRONTEND_DIR).getAbsolutePath(), - ((File) getFieldValue(builder, "frontendDirectory")) - .getAbsolutePath()); - Assert.assertEquals( - new File(new File(userDir, TARGET), DEFAULT_GENERATED_DIR) - .getAbsolutePath(), - ((File) getFieldValue(builder, "generatedFolder")) - .getAbsolutePath()); - - builder.build().execute(); - Assert.assertTrue(new File(userDir, Paths - .get(TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME).toString()) - .exists()); - } - - @Test - public void should_BeAbleToCustomizeFolders() throws Exception { - System.setProperty(PARAM_FRONTEND_DIR, "my_custom_sources_folder"); - System.setProperty(PARAM_GENERATED_DIR, "my/custom/generated/folder"); - - Lookup mockedLookup = mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - - Assert.assertEquals( - new File(userDir, "my_custom_sources_folder").getAbsolutePath(), - ((File) getFieldValue(builder, "frontendDirectory")) - .getAbsolutePath()); - Assert.assertEquals( - new File(userDir, "my/custom/generated/folder") - .getAbsolutePath(), - ((File) getFieldValue(builder, "generatedFolder")) - .getAbsolutePath()); - - builder.build().execute(); - Assert.assertTrue( - new File(userDir, "my/custom/generated/folder/" + IMPORTS_NAME) - .exists()); - } - - private File getJarFrontendResourcesFolder() { - return new File(userDir, "frontend/" + FrontendUtils.GENERATED - + FrontendUtils.JAR_RESOURCES_FOLDER); - } - - @Test - public void should_GenerateTsConfigAndTsDefinitions_When_Vaadin14BootstrapMode() - throws ExecutionFailedException { - Lookup mockedLookup = mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - builder.build().execute(); - - Assert.assertTrue(new File(userDir, "tsconfig.json").exists()); - Assert.assertTrue(new File(userDir, "types.d.ts").exists()); - } - - @Test - public void should_failWithExecutionFailedException_when_customWebpackConfigFileExist() - throws IOException { - try (MockedStatic paths = Mockito.mockStatic(Paths.class)) { - File webpackConfigFile = new File(userDir, WEBPACK_CONFIG); - Path webpackConfigFilePath = webpackConfigFile.toPath(); - paths.when(() -> Paths.get(webpackConfigFile.getPath())) - .thenReturn(webpackConfigFilePath); - Path targetPath = new File(userDir, - TARGET + "/" + DEFAULT_GENERATED_DIR).toPath(); - paths.when(() -> Paths.get(TARGET, DEFAULT_GENERATED_DIR)) - .thenReturn(targetPath); - paths.when(() -> Paths.get(new File(userDir).getPath(), - WEBPACK_CONFIG)).thenReturn(webpackConfigFilePath); - paths.when(() -> Paths.get(ALPINE_RELEASE_FILE_PATH)) - .thenReturn(Path.of(ALPINE_RELEASE_FILE_PATH)); - - String content = "const merge = require('webpack-merge');\n" - + "const flowDefaults = require('./webpack.generated.js');\n" - + "\n" - + "module.exports = merge(flowDefaults, {\"some-config\": 1\n" - + "\n" + "});\n"; - Files.writeString(webpackConfigFilePath, content); - - Lookup mockedLookup = Mockito.mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), - TARGET).enablePackagesUpdate(false) - .enableImportsUpdate(true).runNpmInstall(false) - .withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder( - getJarFrontendResourcesFolder()); - - ExecutionFailedException exception = Assert.assertThrows( - ExecutionFailedException.class, - () -> builder.build().execute()); - Assert.assertTrue(exception.getMessage().contains( - "Webpack related config file 'webpack.config.js' is detected in your")); - } - } - - private static void setPropertyIfPresent(String key, String value) { - if (value != null) { - System.setProperty(key, value); - } - } - - private Object getFieldValue(Object obj, String name) throws Exception { - Field field = obj.getClass().getDeclaredField(name); - field.setAccessible(true); - return field.get(obj); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksWebpackTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksWebpackTest.java deleted file mode 100644 index 01a34beb0a6..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTasksWebpackTest.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.commons.io.FileUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.frontend.NodeTasks.Builder; -import com.vaadin.flow.server.frontend.NodeTestComponents.ExampleExperimentalComponent; -import com.vaadin.flow.server.frontend.NodeTestComponents.FlagView; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_PROJECT_FRONTEND_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.WEBPACK_GENERATED; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - -public class NodeTasksWebpackTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private static final String USER_DIR = "user.dir"; - - private static String globalUserDirValue; - private static String globalFrontendDirValue; - private static String globalGeneratedDirValue; - - private String userDir; - - private File propertiesDir; - - @Before - public void setup() throws Exception { - userDir = temporaryFolder.getRoot().getAbsolutePath(); - System.setProperty(USER_DIR, userDir); - System.clearProperty(PARAM_FRONTEND_DIR); - System.clearProperty(PARAM_GENERATED_DIR); - - propertiesDir = temporaryFolder.newFolder(); - - FileUtils.write( - new File(propertiesDir, FeatureFlags.PROPERTIES_FILENAME), - "com.vaadin.experimental.webpackForFrontendBuild=true\n", - StandardCharsets.UTF_8); - } - - @BeforeClass - public static void setupBeforeClass() { - globalUserDirValue = System.getProperty(USER_DIR); - globalFrontendDirValue = System.getProperty(PARAM_FRONTEND_DIR); - globalGeneratedDirValue = System.getProperty(PARAM_GENERATED_DIR); - } - - @AfterClass - public static void tearDownAfterClass() { - setPropertyIfPresent(USER_DIR, globalUserDirValue); - setPropertyIfPresent(PARAM_FRONTEND_DIR, globalFrontendDirValue); - setPropertyIfPresent(PARAM_GENERATED_DIR, globalGeneratedDirValue); - } - - @Test - public void should_ExcludeExperimentalComponent_WhenFeatureDisabled() - throws Exception { - Class[] classes = { FlagView.class, - ExampleExperimentalComponent.class }; - - Lookup mockedLookup = Mockito.mock(Lookup.class); - ClassFinder finder = NodeUpdateTestUtil.getClassFinder(classes); - Mockito.doReturn(finder).when(mockedLookup).lookup(ClassFinder.class); - - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir); - - assertEquals(1, finder.getAnnotatedClasses(JsModule.class).size()); - assertEquals(1, finder.getAnnotatedClasses(JavaScript.class).size()); - - builder.build().execute(); - File importsFile = Paths - .get(userDir, TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME) - .toFile(); - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertFalse(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertFalse(content.contains("experimental-Connector.js")); - } - - @Test - public void should_IncludeExperimentalComponent_WhenFeatureEnabled() - throws Exception { - Class[] classes = { FlagView.class, - ExampleExperimentalComponent.class }; - - FileUtils.write( - new File(propertiesDir, FeatureFlags.PROPERTIES_FILENAME), - "com.vaadin.experimental.exampleFeatureFlag=true\n" - + "com.vaadin.experimental.webpackForFrontendBuild=true\n", - StandardCharsets.UTF_8); - - Lookup mockedLookup = Mockito.mock(Lookup.class); - ClassFinder finder = NodeUpdateTestUtil.getClassFinder(classes); - Mockito.doReturn(finder).when(mockedLookup).lookup(ClassFinder.class); - - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir); - - builder.build().execute(); - File importsFile = Paths - .get(userDir, TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME) - .toFile(); - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - assertTrue(content - .contains("@vaadin/example-flag/experimental-module-1.js")); - assertTrue(content - .contains("@vaadin/example-flag/experimental-module-2.js")); - assertTrue(content.contains("experimental-Connector.js")); - } - - @Test - public void should_UseDefaultFolders() throws Exception { - Lookup mockedLookup = Mockito.mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir); - - Assert.assertEquals( - new File(userDir, DEFAULT_FRONTEND_DIR).getAbsolutePath(), - ((File) getFieldValue(builder, "frontendDirectory")) - .getAbsolutePath()); - Assert.assertEquals( - Paths.get(userDir, TARGET, DEFAULT_GENERATED_DIR).toFile() - .getAbsolutePath(), - ((File) getFieldValue(builder, "generatedFolder")) - .getAbsolutePath()); - - builder.build().execute(); - Assert.assertTrue( - Paths.get(userDir, TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME) - .toFile().exists()); - } - - @Test - public void should_notExecuteTaskNotifyWebpackConfExistenceWhileUsingVite_whenWebpackIsInUse() - throws Exception { - - Lookup mockedLookup = Mockito.mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir); - - NodeTasks nodeTasks = builder.build(); - - Assert.assertFalse( - "TaskNotifyWebpackConfExistenceWhileUsingVite should not be in the list of node tasks when webpack is used.", - isTaskAddedToBeExecuted(nodeTasks, - TaskNotifyWebpackConfExistenceWhileUsingVite.class)); - } - - @Test - public void should_generateServiceWorkerWhenPwa() throws Exception { - Lookup mockedLookup = mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir); - - Assert.assertEquals( - new File(userDir, DEFAULT_FRONTEND_DIR).getAbsolutePath(), - ((File) getFieldValue(builder, "frontendDirectory")) - .getAbsolutePath()); - Assert.assertEquals( - new File(new File(userDir, TARGET), DEFAULT_GENERATED_DIR) - .getAbsolutePath(), - ((File) getFieldValue(builder, "generatedFolder")) - .getAbsolutePath()); - - builder.build().execute(); - Assert.assertTrue(new File(userDir, Paths - .get(TARGET, DEFAULT_GENERATED_DIR, IMPORTS_NAME).toString()) - .exists()); - } - - @Test - public void should_BeAbleToCustomizeFolders() throws Exception { - System.setProperty(PARAM_FRONTEND_DIR, "my_custom_sources_folder"); - System.setProperty(PARAM_GENERATED_DIR, "my/custom/generated/folder"); - - Lookup mockedLookup = mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false).enableImportsUpdate(true) - .runNpmInstall(false).withEmbeddableWebComponents(false) - .setJavaResourceFolder(propertiesDir); - - Assert.assertEquals( - new File(userDir, "my_custom_sources_folder").getAbsolutePath(), - ((File) getFieldValue(builder, "frontendDirectory")) - .getAbsolutePath()); - Assert.assertEquals( - new File(userDir, "my/custom/generated/folder") - .getAbsolutePath(), - ((File) getFieldValue(builder, "generatedFolder")) - .getAbsolutePath()); - - builder.build().execute(); - Assert.assertTrue( - new File(userDir, "my/custom/generated/folder/" + IMPORTS_NAME) - .exists()); - } - - @Test - public void should_SetIsClientBootstrapMode_When_EnableClientSideBootstrapMode() - throws ExecutionFailedException, IOException { - Lookup mockedLookup = mock(Lookup.class); - Mockito.doReturn( - new DefaultClassFinder(this.getClass().getClassLoader())) - .when(mockedLookup).lookup(ClassFinder.class); - Builder builder = new Builder(mockedLookup, new File(userDir), TARGET) - .enablePackagesUpdate(false) - .withWebpack(new File(userDir, TARGET + "webapp"), - new File(userDir, TARGET + "classes")) - .enableImportsUpdate(true).runNpmInstall(false) - .withEmbeddableWebComponents(false) - .withJarFrontendResourcesFolder(new File( - new File(userDir, - DEFAULT_PROJECT_FRONTEND_GENERATED_DIR), - FrontendUtils.JAR_RESOURCES_FOLDER)) - .withFrontendGeneratedFolder(new File(userDir, - DEFAULT_PROJECT_FRONTEND_GENERATED_DIR)) - .setJavaResourceFolder(propertiesDir); - builder.build().execute(); - String webpackGeneratedContent = Files - .lines(new File(userDir, WEBPACK_GENERATED).toPath()) - .collect(Collectors.joining("\n")); - Assert.assertTrue( - "useClientSideIndexFileForBootstrapping should be true", - webpackGeneratedContent.contains( - "const useClientSideIndexFileForBootstrapping = true;")); - } - - private static void setPropertyIfPresent(String key, String value) { - if (value != null) { - System.setProperty(key, value); - } - } - - private Object getFieldValue(Object obj, String name) throws Exception { - Field field = obj.getClass().getDeclaredField(name); - field.setAccessible(true); - return field.get(obj); - } - - private boolean isTaskAddedToBeExecuted(NodeTasks nodeTasks, - Class taskClass) throws Exception { - List commands = (List) getFieldValue( - nodeTasks, "commands"); - return commands.stream().anyMatch(fallibleCommand -> fallibleCommand - .getClass().equals(taskClass)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTestComponents.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTestComponents.java deleted file mode 100644 index 57143170677..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeTestComponents.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.LoggerFactory; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.component.dependency.NpmPackage; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.Theme; - -/** - * A container class for all components used in tests. - */ -public class NodeTestComponents extends NodeUpdateTestUtil { - - public static final String BUTTON_COMPONENT_FQN = ButtonComponent.class - .getName(); - public static final String ICON_COMPONENT_FQN = IconComponent.class - .getName(); - - @NpmPackage(value = "@vaadin/vaadin-button", version = "1.1.1") - class ButtonComponent extends Component { - } - - @JsModule("@polymer/iron-icon/iron-icon.js") - class IconComponent extends Component { - } - - @JsModule("@vaadin/vaadin-date-picker/src/vaadin-date-picker.js") - @JsModule("@vaadin/vaadin-date-picker/src/vaadin-month-calendar.js") - @JavaScript("ExampleConnector.js") - public static class VaadinBowerComponent extends Component { - } - - @NpmPackage(value = "@vaadin/vaadin-element-mixin", version = "1.1.2") - @JsModule("@vaadin/vaadin-element-mixin/vaadin-element-mixin.js") - public static class VaadinElementMixin extends Component { - } - - @JsModule("./foo-dir/vaadin-npm-component.js") - public static class VaadinNpmComponent extends Component { - } - - @JsModule("vaadin-mixed-component/src/vaadin-mixed-component.js") - public static class VaadinMixedComponent extends Component { - } - - @JsModule("./local-template.js") - @JsModule("3rdparty/component.js") - public static class LocalTemplate extends Component { - } - - @JsModule("./local-p3-template.js") - @NpmPackage(value = "@foo/var-component", version = "1.1.0") - public static class LocalP3Template extends Component { - } - - @JsModule("unresolved/component") - public static class UnresolvedComponent extends Component { - } - - @JsModule("@vaadin/example-flag/experimental-module-1.js") - @JsModule("@vaadin/example-flag/experimental-module-2.js") - @JavaScript("experimental-Connector.js") - @Tag("example-experimental-component") - public static class ExampleExperimentalComponent extends Component { - } - - @Route("flag-view") - public static class FlagView extends Component { - ExampleExperimentalComponent component; - } - - @JsModule("./foo.js") - @CssImport("@vaadin/vaadin-mixed-component/bar.css") - @CssImport("./foo.css") - @CssImport(value = "./foo.css") - @CssImport(value = "./foo.css", include = "bar") - @CssImport(value = "./foo.css", id = "baz") - @CssImport(value = "./foo.css", id = "baz", include = "bar") - @CssImport(value = "./foo.css", themeFor = "foo-bar") - @CssImport(value = "./foo.css", themeFor = "foo-bar", include = "bar") - public static class FlatImport extends Component { - } - - @JsModule("@vaadin/vaadin-mixed-component/src/vaadin-mixed-component.js") - @JsModule("@vaadin/vaadin-mixed-component/src/vaadin-something-else.js") - @JsModule("@vaadin/vaadin-mixed-component/src/vaadin-something-else") - @JsModule("@vaadin/vaadin-mixed-component/src/vaadin-custom-themed-component.js") - public static class TranslatedImports extends Component { - - } - - @JsModule("./common-js-file.js") - @Theme(themeClass = LumoTest.class, variant = LumoTest.DARK) - @Route - public static class MainLayout implements RouterLayout { - @Override - public Element getElement() { - return null; - } - } - - @Route(value = "", layout = MainLayout.class) - public static class MainView extends Component { - ButtonComponent buttonComponent; - IconComponent iconComponent; - VaadinBowerComponent vaadinBowerComponent; - VaadinElementMixin vaadinElementMixin; - VaadinNpmComponent vaadinNpmComponent; - VaadinMixedComponent vaadinMixedComponent; - LocalTemplate localP2Template; - LocalP3Template localP3Template; - UnresolvedComponent frontendP3Template; - FlatImport flatImport; - TranslatedImports translatedImports; - JavaScriptOrder order; - } - - /** - * Lumo component theme class implementation. - */ - @JsModule("@vaadin/vaadin-lumo-styles/color.js") - @JsModule("@vaadin/vaadin-lumo-styles/typography.js") - @JsModule("@vaadin/vaadin-lumo-styles/sizing.js") - @JsModule("@vaadin/vaadin-lumo-styles/spacing.js") - @JsModule("@vaadin/vaadin-lumo-styles/style.js") - @JsModule("@vaadin/vaadin-lumo-styles/icons.js") - public static class LumoTest implements AbstractTheme { - - public static final String LIGHT = "light"; - public static final String DARK = "dark"; - - public LumoTest() { - } - - @Override - public String getBaseUrl() { - return "src/"; - } - - @Override - public String getThemeUrl() { - return "theme/lumo/"; - } - - @Override - public List getHeaderInlineContents() { - return Collections.singletonList("\n" - + " \n" - + ""); - } - - @Override - public Map getHtmlAttributes(String variant) { - if (variant.isEmpty()) { - return Collections.emptyMap(); - } - Map attributes = new HashMap<>(1); - switch (variant) { - case LIGHT: - attributes.put("theme", LIGHT); - break; - case DARK: - attributes.put("theme", DARK); - break; - default: - LoggerFactory.getLogger(LumoTest.class.getName()).warn( - "Lumo theme variant not recognized: '{}'. Using no variant.", - variant); - } - return attributes; - } - } - - @NpmPackage(value = "@webcomponents/webcomponentsjs", version = "2.2.10") - public static class ExtraImport { - } - - @JavaScript("javascript/a.js") - @JavaScript("javascript/b.js") - @JavaScript("javascript/c.js") - @JsModule("jsmodule/g.js") - public static class JavaScriptOrder extends Component { - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java deleted file mode 100644 index 8eff9da170e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsTest.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.net.URLClassLoader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Stream; - -import org.apache.commons.io.FileUtils; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; -import org.slf4j.Logger; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner.FrontendDependenciesScannerFactory; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_D_TS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES; -import static org.junit.Assert.assertTrue; - -public class NodeUpdateImportsTest extends NodeUpdateTestUtil { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private File importsFile; - private File importsDefinitionFile; - private File fallBackImportsFile; - private File generatedPath; - private File frontendDirectory; - private File nodeModulesPath; - private TaskUpdateImports updater; - private File tmpRoot; - private File tokenFile; - - private Logger logger = Mockito.mock(Logger.class); - - @Before - public void setup() throws Exception { - tmpRoot = temporaryFolder.getRoot(); - - frontendDirectory = new File(tmpRoot, DEFAULT_FRONTEND_DIR); - nodeModulesPath = new File(tmpRoot, NODE_MODULES); - generatedPath = new File(tmpRoot, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - importsFile = new File(generatedPath, IMPORTS_NAME); - importsDefinitionFile = new File(generatedPath, IMPORTS_D_TS_NAME); - fallBackImportsFile = new File(generatedPath, - FrontendUtils.FALLBACK_IMPORTS_NAME); - File webpackDir = temporaryFolder.newFolder(); - tokenFile = new File(webpackDir, "config/flow-build-info.json"); - FileUtils.forceMkdirParent(tokenFile); - tokenFile.createNewFile(); - - assertTrue(nodeModulesPath.mkdirs()); - createExpectedImports(frontendDirectory, nodeModulesPath); - assertTrue( - new File( - new File( - new File(frontendDirectory, - FrontendUtils.GENERATED), - FrontendUtils.JAR_RESOURCES_FOLDER), - "ExampleConnector.js").exists()); - - new File(frontendDirectory, "extra-javascript.js").createNewFile(); - new File(frontendDirectory, "extra-css.css").createNewFile(); - new File(frontendDirectory, "a-css.css").createNewFile(); - new File(frontendDirectory, "b-css.css").createNewFile(); - } - - @Test - public void extraComponentsInCP_componentsAreNotDiscoveredByMainScannerWrittenByFallback_fallbackIsGenerated() - throws IOException { - Stream> classes = Stream.concat( - Stream.of(NodeTestComponents.class.getDeclaredClasses()), - Stream.of(ExtraNodeTestComponents.class.getDeclaredClasses())); - ClassFinder classFinder = new DefaultClassFinder( - new URLClassLoader(getClassPath()), - classes.toArray(Class[]::new)); - - JsonObject fallBackData = Json.createObject(); - - updater = new TaskUpdateImports(classFinder, - new FrontendDependenciesScannerFactory().createScanner(false, - classFinder, true), - finder -> new FrontendDependenciesScannerFactory() - .createScanner(true, finder, true), - tmpRoot, generatedPath, frontendDirectory, tokenFile, - fallBackData, false, TARGET, true, false, - Mockito.mock(FeatureFlags.class)) { - @Override - Logger log() { - return logger; - } - }; - - updater.execute(); - - assertTrue(importsFile.exists()); - - String mainContent = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - // ============== check main generated imports file ============ - // Contains theme lines - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "export const addCssBlock = function(block, before = false) {")); - - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "addCssBlock('', true);")); - - // Contains CSS import lines - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css?inline';")); - MatcherAssert.assertThat(mainContent, CoreMatchers - .containsString("addCssBlock(``);")); - - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "import $cssFromFile_5 from 'Frontend/foo.css?inline';")); - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "registerStyles('foo-bar', $css_5, {moduleId: 'flow_css_mod_5'});")); - - // Contains theme imports - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "import '@vaadin/vaadin-lumo-styles/color.js';")); - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "import '@vaadin/vaadin-lumo-styles/typography.js';")); - - // Contains JS module imports - MatcherAssert.assertThat(mainContent, CoreMatchers - .containsString("import '@polymer/iron-icon/iron-icon.js';")); - MatcherAssert.assertThat(mainContent, - CoreMatchers.containsString("import '3rdparty/component.js';")); - - // Contains Javascript imports - MatcherAssert.assertThat(mainContent, - CoreMatchers.containsString("import 'javascript/a.js';")); - MatcherAssert.assertThat(mainContent, - CoreMatchers.containsString("import 'javascript/b.js';")); - - // fallback chunk load function is generated - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "fallbacks[thisScript.getAttribute('data-app-id')].loadFallback = function loadFallback() {")); - - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "return import('./generated-flow-imports-fallback.js');")); - - assertTrue(fallBackImportsFile.exists()); - - // ============== check fallback generated imports file ============ - - String fallBackContent = FileUtils.readFileToString(fallBackImportsFile, - Charset.defaultCharset()); - - // Does not Contains theme lines - MatcherAssert.assertThat(fallBackContent, CoreMatchers.not(CoreMatchers - .containsString("const div = document.createElement('div');"))); - - // Does not contains theme imports - MatcherAssert.assertThat(fallBackContent, - CoreMatchers.not(CoreMatchers.containsString( - "import '@vaadin/vaadin-lumo-styles/color.js';"))); - - // Does not contains CSS import lines - MatcherAssert.assertThat(fallBackContent, - CoreMatchers.not(CoreMatchers.containsString( - "import $cssFromFile_0 from '@vaadin/vaadin-mixed-component/bar.css?inline';"))); - - // Contain lines to import exported modules from main file - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "export const addCssBlock = function(block, before = false) {")); - - // Contains CSS import lines from CP not discovered by byte scanner - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "import $cssFromFile_0 from 'Frontend/b-css.css?inline';")); - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "registerStyles('extra-foo', $css_2, {include: 'extra-bar', moduleId: 'fallback_flow_css_mod_2'});")); - - // Does not contains JS module imports - MatcherAssert.assertThat(fallBackContent, CoreMatchers.not(CoreMatchers - .containsString("import '@polymer/iron-icon/iron-icon.js';"))); - - // Contains JS module imports - MatcherAssert.assertThat(fallBackContent, - CoreMatchers.containsString("import '@polymer/a.js';")); - - // Does not contain Javascript imports - MatcherAssert.assertThat(fallBackContent, CoreMatchers - .not(CoreMatchers.containsString("import 'javascript/a.js';"))); - - // Contains Javascript imports - MatcherAssert.assertThat(fallBackContent, CoreMatchers - .containsString("import 'Frontend/extra-javascript.js';")); - - // ============== check token file with fallback chunk data ============ - - String tokenContent = FileUtils.readFileToString(tokenFile, - Charset.defaultCharset()); - JsonObject object = Json.parse(tokenContent); - - assertTokenFileWithFallBack(object); - assertTokenFileWithFallBack(fallBackData); - - // ============== check definition file ============ - - assertTrue(importsDefinitionFile.exists()); - - String definitionContent = FileUtils.readFileToString( - importsDefinitionFile, Charset.defaultCharset()); - - MatcherAssert.assertThat(definitionContent, CoreMatchers.containsString( - "export declare const addCssBlock: (block: string, before?: boolean) => void;")); - } - - @Test - public void emptyByteCodeScannerData_themeIsDiscovered_fallbackIsGenerated() - throws IOException { - ClassFinder classFinder = new DefaultClassFinder( - new URLClassLoader(getClassPath()), - EmptyByteScannerDataTestComponents.class.getDeclaredClasses()); - - updater = new TaskUpdateImports(classFinder, - new FrontendDependenciesScannerFactory().createScanner(false, - classFinder, true), - finder -> new FrontendDependenciesScannerFactory() - .createScanner(true, finder, true), - tmpRoot, generatedPath, frontendDirectory, tokenFile, null, - false, TARGET, true, false, Mockito.mock(FeatureFlags.class)) { - @Override - Logger log() { - return logger; - } - }; - - updater.execute(); - - assertTrue(importsFile.exists()); - - String mainContent = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - // ============== check main generated imports file ============ - - // Contains theme lines - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "export const addCssBlock = function(block, before = false) {")); - - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "addCssBlock('foo', true);")); - - // fallback chunk load function is generated - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "fallbacks[thisScript.getAttribute('data-app-id')].loadFallback = function loadFallback() {")); - - MatcherAssert.assertThat(mainContent, CoreMatchers.containsString( - "return import('./generated-flow-imports-fallback.js');")); - - // ============== check fallback generated imports file ============ - - String fallBackContent = FileUtils.readFileToString(fallBackImportsFile, - Charset.defaultCharset()); - - // Does not Contains theme lines - MatcherAssert.assertThat(fallBackContent, CoreMatchers.not(CoreMatchers - .containsString("const div = document.createElement('div');"))); - - // Contains CSS import lines from CP not discovered by byte - // scanner - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "import $cssFromFile_0 from 'Frontend/foo.css?inline';")); - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "registerStyles('', $css_0, {include: 'bar', moduleId: 'baz'});")); - - // Contains JS module imports - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "import '@vaadin/vaadin-lumo-styles/icons.js';")); - MatcherAssert.assertThat(fallBackContent, CoreMatchers - .containsString("import 'Frontend/common-js-file.js';")); - - // Contains Javascript imports - MatcherAssert.assertThat(fallBackContent, CoreMatchers.containsString( - "import 'Frontend/generated/jar-resources/ExampleConnector.js';")); - } - - @Test - public void noFallBackScanner_fallbackIsNotGenerated() throws IOException { - Stream> classes = Stream.concat( - Stream.of(NodeTestComponents.class.getDeclaredClasses()), - Stream.of(ExtraNodeTestComponents.class.getDeclaredClasses())); - ClassFinder classFinder = new DefaultClassFinder( - new URLClassLoader(getClassPath()), - classes.toArray(Class[]::new)); - - updater = new TaskUpdateImports(classFinder, - new FrontendDependenciesScannerFactory().createScanner(false, - classFinder, true), - finder -> null, tmpRoot, generatedPath, frontendDirectory, - tokenFile, null, false, TARGET, true, false, - Mockito.mock(FeatureFlags.class)) { - @Override - Logger log() { - return logger; - } - }; - - updater.execute(); - - assertTrue(importsFile.exists()); - - String mainContent = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - // fallback chunk load function is not generated - MatcherAssert.assertThat(mainContent, - CoreMatchers.not(CoreMatchers.containsString( - "window.Vaadin.Flow.loadFallback = function loadFallback(){"))); - - Assert.assertFalse(fallBackImportsFile.exists()); - - } - - @Test - public void noFallBackScanner_fallbackIsNotImportedEvenIfTheFileExists() - throws Exception { - Stream> classes = Stream.concat( - Stream.of(NodeTestComponents.class.getDeclaredClasses()), - Stream.of(ExtraNodeTestComponents.class.getDeclaredClasses())); - ClassFinder classFinder = new DefaultClassFinder( - new URLClassLoader(getClassPath()), - classes.toArray(Class[]::new)); - - // create fallback imports file: - // it is present after generated but the user is now running - // everything without fallback. The file should not be included into - // the imports - fallBackImportsFile.mkdirs(); - fallBackImportsFile.createNewFile(); - Assert.assertTrue(fallBackImportsFile.exists()); - - updater = new TaskUpdateImports(classFinder, - new FrontendDependenciesScannerFactory().createScanner(false, - classFinder, true), - finder -> null, tmpRoot, generatedPath, frontendDirectory, - tokenFile, null, false, TARGET, true, false, - Mockito.mock(FeatureFlags.class)) { - @Override - Logger log() { - return logger; - } - }; - - updater.execute(); - - assertTrue(importsFile.exists()); - - String mainContent = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - - // fallback file is not imported in generated-flow-imports - MatcherAssert.assertThat(mainContent, CoreMatchers.not(CoreMatchers - .containsString(FrontendUtils.FALLBACK_IMPORTS_NAME))); - } - - @Test - public void tokenFileIsStable() throws Exception { - Stream> classes = Stream.concat( - Stream.of(ExtraNodeTestComponents.class.getDeclaredClasses()), - Stream.of(NodeTestComponents.class.getDeclaredClasses())); - ClassFinder classFinder = new DefaultClassFinder( - new URLClassLoader(getClassPath()), - classes.toArray(Class[]::new)); - - JsonObject fallBackData = Json.createObject(); - - updater = new TaskUpdateImports(classFinder, - new FrontendDependenciesScannerFactory().createScanner(false, - classFinder, true), - finder -> new FrontendDependenciesScannerFactory() - .createScanner(true, finder, true), - tmpRoot, generatedPath, frontendDirectory, tokenFile, - fallBackData, false, TARGET, true, false, - Mockito.mock(FeatureFlags.class)) { - @Override - Logger log() { - return logger; - } - }; - - updater.execute(); - - JsonObject fallback = fallBackData.getObject("chunks") - .getObject("fallback"); - JsonArray jsModules = fallback.getArray("jsModules"); - JsonArray cssImports = fallback.getArray("cssImports"); - - String expectedJsModules = "[\"@polymer/e.js\",\"@polymer/D.js\",\"@polymer/c.js\",\"@polymer/b.js\",\"@polymer/a.js\",\"./extra-javascript.js\"]"; - String expectedCssImports = "[{\"value\":\"./b-css.css\"},{\"include\":\"a-a\",\"value\":\"./a-css.css\"},{\"include\":\"extra-bar\",\"themeFor\":\"extra-foo\",\"value\":\"./extra-css.css\"}]"; - - Assert.assertEquals(expectedJsModules, jsModules.toJson()); - Assert.assertEquals(expectedCssImports, cssImports.toJson()); - - String actual = FileUtils.readFileToString(tokenFile, - StandardCharsets.UTF_8); - String expected = "{\n" + // - " \"chunks\": {\n" + // - " \"fallback\": {\n" + // - " \"jsModules\": [\n" + // - " \"@polymer/e.js\",\n" + // - " \"@polymer/D.js\",\n" + // - " \"@polymer/c.js\",\n" + // - " \"@polymer/b.js\",\n" + // - " \"@polymer/a.js\",\n" + // - " \"./extra-javascript.js\"\n" + // - " ],\n" + // - " \"cssImports\": [\n" + // - " {\n" + // - " \"value\": \"./b-css.css\"\n" + // - " },\n" + // - " {\n" + // - " \"include\": \"a-a\",\n" + // - " \"value\": \"./a-css.css\"\n" + // - " },\n" + // - " {\n" + // - " \"include\": \"extra-bar\",\n" + // - " \"themeFor\": \"extra-foo\",\n" + // - " \"value\": \"./extra-css.css\"\n" + // - " }\n" + // - " ]\n" + // - " }\n" + // - " }\n" + // - "}"; - Assert.assertEquals(expected, actual); - - } - - private void assertTokenFileWithFallBack(JsonObject object) - throws IOException { - JsonObject fallback = object.getObject("chunks").getObject("fallback"); - - JsonArray modules = fallback.getArray("jsModules"); - Set modulesSet = new HashSet<>(); - for (int i = 0; i < modules.length(); i++) { - modulesSet.add(modules.getString(i)); - } - Assert.assertTrue(modulesSet.contains("@polymer/a.js")); - Assert.assertTrue(modulesSet.contains("./extra-javascript.js")); - - JsonArray css = fallback.getArray("cssImports"); - Assert.assertEquals(3, css.length()); - JsonObject cssImport = css.get(2); - Assert.assertEquals("extra-bar", cssImport.getString("include")); - Assert.assertEquals("extra-foo", cssImport.getString("themeFor")); - Assert.assertEquals("./extra-css.css", cssImport.getString("value")); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsWithByteCodeScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsWithByteCodeScannerTest.java deleted file mode 100644 index 6146213ac97..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsWithByteCodeScannerTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -public class NodeUpdateImportsWithByteCodeScannerTest - extends AbstractNodeUpdateImportsTest { - - @Override - protected FrontendDependenciesScanner getScanner(ClassFinder finder) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(false, finder, true); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsWithFullCPScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsWithFullCPScannerTest.java deleted file mode 100644 index 6a23ad86c0d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateImportsWithFullCPScannerTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -public class NodeUpdateImportsWithFullCPScannerTest - extends AbstractNodeUpdateImportsTest { - - @Override - protected FrontendDependenciesScanner getScanner(ClassFinder finder) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(true, finder, true); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesNpmVersionLockingTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesNpmVersionLockingTest.java deleted file mode 100644 index 41fb8be8f58..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesNpmVersionLockingTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; - -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; -import com.vaadin.flow.testcategory.SlowTests; -import com.vaadin.flow.testutil.FrontendStubs; - -import elemental.json.Json; -import elemental.json.JsonObject; -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; - -@Category(SlowTests.class) -public class NodeUpdatePackagesNpmVersionLockingTest - extends NodeUpdateTestUtil { - - private static final String TEST_DEPENDENCY = "@vaadin/vaadin-overlay"; - private static final String DEPENDENCIES = "dependencies"; - private static final String OVERRIDES = "overrides"; - private static final String PLATFORM_PINNED_DEPENDENCY_VERSION = "3.2.17"; - private static final String USER_PINNED_DEPENDENCY_VERSION = "1.0"; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File baseDir; - private File generatedDir; - - private ClassFinder classFinder; - - private FeatureFlags featureFlags; - - @Before - public void setup() throws Exception { - baseDir = temporaryFolder.getRoot(); - - featureFlags = Mockito.mock(FeatureFlags.class); - - generatedDir = new File(baseDir, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - - FrontendStubs.createStubNode(true, true, baseDir.getAbsolutePath()); - - classFinder = Mockito.spy(getClassFinder()); - File versions = temporaryFolder.newFile(); - FileUtils.write(versions, - String.format( - "{" + "\"vaadin-overlay\": {" - + "\"npmName\": \"@vaadin/vaadin-overlay\"," - + "\"jsVersion\": \"%s\"" + "}" + "}", - PLATFORM_PINNED_DEPENDENCY_VERSION), - StandardCharsets.UTF_8); - // @formatter:on - - Mockito.when( - classFinder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versions.toURI().toURL()); - } - - @Test - public void shoudlLockPinnedVersion_whenExistsInDependencies() - throws IOException { - TaskUpdatePackages packageUpdater = createPackageUpdater(); - JsonObject packageJson = packageUpdater.getPackageJson(); - packageJson.getObject(DEPENDENCIES).put(TEST_DEPENDENCY, - PLATFORM_PINNED_DEPENDENCY_VERSION); - Assert.assertNull(packageJson.getObject(OVERRIDES)); - - String versionsPath = packageUpdater.generateVersionsJson(packageJson); - packageUpdater.lockVersionForNpm(packageJson, versionsPath); - - Assert.assertEquals("$" + TEST_DEPENDENCY, - packageJson.getObject(OVERRIDES).getString(TEST_DEPENDENCY)); - } - - @Test - public void shoudlNotLockPinnedVersion_whenNotExistsInDependencies() - throws IOException { - TaskUpdatePackages packageUpdater = createPackageUpdater(); - JsonObject packageJson = packageUpdater.getPackageJson(); - - Assert.assertNull(packageJson.getObject(OVERRIDES)); - Assert.assertNull( - packageJson.getObject(DEPENDENCIES).get(TEST_DEPENDENCY)); - - String versionsPath = packageUpdater.generateVersionsJson(packageJson); - packageUpdater.lockVersionForNpm(packageJson, versionsPath); - - Assert.assertNull( - packageJson.getObject(OVERRIDES).get(TEST_DEPENDENCY)); - } - - @Test - public void shouldNotUpdatesOverrides_whenHasUserModification() - throws IOException { - TaskUpdatePackages packageUpdater = createPackageUpdater(); - JsonObject packageJson = packageUpdater.getPackageJson(); - JsonObject overridesSection = Json.createObject(); - packageJson.put(OVERRIDES, overridesSection); - - packageJson.getObject(DEPENDENCIES).put(TEST_DEPENDENCY, - USER_PINNED_DEPENDENCY_VERSION); - overridesSection.put(TEST_DEPENDENCY, USER_PINNED_DEPENDENCY_VERSION); - - String versionsPath = packageUpdater.generateVersionsJson(packageJson); - packageUpdater.lockVersionForNpm(packageJson, versionsPath); - - Assert.assertEquals(USER_PINNED_DEPENDENCY_VERSION, - packageJson.getObject(OVERRIDES).getString(TEST_DEPENDENCY)); - } - - @Test - public void shouldDoNothingForNpmLocking_whenInPnpmMode() - throws IOException { - TaskUpdatePackages packageUpdater = createPackageUpdater(true); - JsonObject packageJson = packageUpdater.getPackageJson(); - packageJson.getObject(DEPENDENCIES).put(TEST_DEPENDENCY, - PLATFORM_PINNED_DEPENDENCY_VERSION); - Assert.assertNull(packageJson.getObject(OVERRIDES)); - - String versionsPath = packageUpdater.generateVersionsJson(packageJson); - packageUpdater.lockVersionForNpm(packageJson, versionsPath); - - Assert.assertNull(packageJson.getObject(OVERRIDES)); - } - - @Test - public void shouldRemoveUnusedLocking() throws IOException { - // Test when there is no vaadin-version-core.json available - Mockito.when( - classFinder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(null); - - TaskUpdatePackages packageUpdater = createPackageUpdater(true); - JsonObject packageJson = packageUpdater.getPackageJson(); - packageJson.getObject(DEPENDENCIES).put(TEST_DEPENDENCY, - PLATFORM_PINNED_DEPENDENCY_VERSION); - Assert.assertNull(packageJson.getObject(OVERRIDES)); - - String versionsPath = packageUpdater.generateVersionsJson(packageJson); - File output = new File(packageUpdater.npmFolder, versionsPath); - Assert.assertTrue( - FileUtils.readFileToString(output, StandardCharsets.UTF_8) - .contains(TEST_DEPENDENCY)); - - packageJson.getObject(DEPENDENCIES).remove(TEST_DEPENDENCY); - - packageUpdater.generateVersionsJson(packageJson); - Assert.assertFalse( - FileUtils.readFileToString(output, StandardCharsets.UTF_8) - .contains(TEST_DEPENDENCY)); - - } - - private TaskUpdatePackages createPackageUpdater(boolean enablePnpm) { - FrontendDependenciesScanner scanner = Mockito - .mock(FrontendDependenciesScanner.class); - return new TaskUpdatePackages(classFinder, scanner, baseDir, - generatedDir, null, false, enablePnpm, TARGET, featureFlags); - } - - private TaskUpdatePackages createPackageUpdater() { - return createPackageUpdater(false); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesWithByteCodeScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesWithByteCodeScannerTest.java deleted file mode 100644 index 6ccd80a93b2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesWithByteCodeScannerTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -public class NodeUpdatePackagesWithByteCodeScannerTest - extends AbstractNodeUpdatePackagesTest { - - @Override - protected FrontendDependenciesScanner getScanner(ClassFinder finder) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(false, finder, true); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesWithFullCPCodeScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesWithFullCPCodeScannerTest.java deleted file mode 100644 index 5e35cd65cb5..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdatePackagesWithFullCPCodeScannerTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -public class NodeUpdatePackagesWithFullCPCodeScannerTest - extends AbstractNodeUpdatePackagesTest { - - @Override - protected FrontendDependenciesScanner getScanner(ClassFinder finder) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(true, finder, true); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateTestUtil.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateTestUtil.java deleted file mode 100644 index d021bbfdd32..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdateTestUtil.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Assert; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; - -import static com.vaadin.flow.server.frontend.FrontendUtils.FRONTEND_FOLDER_ALIAS; -import static org.junit.Assert.assertNotNull; - -public class NodeUpdateTestUtil { - - static ClassFinder getClassFinder() throws MalformedURLException { - return new DefaultClassFinder(new URLClassLoader(getClassPath()), - NodeTestComponents.class.getDeclaredClasses()); - } - - static ClassFinder getClassFinder(Class... classes) - throws MalformedURLException { - return new DefaultClassFinder(new URLClassLoader(getClassPath()), - classes); - } - - static URL[] getClassPath() throws MalformedURLException { - // Add folder with test classes - List classPaths = new ArrayList<>(); - - classPaths.add(new File("target/test-classes").toURI().toURL()); - - // Add this test jar which has some frontend resources used in tests - URL jar = getTestResource("jar-with-frontend-resources.jar"); - classPaths.add(jar); - - // Add other paths already present in the system classpath - ClassLoader classLoader = ClassLoader.getSystemClassLoader(); - URL[] urls = URLClassLoader.newInstance(new URL[] {}, classLoader) - .getURLs(); - for (URL url : urls) { - classPaths.add(url); - } - return classPaths.toArray(new URL[0]); - } - - static URL getTestResource(String resourceName) { - URL resourceUrl = NodeUpdateTestUtil.class.getClassLoader() - .getResource(resourceName); - assertNotNull(String.format( - "Expect the test resource to be present in test resource folder with name = '%s'", - resourceName), resourceUrl); - return resourceUrl; - } - - void sleep(int ms) throws InterruptedException { - Thread.sleep(ms); // NOSONAR - } - - List getExpectedImports() { - return Arrays.asList("@polymer/iron-icon/iron-icon.js", - "@vaadin/vaadin-lumo-styles/spacing.js", - "@vaadin/vaadin-lumo-styles/icons.js", - "@vaadin/vaadin-lumo-styles/style.js", - "@vaadin/vaadin-lumo-styles/typography.js", - "@vaadin/vaadin-lumo-styles/color.js", - "@vaadin/vaadin-lumo-styles/sizing.js", - "@vaadin/vaadin-date-picker/theme/lumo/vaadin-date-picker.js", - "@vaadin/vaadin-date-picker/src/vaadin-month-calendar.js", - "@vaadin/vaadin-element-mixin/vaadin-element-mixin.js", - "@vaadin/vaadin-mixed-component/theme/lumo/vaadin-mixed-component.js", - "@vaadin/vaadin-mixed-component/theme/lumo/vaadin-something-else.js", - "./theme/lumo/vaadin-custom-themed-component.js", - "./generated/jar-resources/ExampleConnector.js", - "3rdparty/component.js", "./local-p3-template.js", "./foo.js", - "./vaadin-mixed-component/theme/lumo/vaadin-mixed-component.js", - "./local-template.js", "./foo-dir/vaadin-npm-component.js", - "./foo.css", "@vaadin/vaadin-mixed-component/bar.css", - "./common-js-file.js", - "@vaadin/example-flag/experimental-module-1.js", - "@vaadin/example-flag/experimental-module-2.js", - "experimental-Connector.js"); - } - - void createExpectedImports(File directoryWithImportsJs, - File nodeModulesPath) throws IOException { - for (String expectedImport : getExpectedImports()) { - File newFile = resolveImportFile(directoryWithImportsJs, - nodeModulesPath, expectedImport); - newFile.getParentFile().mkdirs(); - Assert.assertTrue(newFile.createNewFile()); - } - } - - void deleteExpectedImports(File directoryWithImportsJs, - File nodeModulesPath) { - for (String expectedImport : getExpectedImports()) { - Assert.assertTrue(resolveImportFile(directoryWithImportsJs, - nodeModulesPath, expectedImport).delete()); - } - } - - File resolveImportFile(File directoryWithImportsJs, File nodeModulesPath, - String jsImport) { - File root = jsImport.startsWith("./") ? directoryWithImportsJs - : nodeModulesPath; - return new File(root, jsImport); - } - - String addWebpackPrefix(String s) { - if (s.startsWith("./")) { - return FRONTEND_FOLDER_ALIAS + s.substring(2); - } - return s; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java deleted file mode 100644 index 9390afa6ed6..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/NodeUpdaterTest.java +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.commons.io.FileUtils; -import org.hamcrest.MatcherAssert; -import org.hamcrest.core.StringContains; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.experimental.Feature; -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; - -import elemental.json.Json; -import elemental.json.JsonException; -import elemental.json.JsonObject; -import static com.vaadin.flow.server.Constants.PACKAGE_JSON; -import static com.vaadin.flow.server.Constants.TARGET; -import static java.nio.charset.StandardCharsets.UTF_8; - -public class NodeUpdaterTest { - - private static final String POLYMER_VERSION = "3.5.1"; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private NodeUpdater nodeUpdater; - - private File npmFolder; - - private File generatedPath; - - private ClassFinder finder; - - private URL url; - - private boolean useWebpack = false; - - @Before - public void setUp() throws IOException { - url = new URL("file://bar"); - npmFolder = temporaryFolder.newFolder(); - generatedPath = temporaryFolder.newFolder(); - FeatureFlags featureFlags = Mockito.mock(FeatureFlags.class); - Mockito.when(featureFlags.isEnabled(Mockito.any(Feature.class))) - .thenAnswer((query) -> { - if (query.getArgument(0).equals(FeatureFlags.WEBPACK)) { - return useWebpack; - } - return false; - }); - finder = Mockito.mock(ClassFinder.class); - nodeUpdater = new NodeUpdater(finder, - Mockito.mock(FrontendDependencies.class), npmFolder, - generatedPath, TARGET, featureFlags) { - - @Override - public void execute() { - } - - }; - } - - @Test - public void getGeneratedModules_should_excludeByFileName() - throws IOException { - File generated = temporaryFolder.newFolder(); - File fileA = new File(generated, "a.js"); - File fileB = new File(generated, "b.js"); - File fileC = new File(generated, "c.js"); - fileA.createNewFile(); - fileB.createNewFile(); - fileC.createNewFile(); - - Set modules = NodeUpdater.getGeneratedModules(generated, - Stream.of("a.js", "/b.js").collect(Collectors.toSet())); - - Assert.assertEquals(1, modules.size()); - // GENERATED/ is an added prefix for files from this method - Assert.assertTrue(modules.contains("GENERATED/c.js")); - } - - @Test - public void getDefaultDependencies_includesAllDependencies() { - Map defaultDeps = nodeUpdater.getDefaultDependencies(); - Set expectedDependencies = new HashSet<>(); - expectedDependencies.add("@polymer/polymer"); - expectedDependencies.add("@vaadin/common-frontend"); - expectedDependencies.add("@vaadin/router"); - expectedDependencies.add("construct-style-sheets-polyfill"); - expectedDependencies.add("lit"); - - Set actualDependendencies = defaultDeps.keySet(); - - Assert.assertEquals(expectedDependencies, actualDependendencies); - } - - @Test - public void getDefaultDevDependencies_includesAllDependencies_whenUsingVite() { - Map defaultDeps = nodeUpdater - .getDefaultDevDependencies(); - Set expectedDependencies = getCommonDevDeps(); - - // Vite - expectedDependencies.add("vite"); - expectedDependencies.add("rollup-plugin-brotli"); - expectedDependencies.add("@rollup/plugin-replace"); - expectedDependencies.add("@rollup/pluginutils"); - expectedDependencies.add("vite-plugin-checker"); - expectedDependencies.add("mkdirp"); - expectedDependencies.add("workbox-build"); - expectedDependencies.add("transform-ast"); - expectedDependencies.add("strip-css-comments"); - - Set actualDependendencies = defaultDeps.keySet(); - - Assert.assertEquals(expectedDependencies, actualDependendencies); - } - - @Test - public void getDefaultDevDependencies_includesAllDependencies_whenUsingWebpack() { - useWebpack = true; - Map defaultDeps = nodeUpdater - .getDefaultDevDependencies(); - Set expectedDependencies = getCommonDevDeps(); - - // Webpack - // Webpack plugins and helpers - expectedDependencies.add("esbuild-loader"); - expectedDependencies.add("html-webpack-plugin"); - expectedDependencies.add("fork-ts-checker-webpack-plugin"); - expectedDependencies.add("webpack"); - expectedDependencies.add("webpack-cli"); - expectedDependencies.add("webpack-dev-server"); - expectedDependencies.add("compression-webpack-plugin"); - expectedDependencies.add("extra-watch-webpack-plugin"); - expectedDependencies.add("webpack-merge"); - expectedDependencies.add("css-loader"); - expectedDependencies.add("extract-loader"); - expectedDependencies.add("lit-css-loader"); - expectedDependencies.add("file-loader"); - expectedDependencies.add("loader-utils"); - expectedDependencies.add("workbox-webpack-plugin"); - expectedDependencies.add("chokidar"); - expectedDependencies.add("strip-css-comments"); - - Set actualDependendencies = defaultDeps.keySet(); - - Assert.assertEquals(expectedDependencies, actualDependendencies); - } - - private Set getCommonDevDeps() { - Set expectedDependencies = new HashSet<>(); - expectedDependencies.add("typescript"); - expectedDependencies.add("workbox-core"); - expectedDependencies.add("workbox-precaching"); - expectedDependencies.add("glob"); - expectedDependencies.add("async"); - return expectedDependencies; - } - - @Test - public void updateMainDefaultDependencies_polymerVersionIsNull_useDefault() { - JsonObject object = Json.createObject(); - nodeUpdater.addVaadinDefaultsToJson(object); - nodeUpdater.updateDefaultDependencies(object); - - String version = getPolymerVersion(object); - Assert.assertEquals(POLYMER_VERSION, version); - } - - @Test - public void updateMainDefaultDependencies_polymerVersionIsProvidedByUser_useProvided() { - JsonObject object = Json.createObject(); - JsonObject dependencies = Json.createObject(); - dependencies.put("@polymer/polymer", "4.0.0"); - object.put(NodeUpdater.DEPENDENCIES, dependencies); - nodeUpdater.addVaadinDefaultsToJson(object); - - nodeUpdater.updateDefaultDependencies(object); - - String version = getPolymerVersion(object); - Assert.assertEquals("4.0.0", version); - } - - @Test - public void updateMainDefaultDependencies_vaadinIsProvidedByUser_useDefault() { - JsonObject object = Json.createObject(); - - JsonObject vaadin = Json.createObject(); - vaadin.put("disableUsageStatistics", true); - object.put(NodeUpdater.VAADIN_DEP_KEY, vaadin); - - nodeUpdater.addVaadinDefaultsToJson(object); - nodeUpdater.updateDefaultDependencies(object); - - Assert.assertEquals(POLYMER_VERSION, getPolymerVersion(object)); - Assert.assertEquals(POLYMER_VERSION, getPolymerVersion( - object.getObject(NodeUpdater.VAADIN_DEP_KEY))); - } - - @Test - public void updateDefaultDependencies_olderVersionsAreUpdated() - throws IOException { - JsonObject packageJson = nodeUpdater.getPackageJson(); - packageJson.put(NodeUpdater.DEPENDENCIES, Json.createObject()); - packageJson.put(NodeUpdater.DEV_DEPENDENCIES, Json.createObject()); - packageJson.getObject(NodeUpdater.DEV_DEPENDENCIES).put("glob", - "7.0.0"); - nodeUpdater.updateDefaultDependencies(packageJson); - - Assert.assertEquals("7.2.3", packageJson - .getObject(NodeUpdater.DEV_DEPENDENCIES).getString("glob")); - } - - @Test // #6907 test when user has set newer versions - public void updateDefaultDependencies_newerVersionsAreNotChanged() - throws IOException { - JsonObject packageJson = nodeUpdater.getPackageJson(); - packageJson.put(NodeUpdater.DEPENDENCIES, Json.createObject()); - packageJson.put(NodeUpdater.DEV_DEPENDENCIES, Json.createObject()); - packageJson.getObject(NodeUpdater.DEV_DEPENDENCIES).put("vite", - "v4.0.0"); - nodeUpdater.updateDefaultDependencies(packageJson); - - Assert.assertEquals("v4.0.0", packageJson - .getObject(NodeUpdater.DEV_DEPENDENCIES).getString("vite")); - } - - @Test - public void shouldUpdateExistingLocalFormPackageToNpmPackage() - throws IOException { - JsonObject packageJson = Json.createObject(); - JsonObject dependencies = Json.createObject(); - packageJson.put(NodeUpdater.DEPENDENCIES, dependencies); - JsonObject vaadinDependencies = Json.createObject(); - vaadinDependencies.put(NodeUpdater.DEPENDENCIES, Json.createObject()); - packageJson.put(NodeUpdater.VAADIN_DEP_KEY, vaadinDependencies); - - String formPackage = "@vaadin/form"; - String legecyVersion = "./target/flow-frontend/form"; - String newVersion = "22.0.0"; - - dependencies.put(formPackage, legecyVersion); - - nodeUpdater.addDependency(packageJson, NodeUpdater.DEPENDENCIES, - formPackage, newVersion); - - Assert.assertEquals(newVersion, packageJson - .getObject(NodeUpdater.DEPENDENCIES).getString(formPackage)); - } - - @Test - public void shouldSkipUpdatingNonParsableVersions() throws IOException { - JsonObject packageJson = Json.createObject(); - JsonObject dependencies = Json.createObject(); - packageJson.put(NodeUpdater.DEPENDENCIES, dependencies); - JsonObject vaadinDependencies = Json.createObject(); - vaadinDependencies.put(NodeUpdater.DEPENDENCIES, Json.createObject()); - packageJson.put(NodeUpdater.VAADIN_DEP_KEY, vaadinDependencies); - - String formPackage = "@vaadin/form"; - String existingVersion = "../../../some/local/path"; - String newVersion = "2.0.0"; - - dependencies.put(formPackage, existingVersion); - - nodeUpdater.addDependency(packageJson, NodeUpdater.DEPENDENCIES, - formPackage, newVersion); - - Assert.assertEquals(existingVersion, packageJson - .getObject(NodeUpdater.DEPENDENCIES).getString(formPackage)); - } - - @Test - public void canUpdateNonParseableVersions() throws IOException { - JsonObject packageJson = Json.createObject(); - JsonObject dependencies = Json.createObject(); - packageJson.put(NodeUpdater.DEPENDENCIES, dependencies); - JsonObject vaadinDependencies = Json.createObject(); - vaadinDependencies.put(NodeUpdater.DEPENDENCIES, Json.createObject()); - packageJson.put(NodeUpdater.VAADIN_DEP_KEY, vaadinDependencies); - - String pkg = "mypackage"; - String existingVersion = "./some/path"; - - dependencies.put(pkg, existingVersion); - - nodeUpdater.addDependency(packageJson, NodeUpdater.DEPENDENCIES, pkg, - existingVersion); - - Assert.assertEquals(existingVersion, - packageJson.getObject(NodeUpdater.DEPENDENCIES).getString(pkg)); - - } - - @Test - public void getJsonFileContent_incorrectPackageJsonContent_throwsExceptionWithFileName() - throws IOException { - File brokenPackageJsonFile = temporaryFolder - .newFile("broken-package.json"); - FileUtils.writeStringToFile(brokenPackageJsonFile, - "{ some broken json ", UTF_8); - - JsonException exception = Assert.assertThrows(JsonException.class, - () -> NodeUpdater.getJsonFileContent(brokenPackageJsonFile)); - - MatcherAssert.assertThat(exception.getMessage(), - StringContains.containsString("Cannot parse package file ")); - MatcherAssert.assertThat(exception.getMessage(), - StringContains.containsString("broken-package.json")); - } - - @Test - public void removedAllOldAndExistingPlugins() throws IOException { - File packageJson = new File(npmFolder, "package.json"); - FileWriter packageJsonWriter = new FileWriter(packageJson); - packageJsonWriter.write("{\"devDependencies\": {" - + "\"@vaadin/some-old-plugin\": \"./target/plugins/some-old-plugin\"," - + "\"@vaadin/application-theme-plugin\": \"./target/plugins/application-theme-plugin\"}" - + "}"); - packageJsonWriter.close(); - JsonObject actualDevDeps = nodeUpdater.getPackageJson() - .getObject(NodeUpdater.DEV_DEPENDENCIES); - Assert.assertFalse(actualDevDeps.hasKey("some-old-plugin")); - Assert.assertFalse( - actualDevDeps.hasKey("@vaadin/application-theme-plugin")); - } - - @Test - public void generateVersionsJson_noVersions_noDevDeps_versionsGeneratedFromPackageJson() - throws IOException { - final String versions = nodeUpdater - .generateVersionsJson(Json.createObject()); - Assert.assertNotNull(versions); - - File generatedVersionsFile = new File(npmFolder, versions); - final JsonObject versionsJson = Json.parse(FileUtils.readFileToString( - generatedVersionsFile, StandardCharsets.UTF_8)); - Assert.assertEquals("{}", versionsJson.toJson()); - } - - @Test - public void generateVersionsJson_versionsGeneratedFromPackageJson_containsBothDepsAndDevDeps() - throws IOException { - - File packageJson = new File(nodeUpdater.npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - // @formatter:off - FileUtils.write(packageJson, - "{" - + "\"vaadin\": {" - + "\"dependencies\": {" - + "\"lit\": \"2.0.0\"," - + "\"@vaadin/router\": \"1.7.4\"," - + "\"@polymer/polymer\": \"3.4.1\"," - + "}," - + "\"devDependencies\": {" - + "\"css-loader\": \"4.2.1\"," - + "\"file-loader\": \"6.1.0\"" - + "}" - + "}," - + "\"dependencies\": {" - + "\"lit\": \"2.0.0\"," - + "\"@vaadin/router\": \"1.7.4\"," - + "\"@polymer/polymer\": \"3.4.1\"," - + "}," - + "\"devDependencies\": {" - + "\"css-loader\": \"4.2.1\"," - + "\"file-loader\": \"6.1.0\"" - + "}" - + "}", StandardCharsets.UTF_8); - // @formatter:on - - final String versions = nodeUpdater.generateVersionsJson( - Json.parse(FileUtils.readFileToString(packageJson, - StandardCharsets.UTF_8))); - Assert.assertNotNull(versions); - - File generatedVersionsFile = new File(npmFolder, versions); - final JsonObject versionsJson = Json.parse(FileUtils.readFileToString( - generatedVersionsFile, StandardCharsets.UTF_8)); - Assert.assertEquals( - "{" + "\"lit\":\"2.0.0\"," + "\"@vaadin/router\":\"1.7.4\"," - + "\"@polymer/polymer\":\"3.4.1\"," - + "\"css-loader\":\"4.2.1\"," - + "\"file-loader\":\"6.1.0\"" + "}", - versionsJson.toJson()); - } - - @Test - public void testGetPlatformPinnedDependencies_vaadinCoreVersionIsNotPresent_outputIsEmptyJson() - throws IOException { - Logger logger = Mockito.spy(Logger.class); - try (MockedStatic loggerFactoryMocked = Mockito - .mockStatic(LoggerFactory.class)) { - loggerFactoryMocked - .when(() -> LoggerFactory.getLogger(nodeUpdater.getClass())) - .thenReturn(logger); - - Mockito.when( - finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(null); - Mockito.when(finder.getResource(Constants.VAADIN_VERSIONS_JSON)) - .thenReturn(null); - - JsonObject pinnedVersions = nodeUpdater - .getPlatformPinnedDependencies(); - Assert.assertEquals(0, pinnedVersions.keys().length); - - Mockito.verify(logger, Mockito.times(1)).info( - "Couldn't find {} file to pin dependency versions for core components." - + " Transitive dependencies won't be pinned for npm/pnpm.", - Constants.VAADIN_CORE_VERSIONS_JSON); - } - } - - @Test - public void testGetPlatformPinnedDependencies_onlyVaadinCoreVersionIsPresent_outputContainsOnlyCoreVersions() - throws IOException { - File coreVersionsFile = File.createTempFile("vaadin-core-versions", - ".json", temporaryFolder.newFolder()); - JsonObject mockedVaadinCoreJson = getMockVaadinCoreVersionsJson(); - Assert.assertTrue(mockedVaadinCoreJson.hasKey("core")); - Assert.assertTrue( - mockedVaadinCoreJson.getObject("core").hasKey("button")); - Assert.assertFalse(mockedVaadinCoreJson.hasKey("vaadin")); - - FileUtils.write(coreVersionsFile, mockedVaadinCoreJson.toJson(), - StandardCharsets.UTF_8); - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(coreVersionsFile.toURI().toURL()); - Mockito.when(finder.getResource(Constants.VAADIN_VERSIONS_JSON)) - .thenReturn(null); - - JsonObject pinnedVersions = nodeUpdater.getPlatformPinnedDependencies(); - - Assert.assertTrue(pinnedVersions.hasKey("@vaadin/button")); - Assert.assertFalse(pinnedVersions.hasKey("@vaadin/grid-pro")); - Assert.assertFalse(pinnedVersions.hasKey("@vaadin/vaadin-grid-pro")); - } - - @Test - public void testGetPlatformPinnedDependencies_VaadinAndVaadinCoreVersionsArePresent_outputContainsBothCoreAndCommercialVersions() - throws IOException { - File coreVersionsFile = File.createTempFile("vaadin-core-versions", - ".json", temporaryFolder.newFolder()); - JsonObject mockedVaadinCoreJson = getMockVaadinCoreVersionsJson(); - Assert.assertTrue(mockedVaadinCoreJson.hasKey("core")); - Assert.assertTrue( - mockedVaadinCoreJson.getObject("core").hasKey("button")); - Assert.assertFalse(mockedVaadinCoreJson.hasKey("vaadin")); - - FileUtils.write(coreVersionsFile, mockedVaadinCoreJson.toJson(), - StandardCharsets.UTF_8); - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(coreVersionsFile.toURI().toURL()); - - File vaadinVersionsFile = File.createTempFile("vaadin-versions", - ".json", temporaryFolder.newFolder()); - JsonObject mockedVaadinJson = getMockVaadinVersionsJson(); - Assert.assertFalse(mockedVaadinJson.hasKey("core")); - Assert.assertTrue(mockedVaadinJson.hasKey("vaadin")); - Assert.assertTrue( - mockedVaadinJson.getObject("vaadin").hasKey("grid-pro")); - Assert.assertTrue( - mockedVaadinJson.getObject("vaadin").hasKey("vaadin-grid-pro")); - - FileUtils.write(vaadinVersionsFile, mockedVaadinJson.toJson(), - StandardCharsets.UTF_8); - Mockito.when(finder.getResource(Constants.VAADIN_VERSIONS_JSON)) - .thenReturn(vaadinVersionsFile.toURI().toURL()); - - JsonObject pinnedVersions = nodeUpdater.getPlatformPinnedDependencies(); - - Assert.assertTrue(pinnedVersions.hasKey("@vaadin/button")); - Assert.assertTrue(pinnedVersions.hasKey("@vaadin/grid-pro")); - Assert.assertTrue(pinnedVersions.hasKey("@vaadin/vaadin-grid-pro")); - } - - private String getPolymerVersion(JsonObject object) { - JsonObject deps = object.get("dependencies"); - String version = deps.getString("@polymer/polymer"); - return version; - } - - private JsonObject getMockVaadinCoreVersionsJson() { - // @formatter:off - return Json.parse( - "{\n" + - " \"bundles\": {\n" + - " \"vaadin\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/bundles\"\n" + - " }\n" + - " },\n" + - " \"core\": {\n" + - " \"accordion\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/accordion\"\n" + - " },\n" + - " \"app-layout\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/app-layout\"\n" + - " },\n" + - " \"avatar\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/avatar\"\n" + - " },\n" + - " \"avatar-group\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/avatar-group\"\n" + - " },\n" + - " \"button\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/button\"\n" + - " },\n" + - " \"checkbox\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/checkbox\"\n" + - " }" + - " },\n" + - " \"platform\": \"23.2.0\"\n" + - "}" - ); - // @formatter:on - } - - private JsonObject getMockVaadinVersionsJson() { - // @formatter:off - return Json.parse( - "{\n" + - " \"vaadin\": {\n" + - " \"board\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/board\"\n" + - " },\n" + - " \"charts\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/charts\"\n" + - " },\n" + - " \"grid-pro\": {\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/grid-pro\"\n" + - " },\n" + - " \"vaadin-board\": {\n" + - " \"component\": true,\n" + - " \"javaVersion\": \"23.2.0\",\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/vaadin-board\",\n" + - " \"pro\": true\n" + - " },\n" + - " \"vaadin-charts\": {\n" + - " \"component\": true,\n" + - " \"javaVersion\": \"23.2.0\",\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/vaadin-charts\",\n" + - " \"pro\": true\n" + - " },\n" + - " \"vaadin-grid-pro\": {\n" + - " \"component\": true,\n" + - " \"javaVersion\": \"23.2.0\",\n" + - " \"jsVersion\": \"23.2.0\",\n" + - " \"npmName\": \"@vaadin/vaadin-grid-pro\",\n" + - " \"pro\": true\n" + - " },\n" + - " },\n" + - " \"platform\": \"23.2.0\"\n" + - "}" - ); - // @formatter:on - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyFrontendFilesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyFrontendFilesTest.java deleted file mode 100644 index 2cc02cf4b02..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyFrontendFilesTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.testutil.TestUtils; - -import elemental.json.JsonObject; - -import static com.vaadin.flow.server.Constants.PACKAGE_JSON; -import static com.vaadin.flow.server.Constants.TARGET; - -public class TaskCopyFrontendFilesTest extends NodeUpdateTestUtil { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File npmFolder; - private File generatedFolder; - private File frontendDepsFolder; - - @Before - public void setup() throws IOException { - // creating non-existing folder to make sure the execute() creates - // the folder if missing - npmFolder = new File(temporaryFolder.newFolder(), "child/"); - generatedFolder = new File(npmFolder, "target/frontend"); - frontendDepsFolder = new File(npmFolder, "target/frontend-deps"); - } - - @Test - public void should_collectJsAndCssFilesFromJars_obsoleteResourceFolder() - throws IOException { - should_collectJsAndCssFilesFromJars("jar-with-frontend-resources.jar", - "dir-with-frontend-resources/"); - } - - @Test - public void should_collectJsAndCssFilesFromJars_modernResourceFolder() - throws IOException { - should_collectJsAndCssFilesFromJars("jar-with-modern-frontend.jar", - "dir-with-modern-frontend"); - } - - @Test - public void should_createPackageJson() throws IOException { - TaskGeneratePackageJson task = new TaskGeneratePackageJson(npmFolder, - generatedFolder, TARGET, Mockito.mock(FeatureFlags.class)); - task.execute(); - Assert.assertTrue(new File(npmFolder, PACKAGE_JSON).exists()); - Assert.assertFalse(new File(generatedFolder, PACKAGE_JSON).exists()); - JsonObject deps = task.getPackageJson().getObject("dependencies"); - Assert.assertFalse(deps.hasKey(NodeUpdater.DEP_NAME_FLOW_DEPS)); - Assert.assertFalse(deps.hasKey(NodeUpdater.DEP_NAME_FLOW_JARS)); - } - - private void should_collectJsAndCssFilesFromJars(String jarFile, - String fsDir) throws IOException { - - // contains: - // - ExampleConnector.js - // - ExampleConnector.js.map - // - inline.css - // - inline.css.map - // - example.ts - // - example.ts.map - File jar = TestUtils.getTestJar(jarFile); - // Contains: - // - resourceInFolder.js - // - resourceInFolder.js.map - File dir = TestUtils.getTestFolder(fsDir); - - TaskCopyFrontendFiles task = new TaskCopyFrontendFiles( - frontendDepsFolder, jars(jar, dir)); - - task.execute(); - - List files = TestUtils.listFilesRecursively(frontendDepsFolder); - Assert.assertEquals(10, files.size()); - - Assert.assertTrue("TS resource should have been copied from jar file", - files.contains("example.ts")); - - Assert.assertTrue( - "TS resource source map should have been copied from jar file", - files.contains("example.ts.map")); - - Assert.assertTrue("JS resource should have been copied from jar file", - files.contains("ExampleConnector.js")); - - Assert.assertTrue( - "JS resource source map should have been copied from jar file", - files.contains("ExampleConnector.js.map")); - - Assert.assertTrue("CSS resource should have been copied from jar file", - files.contains("inline.css")); - - Assert.assertTrue( - "CSS resource source map should have been copied from jar file", - files.contains("inline.css.map")); - - Assert.assertTrue( - "JS resource should have been copied from resource folder", - files.contains("resourceInFolder.js")); - - Assert.assertTrue( - "JS resource source map should have been copied from resource folder", - files.contains("resourceInFolder.js.map")); - - Assert.assertTrue("TSX resource should have been copied from jar file", - files.contains("react.tsx")); - - Assert.assertTrue( - "TSX resource source map should have been copied from jar file", - files.contains("react.tsx.map")); - } - - private static Set jars(File... files) { - return Stream.of(files).collect(Collectors.toSet()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyLocalFrontendFilesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyLocalFrontendFilesTest.java deleted file mode 100644 index 19de33381f7..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyLocalFrontendFilesTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class TaskCopyLocalFrontendFilesTest { - - @Rule - public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Test - public void directoryWithReadOnlyFile_copyIsNotReadOnly() - throws IOException { - final File sourceFolder = createReadOnlySource(); - - final File outFolder = temporaryFolder.newFolder("out"); - - TaskCopyLocalFrontendFiles.copyLocalResources(sourceFolder, outFolder); - - final File copiedReadOnly = new File(outFolder, "readOnly.txt"); - Assert.assertTrue( - "Copied files should be writable even when source is readOnly", - copiedReadOnly.canWrite()); - - } - - @Test - public void directoryWithReadOnlyFile_canCopyMultipleTimesToSource() - throws IOException { - final File sourceFolder = createReadOnlySource(); - - final File outFolder = temporaryFolder.newFolder("out"); - - TaskCopyLocalFrontendFiles.copyLocalResources(sourceFolder, outFolder); - - TaskCopyLocalFrontendFiles.copyLocalResources(sourceFolder, outFolder); - } - - private File createReadOnlySource() throws IOException { - final File sourceFolder = temporaryFolder.newFolder("source"); - File readOnly = new File(sourceFolder, "readOnly.txt"); - readOnly.createNewFile(); - Assert.assertTrue("Could not make file read-only", - readOnly.setReadOnly()); - - return sourceFolder; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyTemplateFilesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyTemplateFilesTest.java deleted file mode 100644 index 900f19d45f8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskCopyTemplateFilesTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.internal.Template; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.testutil.TestUtils; - -public class TaskCopyTemplateFilesTest { - - @Tag("my-lit-element-view") - @JsModule("./my-lit-element-view.js") - public static class MyLitElementView implements Template { - } - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File projectDirectory; - private File resourceOutputDirectory; - - private ClassFinder finder; - - @Before - public void setup() throws IOException, ClassNotFoundException { - // creating non-existing folder to make sure the execute() creates - // the folder if missing - projectDirectory = temporaryFolder.newFolder(); - resourceOutputDirectory = new File(projectDirectory, - "target/" + Constants.VAADIN_SERVLET_RESOURCES); - finder = Mockito.mock(ClassFinder.class); - Mockito.when(finder.getSubTypesOf(Template.class)) - .thenReturn(Collections.singleton(MyLitElementView.class)); - Class clazz = JsModule.class; - Mockito.when(finder.loadClass(JsModule.class.getName())) - .thenReturn(clazz); - } - - @Test - public void should_copyTemplateFilesFromDefaultFrontendDirectory() - throws Exception { - executeTaskCopyTemplateFiles(FrontendUtils.FRONTEND); - } - - @Test - public void should_copyTemplateFilesFromCustomFrontendDirectory() - throws Exception { - executeTaskCopyTemplateFiles("frontend-custom"); - } - - private void executeTaskCopyTemplateFiles(String frontedDirectoryName) - throws Exception { - // prepare frontend resource - File frontendDirectory = new File(projectDirectory, - frontedDirectoryName); - frontendDirectory.mkdirs(); - new File(frontendDirectory, "my-lit-element-view.js").createNewFile(); - - TaskCopyTemplateFiles task = new TaskCopyTemplateFiles(finder, - projectDirectory, resourceOutputDirectory, frontendDirectory); - task.execute(); - - List files = TestUtils - .listFilesRecursively(resourceOutputDirectory); - Assert.assertTrue("TS resource should have been copied", files.stream() - .anyMatch(file -> file.contains("my-lit-element-view.js"))); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateBootstrapTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateBootstrapTest.java deleted file mode 100644 index d80be7fa4d3..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateBootstrapTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.ThemeDefinition; - -import static com.vaadin.flow.server.frontend.FrontendUtils.FRONTEND; -import static com.vaadin.flow.server.frontend.FrontendUtils.INDEX_TS; -import static com.vaadin.flow.server.frontend.FrontendUtils.FEATURE_FLAGS_FILE_NAME; -import static com.vaadin.flow.server.frontend.NodeUpdateTestUtil.getClassFinder; - -public class TaskGenerateBootstrapTest { - - private static final String DEV_TOOLS_IMPORT = "import '" - + FrontendUtils.JAR_RESOURCES_IMPORT + "vaadin-dev-tools.js';"; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private FrontendDependenciesScanner frontDeps; - private File frontendFolder; - private TaskGenerateBootstrap taskGenerateBootstrap; - - @Before - public void setUp() throws Exception { - frontDeps = new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(false, new ClassFinder.DefaultClassFinder( - Collections.singleton(this.getClass())), false); - - frontendFolder = temporaryFolder.newFolder(FRONTEND); - taskGenerateBootstrap = new TaskGenerateBootstrap(frontDeps, - frontendFolder, true); - } - - @Test - public void should_importGeneratedIndexTS() - throws ExecutionFailedException { - taskGenerateBootstrap.execute(); - String content = taskGenerateBootstrap.getFileContent(); - Assert.assertTrue(content.contains("import './index';")); - } - - @Test - public void shouldNot_importDevTools_inProduction() - throws ExecutionFailedException { - taskGenerateBootstrap.execute(); - String content = taskGenerateBootstrap.getFileContent(); - Assert.assertFalse(content.contains(DEV_TOOLS_IMPORT)); - } - - @Test - public void should_importDevTools_inDevMode() - throws ExecutionFailedException { - taskGenerateBootstrap = new TaskGenerateBootstrap(frontDeps, - frontendFolder, false); - taskGenerateBootstrap.execute(); - String content = taskGenerateBootstrap.getFileContent(); - Assert.assertTrue(content.contains(DEV_TOOLS_IMPORT)); - } - - @Test - public void should_importFrontendIndexTS() - throws ExecutionFailedException, IOException { - new File(frontendFolder, INDEX_TS).createNewFile(); - taskGenerateBootstrap.execute(); - String content = taskGenerateBootstrap.getFileContent(); - Assert.assertTrue(content.contains("import '../index';")); - } - - @Test - public void should_importFeatureFlagTS() throws ExecutionFailedException { - taskGenerateBootstrap.execute(); - String content = taskGenerateBootstrap.getFileContent(); - Assert.assertTrue(content.contains( - String.format("import './%s';", FEATURE_FLAGS_FILE_NAME))); - } - - @Test - public void should_load_AppTheme() - throws MalformedURLException, ExecutionFailedException { - taskGenerateBootstrap = new TaskGenerateBootstrap(getThemedDependency(), - frontendFolder, true); - taskGenerateBootstrap.execute(); - String content = taskGenerateBootstrap.getFileContent(); - - final List expectedContent = Arrays.asList("import './index';", - "import { applyTheme } from './theme';", - "applyTheme(document);"); - - expectedContent.forEach(expectedLine -> Assert.assertTrue( - String.format( - "Bootstrap 'vaadin.ts' file is supposed to contain " - + "the line: [%s],\nbut actually contains the " - + "following: [%s]", - expectedLine, content), - content.contains(expectedLine))); - } - - private FrontendDependencies getThemedDependency() - throws MalformedURLException { - ClassFinder finder = getClassFinder(); - return new FrontendDependencies(finder) { - - @Override - public List getModules() { - return Collections.emptyList(); - } - - @Override - public Set getScripts() { - return Collections.emptySet(); - } - - @Override - public AbstractTheme getTheme() { - return new UpdateThemedImportsTest.MyTheme(); - } - - @Override - public ThemeDefinition getThemeDefinition() { - return new ThemeDefinition( - UpdateThemedImportsTest.MyTheme.class, "", "my-theme"); - } - }; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateFeatureFlagsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateFeatureFlagsTest.java deleted file mode 100644 index e1fe7a00085..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateFeatureFlagsTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.experimental.Feature; -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.startup.ApplicationConfiguration; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import java.io.File; - -import static com.vaadin.flow.server.frontend.FrontendUtils.FRONTEND; - -public class TaskGenerateFeatureFlagsTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private TaskGenerateFeatureFlags taskGenerateFeatureFlags; - private FeatureFlags featureFlags; - - @Before - public void setUp() throws Exception { - VaadinContext context = new MockVaadinContext(); - ApplicationConfiguration configuration = Mockito - .mock(ApplicationConfiguration.class); - context.setAttribute(ApplicationConfiguration.class, configuration); - - File frontendFolder = temporaryFolder.newFolder(FRONTEND); - featureFlags = FeatureFlags.get(context); - taskGenerateFeatureFlags = new TaskGenerateFeatureFlags(frontendFolder, - featureFlags); - } - - @Test - public void should_disableTypeChecksForGlobals() - throws ExecutionFailedException { - taskGenerateFeatureFlags.execute(); - String content = taskGenerateFeatureFlags.getFileContent(); - Assert.assertTrue(content.startsWith("// @ts-nocheck")); - } - - @Test - public void should_setupFeatureFlagsGlobal() - throws ExecutionFailedException { - taskGenerateFeatureFlags.execute(); - String content = taskGenerateFeatureFlags.getFileContent(); - Assert.assertTrue( - content.contains("window.Vaadin = window.Vaadin || {};")); - Assert.assertTrue(content.contains( - "window.Vaadin.featureFlags = window.Vaadin.featureFlags || {};")); - } - - @Test - public void should_defineAllFeatureFlags() throws ExecutionFailedException { - taskGenerateFeatureFlags.execute(); - String content = taskGenerateFeatureFlags.getFileContent(); - - featureFlags.getFeatures().forEach(feature -> { - assertFeatureFlagGlobal(content, feature, false); - }); - } - - @Test - public void should_defineCorrectEnabledValue() - throws ExecutionFailedException { - // Enable example feature - featureFlags.getFeatures().stream() - .filter(feature -> feature.equals(FeatureFlags.EXAMPLE)) - .forEach(feature -> feature.setEnabled(true)); - - taskGenerateFeatureFlags.execute(); - String content = taskGenerateFeatureFlags.getFileContent(); - - assertFeatureFlagGlobal(content, FeatureFlags.EXAMPLE, true); - } - - @Test - public void should_containEmptyExport() throws ExecutionFailedException { - taskGenerateFeatureFlags.execute(); - String content = taskGenerateFeatureFlags.getFileContent(); - Assert.assertTrue(content.contains("export {};")); - } - - private static void assertFeatureFlagGlobal(String content, Feature feature, - boolean enabled) { - Assert.assertTrue(content - .contains(String.format("window.Vaadin.featureFlags.%s = %s", - feature.getId(), enabled))); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateIndexHtmlTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateIndexHtmlTest.java deleted file mode 100644 index 909191c25a1..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateIndexHtmlTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import static com.vaadin.flow.server.frontend.FrontendUtils.INDEX_HTML; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class TaskGenerateIndexHtmlTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File frontendFolder; - private TaskGenerateIndexHtml taskGenerateIndexHtml; - - @Before - public void setUp() throws IOException { - frontendFolder = temporaryFolder.newFolder(); - taskGenerateIndexHtml = new TaskGenerateIndexHtml(frontendFolder); - } - - @Test - public void should_loadCorrectContentOfDefaultFile() throws Exception { - String defaultContent = IOUtils.toString( - getClass().getResourceAsStream(INDEX_HTML), - StandardCharsets.UTF_8); - - Assert.assertEquals( - "Should load correct default content from index.html", - defaultContent, taskGenerateIndexHtml.getFileContent()); - } - - @Test - public void should_notOverwriteIndexHtml_IndexHtmlExists() - throws Exception { - File indexhtml = new File(frontendFolder, "index.html"); - Files.createFile(indexhtml.toPath()); - taskGenerateIndexHtml.execute(); - Assert.assertFalse( - "Should not generate index.html while it exists in the frontend folder", - taskGenerateIndexHtml.shouldGenerate()); - Assert.assertEquals("", - IOUtils.toString(indexhtml.toURI(), StandardCharsets.UTF_8)); - } - - @Test - public void should_generateIndexHtml_IndexHtmlNotExist() throws Exception { - String defaultContent = IOUtils.toString( - getClass().getResourceAsStream(INDEX_HTML), - StandardCharsets.UTF_8); - Assert.assertTrue( - "Should generate index.html when it doesn't exists in the frontend folder", - taskGenerateIndexHtml.shouldGenerate()); - - taskGenerateIndexHtml.execute(); - - Assert.assertTrue("The generated file should exists", - taskGenerateIndexHtml.getGeneratedFile().exists()); - - Assert.assertEquals("Should have default content of index.html", - defaultContent, - IOUtils.toString( - taskGenerateIndexHtml.getGeneratedFile().toURI(), - StandardCharsets.UTF_8)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateIndexTsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateIndexTsTest.java deleted file mode 100644 index 69e9c3cfb7e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateIndexTsTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import com.vaadin.flow.internal.UsageStatistics; -import com.vaadin.flow.server.Constants; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.FRONTEND; -import static com.vaadin.flow.server.frontend.FrontendUtils.INDEX_JS; -import static com.vaadin.flow.server.frontend.FrontendUtils.INDEX_TS; - -public class TaskGenerateIndexTsTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File frontendFolder; - private File outputFolder; - private File generatedImports; - private TaskGenerateIndexTs taskGenerateIndexTs; - - @Before - public void setUp() throws IOException { - frontendFolder = temporaryFolder.newFolder(FRONTEND); - outputFolder = temporaryFolder.newFolder(TARGET); - File generatedFolder = temporaryFolder.newFolder(TARGET, FRONTEND); - generatedImports = new File(generatedFolder, - "flow-generated-imports.js"); - generatedImports.createNewFile(); - taskGenerateIndexTs = new TaskGenerateIndexTs(frontendFolder, - generatedImports, outputFolder); - } - - @Test - public void should_reported_routing_client_when_IndexJsExists() - throws Exception { - Files.createFile(new File(frontendFolder, INDEX_JS).toPath()); - taskGenerateIndexTs.execute(); - Assert.assertTrue(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_CLIENT.equals(e.getName()))); - } - - @Test - public void should_reported_routing_client_when_IndexTsExists() - throws Exception { - Files.createFile(new File(frontendFolder, INDEX_TS).toPath()); - taskGenerateIndexTs.execute(); - Assert.assertTrue(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_CLIENT.equals(e.getName()))); - } - - @Test - public void should_not_reported_routing_client() throws Exception { - taskGenerateIndexTs.execute(); - Assert.assertFalse(UsageStatistics.getEntries().anyMatch( - e -> Constants.STATISTIC_ROUTING_CLIENT.equals(e.getName()))); - } - - @Test - public void should_notGenerateIndexTs_IndexJsExists() throws Exception { - Files.createFile(new File(frontendFolder, INDEX_JS).toPath()); - taskGenerateIndexTs.execute(); - Assert.assertFalse( - "Should not generate index.ts when index.js exists in" - + " the frontend folder", - taskGenerateIndexTs.shouldGenerate()); - Assert.assertFalse("The generated file should not exists", - taskGenerateIndexTs.getGeneratedFile().exists()); - } - - @Test - public void should_notGenerateIndexTs_IndexTsExists() throws Exception { - Files.createFile(new File(frontendFolder, INDEX_TS).toPath()); - taskGenerateIndexTs.execute(); - Assert.assertFalse( - "Should not generate index.ts when index.ts exists in" - + " the frontend folder", - taskGenerateIndexTs.shouldGenerate()); - Assert.assertFalse("The generated file should not exists", - taskGenerateIndexTs.getGeneratedFile().exists()); - } - - @Test - public void should_generateIndexJs_IndexJsNotExist() throws Exception { - - taskGenerateIndexTs.execute(); - Assert.assertTrue( - "Should generate index.ts when it doesn't exist in" - + " the frontend folder", - taskGenerateIndexTs.shouldGenerate()); - Assert.assertTrue("The generated file should exists", - taskGenerateIndexTs.getGeneratedFile().exists()); - - Assert.assertEquals("Should have default content of index.ts", - taskGenerateIndexTs.getFileContent(), - IOUtils.toString(taskGenerateIndexTs.getGeneratedFile().toURI(), - StandardCharsets.UTF_8)); - } - - @Test - public void replacedImport_should_beRelativeTo_targetAndFrontend() - throws Exception { - String content = taskGenerateIndexTs.getFileContent(); - Assert.assertTrue(content.contains( - "import('../../target/frontend/flow-generated-imports'")); - - // custom frontend folder - taskGenerateIndexTs = new TaskGenerateIndexTs( - temporaryFolder.newFolder("src", "main", FRONTEND), - generatedImports, outputFolder); - content = taskGenerateIndexTs.getFileContent(); - Assert.assertTrue(content.contains( - "import('../../../../target/frontend/flow-generated-imports'")); - } - - @Test - public void should_ensureValidRelativePath_whenItHasNoRelativePrefix() { - String customPath = TaskGenerateIndexTs.ensureValidRelativePath( - "../custom-frontend/generated-flow-imports.js"); - Assert.assertEquals( - "Should not append './' if it is already a relative path", - "../custom-frontend/generated-flow-imports.js", customPath); - - customPath = TaskGenerateIndexTs.ensureValidRelativePath( - "custom-frontend/generated-flow-imports.js"); - Assert.assertEquals( - "Should append './' if it doesn't start with a relative path", - "./custom-frontend/generated-flow-imports.js", customPath); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateServicWorkerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateServicWorkerTest.java deleted file mode 100644 index 7f5869f5617..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateServicWorkerTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import static com.vaadin.flow.server.frontend.FrontendUtils.SERVICE_WORKER_SRC; -import static com.vaadin.flow.server.frontend.FrontendUtils.SERVICE_WORKER_SRC_JS;; - -public class TaskGenerateServicWorkerTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File frontendFolder; - private File outputFolder; - private TaskGenerateServiceWorker taskGenerateServiceWorker; - - @Before - public void setUp() throws IOException { - frontendFolder = temporaryFolder.newFolder(); - outputFolder = temporaryFolder.newFolder(); - taskGenerateServiceWorker = new TaskGenerateServiceWorker( - frontendFolder, outputFolder); - } - - @Test - public void should_loadCorrectContentOfDefaultFile() throws Exception { - String defaultContent = IOUtils.toString( - getClass().getResourceAsStream(SERVICE_WORKER_SRC), - StandardCharsets.UTF_8); - - Assert.assertEquals("Should load correct default content from sw.ts", - defaultContent, taskGenerateServiceWorker.getFileContent()); - } - - @Test - public void should_notGenerateServiceWorker_ServiceWorkerExists() - throws Exception { - Files.createFile(new File(frontendFolder, SERVICE_WORKER_SRC).toPath()); - taskGenerateServiceWorker.execute(); - Assert.assertFalse( - "Should not generate sw.ts while it exists in" - + " the frontend folder", - taskGenerateServiceWorker.shouldGenerate()); - Assert.assertFalse("The generated file should not exists", - taskGenerateServiceWorker.getGeneratedFile().exists()); - } - - @Test - public void should_notGenerateServiceWorker_ServiceWorkerJsExists() - throws Exception { - Files.createFile( - new File(frontendFolder, SERVICE_WORKER_SRC_JS).toPath()); - taskGenerateServiceWorker.execute(); - Assert.assertFalse( - "Should not generate sw.ts while sw.js exists in" - + " the frontend folder", - taskGenerateServiceWorker.shouldGenerate()); - Assert.assertFalse("The generated file should not exists", - taskGenerateServiceWorker.getGeneratedFile().exists()); - } - - @Test - public void should_generateServiceWorker_ServiceWorkerNotExist() - throws Exception { - String defaultContent = IOUtils.toString( - getClass().getResourceAsStream(SERVICE_WORKER_SRC), - StandardCharsets.UTF_8); - taskGenerateServiceWorker.execute(); - Assert.assertTrue( - "Should generate sw.ts when it doesn't exists in" - + " the frontend folder", - taskGenerateServiceWorker.shouldGenerate()); - Assert.assertTrue("The generated file should exists", - taskGenerateServiceWorker.getGeneratedFile().exists()); - - Assert.assertEquals("Should have default content of sw.ts", - defaultContent, - IOUtils.toString( - taskGenerateServiceWorker.getGeneratedFile().toURI(), - StandardCharsets.UTF_8)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateTsConfigTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateTsConfigTest.java deleted file mode 100644 index 13657721af4..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateTsConfigTest.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.Feature; -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.ExecutionFailedException; - -import static java.nio.charset.StandardCharsets.UTF_8; - -public class TaskGenerateTsConfigTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File npmFolder; - private TaskGenerateTsConfig taskGenerateTsConfig; - - private FeatureFlags featureFlags; - - @Before - public void setUp() throws IOException { - npmFolder = temporaryFolder.newFolder(); - featureFlags = Mockito.mock(FeatureFlags.class); - taskGenerateTsConfig = new TaskGenerateTsConfig(npmFolder, - featureFlags); - } - - @Test - public void should_generateTsConfig_TsConfigNotExist() throws Exception { - taskGenerateTsConfig.execute(); - Assert.assertFalse( - "Should generate tsconfig.json when " - + "tsconfig.json doesn't exist", - taskGenerateTsConfig.shouldGenerate()); - Assert.assertTrue("The generated tsconfig.json should not exist", - taskGenerateTsConfig.getGeneratedFile().exists()); - Assert.assertEquals( - "The generated content should be equals the default content", - taskGenerateTsConfig.getFileContent(), - IOUtils.toString( - taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8)); - } - - @Test - public void viteShouldNotUseEs2019() throws Exception { - taskGenerateTsConfig.execute(); - Assert.assertFalse("The config file should not use es2019", IOUtils - .toString(taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8) - .contains("\"target\": \"es2019\"")); - } - - @Test - public void webpackShouldUseEs2019() throws Exception { - Mockito.when(featureFlags.isEnabled((Feature) Mockito.any())) - .thenAnswer(req -> { - if (req.getArgument(0) == FeatureFlags.WEBPACK) { - return true; - } - return false; - }); - - taskGenerateTsConfig.execute(); - Assert.assertTrue("The config file should use es2019", IOUtils - .toString(taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8) - .contains("\"target\": \"es2019\"")); - } - - @Test - public void viteShouldUpgradeFromEs2019() throws Exception { - AtomicBoolean useWebpack = new AtomicBoolean(true); - Mockito.when(featureFlags.isEnabled((Feature) Mockito.any())) - .thenAnswer(req -> { - if (req.getArgument(0) == FeatureFlags.WEBPACK) { - return useWebpack.get(); - } - return false; - }); - - taskGenerateTsConfig.execute(); // Write a file with es2019 - Assert.assertTrue("The config file should use es2019", IOUtils - .toString(taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8) - .contains("\"target\": \"es2019\"")); - useWebpack.set(false); - taskGenerateTsConfig.execute(); - Assert.assertFalse( - "Vite should have upgraded the config file to not use es2019", - IOUtils.toString( - taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8) - .contains("\"target\": \"es2019\"")); - - } - - @Test - public void switchToWebpackShouldDowngradeToEs2019() throws Exception { - AtomicBoolean useWebpack = new AtomicBoolean(false); - Mockito.when(featureFlags.isEnabled((Feature) Mockito.any())) - .thenAnswer(req -> { - if (req.getArgument(0) == FeatureFlags.WEBPACK) { - return useWebpack.get(); - } - return false; - }); - - taskGenerateTsConfig.execute(); // Write a file without es2019 - Assert.assertFalse("The config file should not use es2019", IOUtils - .toString(taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8) - .contains("\"target\": \"es2019\"")); - useWebpack.set(true); - taskGenerateTsConfig.execute(); - Assert.assertTrue( - "Webpack should have downgraded the config file to use es2019", - IOUtils.toString( - taskGenerateTsConfig.getGeneratedFile().toURI(), - StandardCharsets.UTF_8) - .contains("\"target\": \"es2019\"")); - - } - - @Test - public void should_notGenerateTsConfig_TsConfigExist() throws Exception { - Files.createFile(new File(npmFolder, "tsconfig.json").toPath()); - taskGenerateTsConfig.execute(); - Assert.assertFalse( - "Should not generate tsconfig.json when tsconfig.json exists", - taskGenerateTsConfig.shouldGenerate()); - Assert.assertTrue("The tsconfig.json should already exist", - taskGenerateTsConfig.getGeneratedFile().exists()); - } - - @Test - public void tsConfigUpdated_remindsUpdateVersionAndTemplates() - throws IOException { - File tsconfig = new File(npmFolder, "tsconfig.json"); - Files.createFile(tsconfig.toPath()); - FileUtils.writeStringToFile(tsconfig, "{}", UTF_8); - try { - taskGenerateTsConfig.execute(); - } catch (Exception ignore) { - - } - - String tsConfigLatest = FileUtils.readFileToString(tsconfig, UTF_8); - - String testTsConfig = IOUtils.toString( - Objects.requireNonNull(TaskGenerateTsConfigTest.class - .getClassLoader() - .getResourceAsStream("tsconfig-reference.json")), - StandardCharsets.UTF_8); - - Assert.assertEquals("tsconfig.json content has been updated. " - + "Please also: 1. Increment version in tsconfig.json (\"flow_version\" property) " - + "2. create a new tsconfig-vX.Y.json template in flow-server resources and put the old content there " - + "3. update vaadinVersion array in TaskGenerateTsConfig with X.Y " - + "4. put a new content in tsconfig-reference.json in tests", - testTsConfig, tsConfigLatest); - - } - - @Test - public void tsConfigHasLatestVersion_noUpdates() - throws IOException, ExecutionFailedException { - File tsconfig = new File(npmFolder, "tsconfig.json"); - Files.createFile(tsconfig.toPath()); - FileUtils.writeStringToFile(tsconfig, "{\"flow_version\": \"23.3.0\"}", - UTF_8); - taskGenerateTsConfig.execute(); - - String tsConfigString = FileUtils.readFileToString(tsconfig, UTF_8); - - String expected = IOUtils.toString( - Objects.requireNonNull(TaskGenerateTsConfigTest.class - .getClassLoader() - .getResourceAsStream("tsconfig-latest-version.json")), - StandardCharsets.UTF_8); - - Assert.assertEquals(expected, tsConfigString); - } - - @Test - public void tsConfigHasCustomCodes_updatesAndThrows() throws IOException { - File tsconfig = writeTestTsConfigContent( - "tsconfig-custom-content.json"); - try { - taskGenerateTsConfig.execute(); - } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains( - "TypeScript config file 'tsconfig.json' has been updated to the latest")); - String tsConfigString = FileUtils.readFileToString(tsconfig, UTF_8); - Assert.assertTrue(tsConfigString.contains( - "\"@vaadin/flow-frontend\": [\"generated/jar-resources\"],")); - return; - } - Assert.fail("Expected exception to be thrown"); - } - - @Test - public void defaultTsConfig_updatesSilently() - throws IOException, ExecutionFailedException { - File tsconfig = writeTestTsConfigContent("tsconfig-default.json"); - taskGenerateTsConfig.execute(); - String tsConfigString = FileUtils.readFileToString(tsconfig, UTF_8); - Assert.assertTrue(tsConfigString.contains( - "\"@vaadin/flow-frontend\": [\"generated/jar-resources\"],")); - } - - @Test - public void olderTsConfig_updatesSilently() - throws IOException, ExecutionFailedException { - File tsconfig = writeTestTsConfigContent("tsconfig-older.json"); - taskGenerateTsConfig.execute(); - String tsConfigString = FileUtils.readFileToString(tsconfig, UTF_8); - Assert.assertTrue(tsConfigString.contains( - "\"@vaadin/flow-frontend\": [\"generated/jar-resources\"],")); - } - - private File writeTestTsConfigContent(String s) throws IOException { - File tsconfig = new File(npmFolder, "tsconfig.json"); - Files.createFile(tsconfig.toPath()); - String content = IOUtils.toString( - Objects.requireNonNull(TaskGenerateTsConfigTest.class - .getClassLoader().getResourceAsStream(s)), - StandardCharsets.UTF_8); - FileUtils.writeStringToFile(tsconfig, content, UTF_8); - return tsconfig; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateTsDefinitionsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateTsDefinitionsTest.java deleted file mode 100644 index 53c00cc010c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateTsDefinitionsTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -public class TaskGenerateTsDefinitionsTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - private File outputFolder; - private TaskGenerateTsDefinitions taskGenerateTsDefinitions; - - @Before - public void setUp() throws IOException { - outputFolder = temporaryFolder.newFolder(); - taskGenerateTsDefinitions = new TaskGenerateTsDefinitions(outputFolder); - } - - @Test - public void should_generateTsDefinitions_TsDefinitionsNotExistAndTsConfigExists() - throws Exception { - Files.createFile( - new File(outputFolder, TaskGenerateTsConfig.TSCONFIG_JSON) - .toPath()); - taskGenerateTsDefinitions.execute(); - Assert.assertFalse( - "Should generate types.d.ts when tsconfig.json exists and " - + "types.d.ts doesn't exist", - taskGenerateTsDefinitions.shouldGenerate()); - Assert.assertTrue("The generated types.d.ts should not exist", - taskGenerateTsDefinitions.getGeneratedFile().exists()); - Assert.assertEquals( - "The generated content should be equals the default content", - taskGenerateTsDefinitions.getFileContent(), - IOUtils.toString( - taskGenerateTsDefinitions.getGeneratedFile().toURI(), - StandardCharsets.UTF_8)); - } - - @Test - public void should_notGenerateTsDefinitions_TsConfigNotExist() - throws Exception { - Files.createFile(new File(outputFolder, "types.d.ts").toPath()); - taskGenerateTsDefinitions.execute(); - Assert.assertFalse( - "Should not generate types.d.ts when tsconfig.json " - + "doesn't exist", - taskGenerateTsDefinitions.shouldGenerate()); - Assert.assertTrue("The types.d.ts should already exist", - taskGenerateTsDefinitions.getGeneratedFile().exists()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateWebComponentBootstrapTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateWebComponentBootstrapTest.java deleted file mode 100644 index c81c92449c0..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateWebComponentBootstrapTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; - -import com.vaadin.flow.server.ExecutionFailedException; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.FRONTEND; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; - -public class TaskGenerateWebComponentBootstrapTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File frontendDirectory; - private File generatedImports; - private TaskGenerateWebComponentBootstrap taskGenerateWebComponentBootstrap; - - @Before - public void setup() throws Exception { - frontendDirectory = temporaryFolder.newFolder(DEFAULT_FRONTEND_DIR); - File generatedFolder = temporaryFolder.newFolder(TARGET, FRONTEND); - generatedImports = new File(generatedFolder, - "flow-generated-imports.js"); - generatedImports.createNewFile(); - taskGenerateWebComponentBootstrap = new TaskGenerateWebComponentBootstrap( - frontendDirectory, generatedImports); - } - - @Test - public void should_importGeneratedImports() - throws ExecutionFailedException { - taskGenerateWebComponentBootstrap.execute(); - String content = taskGenerateWebComponentBootstrap.getFileContent(); - Assert.assertTrue(content.contains( - "import '../../target/frontend/flow-generated-imports'")); - } - - @Test - public void should_importAndInitializeFlowClient() - throws ExecutionFailedException { - taskGenerateWebComponentBootstrap.execute(); - String content = taskGenerateWebComponentBootstrap.getFileContent(); - Assert.assertTrue(content.contains( - "import { init } from '" + FrontendUtils.JAR_RESOURCES_IMPORT - + "FlowClient';\n" + "init()")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateWebComponentHtmlTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateWebComponentHtmlTest.java deleted file mode 100644 index 56ed18a2c60..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskGenerateWebComponentHtmlTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import static com.vaadin.flow.server.frontend.FrontendUtils.WEB_COMPONENT_HTML; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class TaskGenerateWebComponentHtmlTest { - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File frontendFolder; - private TaskGenerateWebComponentHtml taskGenerateWebComponentHtml; - - @Before - public void setup() throws IOException { - frontendFolder = temporaryFolder.newFolder(); - taskGenerateWebComponentHtml = new TaskGenerateWebComponentHtml( - frontendFolder); - } - - @Test - public void should_loadCorrectContentOfDefaultFile() throws Exception { - String defaultContent = IOUtils.toString( - getClass().getResourceAsStream(WEB_COMPONENT_HTML), - StandardCharsets.UTF_8); - - Assert.assertEquals( - "Should load correct default content from web-component.html", - defaultContent, taskGenerateWebComponentHtml.getFileContent()); - } - - @Test - public void should_notOverwriteWebComponentHtml_webComponentHtmlExists() - throws Exception { - File webComponentHtml = new File(frontendFolder, "web-component.html"); - Files.createFile(webComponentHtml.toPath()); - taskGenerateWebComponentHtml.execute(); - Assert.assertFalse( - "Should not generate web-component.html while it exists in the frontend folder", - taskGenerateWebComponentHtml.shouldGenerate()); - Assert.assertEquals("", IOUtils.toString(webComponentHtml.toURI(), - StandardCharsets.UTF_8)); - } - - @Test - public void should_generateWebComponentHtml_webComponentHtmlNotExist() - throws Exception { - String defaultContent = IOUtils.toString( - getClass().getResourceAsStream(WEB_COMPONENT_HTML), - StandardCharsets.UTF_8); - Assert.assertTrue( - "Should generate web-component.html when it doesn't exists in the frontend folder", - taskGenerateWebComponentHtml.shouldGenerate()); - - taskGenerateWebComponentHtml.execute(); - - Assert.assertTrue("The generated file should exists", - taskGenerateWebComponentHtml.getGeneratedFile().exists()); - - Assert.assertEquals("Should have default content of web-component.html", - defaultContent, - IOUtils.toString( - taskGenerateWebComponentHtml.getGeneratedFile().toURI(), - StandardCharsets.UTF_8)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskInstallWebpackPluginsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskInstallWebpackPluginsTest.java deleted file mode 100644 index 5554acd10b8..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskInstallWebpackPluginsTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; - -import elemental.json.Json; -import elemental.json.JsonArray; -import elemental.json.JsonObject; -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEV_DEPENDENCIES; -import static com.vaadin.flow.server.frontend.WebpackPluginsUtil.PLUGIN_TARGET; -import static java.nio.charset.StandardCharsets.UTF_8; - -public class TaskInstallWebpackPluginsTest { - - public static final String BUILD_DIRECTORY = TARGET; - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File rootFolder; - - private TaskInstallWebpackPlugins task; - - @Before - public void init() throws IOException { - rootFolder = temporaryFolder.newFolder(); - task = new TaskInstallWebpackPlugins( - new File(rootFolder, BUILD_DIRECTORY)); - } - - @Test - public void getPluginsReturnsExpectedList() { - String[] expectedPlugins = new String[] { "application-theme-plugin", - "theme-loader", "theme-live-reload-plugin", - "build-status-plugin", "rollup-plugin-postcss-lit-custom" }; - final List plugins = WebpackPluginsUtil.getPlugins(); - Assert.assertEquals( - "Unexpected amount of plugins in 'webpack-plugins.json'", - expectedPlugins.length, plugins.size()); - - for (String plugin : expectedPlugins) { - Assert.assertTrue( - "'webpack-plugins.json' didn't contain '" + plugin + "'", - plugins.contains(plugin)); - } - } - - @Test - public void webpackPluginsAreCopied() throws IOException { - task.execute(); - - assertPlugins(); - } - - @Test - public void pluginsDefineAllScriptFiles() throws IOException { - for (String plugin : WebpackPluginsUtil.getPlugins()) { - verifyPluginScriptFilesAreDefined(plugin); - } - } - - @Test - public void pluginsNotAddedToPackageJson() throws IOException { - ClassFinder finder = Mockito.mock(ClassFinder.class); - NodeUpdater nodeUpdater = new NodeUpdater(finder, - Mockito.mock(FrontendDependencies.class), rootFolder, - new File(""), BUILD_DIRECTORY, - Mockito.mock(FeatureFlags.class)) { - - @Override - public void execute() { - } - }; - - task.execute(); - - final JsonObject packageJson = nodeUpdater.getPackageJson(); - - final JsonObject devDependencies = packageJson - .getObject(DEV_DEPENDENCIES); - for (String plugin : WebpackPluginsUtil.getPlugins()) { - Assert.assertFalse("Plugin " + plugin + " added to packageJson", - devDependencies.hasKey("@vaadin/" + plugin)); - } - } - - private void assertPlugins() throws IOException { - Assert.assertTrue("No @vaadin folder created", - Paths.get(rootFolder.toString(), BUILD_DIRECTORY, PLUGIN_TARGET) - .toFile().exists()); - for (String plugin : WebpackPluginsUtil.getPlugins()) { - assertPlugin(plugin); - } - } - - private void assertPlugin(String plugin) throws IOException { - final File pluginFolder = getPluginFolder(plugin); - - final JsonArray files = getPluginFiles(pluginFolder); - for (int i = 0; i < files.length(); i++) { - Assert.assertTrue( - "Missing plugin file " + files.getString(i) + " for " - + plugin, - new File(pluginFolder, files.getString(i)).exists()); - } - } - - private void verifyPluginScriptFilesAreDefined(String plugin) - throws IOException { - final File pluginFolder = new File(this.getClass().getClassLoader() - .getResource(PLUGIN_TARGET + "/" + plugin).getFile()); - - final JsonArray files = getPluginFiles(pluginFolder); - List fileNames = new ArrayList<>(files.length()); - for (int i = 0; i < files.length(); i++) { - Assert.assertTrue( - "Missing plugin file " + files.getString(i) + " for " - + plugin, - new File(pluginFolder, files.getString(i)).exists()); - fileNames.add(files.getString(i)); - } - final List pluginFiles = Arrays - .stream(pluginFolder.listFiles((dir, name) -> FilenameUtils - .getExtension(name).equals("js"))) - .map(file -> file.getName()).collect(Collectors.toList()); - for (String fileName : pluginFiles) { - Assert.assertTrue(String.format( - "Plugin '%s' doesn't define script file '%s' in package.json files", - plugin, fileName), fileNames.contains(fileName)); - } - } - - /** - * Get the expected plugin files from package.json - * - * @param pluginFolder - * @return - * @throws IOException - */ - private JsonArray getPluginFiles(File pluginFolder) throws IOException { - final JsonObject packageJson = Json.parse(FileUtils.readFileToString( - new File(pluginFolder, "package.json"), UTF_8)); - return packageJson.getArray("files"); - } - - private File getPluginFolder(String plugin) { - final String pluginString = Paths - .get(BUILD_DIRECTORY, PLUGIN_TARGET, plugin).toString(); - final File pluginFolder = new File(rootFolder, pluginString); - - Assert.assertTrue("Missing plugin folder for " + plugin, - pluginFolder.exists()); - Assert.assertTrue("Missing package.json for " + plugin, - new File(pluginFolder, "package.json").exists()); - return pluginFolder; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunNpmInstallTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunNpmInstallTest.java deleted file mode 100644 index 3bd1b759217..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunNpmInstallTest.java +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import static com.vaadin.flow.server.Constants.PACKAGE_JSON; -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEPENDENCIES; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEV_DEPENDENCIES; -import static com.vaadin.flow.server.frontend.NodeUpdater.HASH_KEY; -import static com.vaadin.flow.server.frontend.NodeUpdater.PROJECT_FOLDER; -import static com.vaadin.flow.server.frontend.NodeUpdater.VAADIN_DEP_KEY; -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.server.frontend.installer.NodeInstaller; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; -import com.vaadin.flow.testcategory.SlowTests; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import elemental.json.Json; -import elemental.json.JsonObject; -import net.jcip.annotations.NotThreadSafe; -import org.slf4j.event.Level; - -@NotThreadSafe -@Category(SlowTests.class) -public class TaskRunNpmInstallTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private NodeUpdater nodeUpdater; - - private TaskRunNpmInstall task; - - protected File npmFolder; - - protected ClassFinder finder; - - private Logger logger = Mockito - .spy(LoggerFactory.getLogger(NodeUpdater.class)); - protected File generatedPath; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Before - public void setUp() throws IOException { - npmFolder = temporaryFolder.newFolder(); - generatedPath = new File(npmFolder, "generated"); - generatedPath.mkdir(); - finder = Mockito.mock(ClassFinder.class); - nodeUpdater = new NodeUpdater(finder, - Mockito.mock(FrontendDependencies.class), npmFolder, - generatedPath, TARGET, Mockito.mock(FeatureFlags.class)) { - - @Override - public void execute() { - } - - @Override - Logger log() { - return logger; - } - - }; - task = createTask(new ArrayList<>()); - } - - protected TaskRunNpmInstall createTask(List additionalPostInstall) { - return new TaskRunNpmInstall(getNodeUpdater(), false, false, - FrontendTools.DEFAULT_NODE_VERSION, - URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT), false, - false, additionalPostInstall); - } - - @Test - public void runNpmInstall_emptyDir_npmInstallIsExecuted() - throws ExecutionFailedException, IOException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - getNodeUpdater().modified = false; - - ensurePackageJson(); - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - @Test - public void runNpmInstall_nodeModulesContainsStaging_npmInstallIsExecuted() - throws ExecutionFailedException, IOException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - File staging = new File(nodeModules, ".staging"); - staging.mkdir(); - getNodeUpdater().modified = false; - ensurePackageJson(); - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - @Test - public void runNpmInstall_toolIsChanged_nodeModulesIsRemoved() - throws ExecutionFailedException, IOException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - - ensurePackageJson(); - - getNodeUpdater().modified = true; - File yaml = new File(nodeModules, ".modules.yaml"); - yaml.createNewFile(); - task.execute(); - - Assert.assertFalse(yaml.exists()); - } - - @Test - public void runNpmInstall_toolIsNotChanged_nodeModulesIsNotRemoved() - throws ExecutionFailedException, IOException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - - getNodeUpdater().modified = true; - File fakeFile = new File(nodeModules, ".fake.file"); - fakeFile.createNewFile(); - ensurePackageJson(); - task.execute(); - - Assert.assertTrue(fakeFile.exists()); - } - - @Test - public void runNpmInstall_nonEmptyDirNoLocalHash_npmInstallIsExecuted() - throws IOException, ExecutionFailedException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - new File(nodeModules, "foo").createNewFile(); - getNodeUpdater().modified = false; - ensurePackageJson(); - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - @Test - public void runNpmInstall_nonEmptyDirNoHashMatch_npmInstallIsExecuted() - throws IOException, ExecutionFailedException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - new File(nodeModules, "foo").createNewFile(); - writeLocalHash("faulty"); - getNodeUpdater().modified = false; - - ensurePackageJson(); - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - @Test - public void runNpmInstall_matchingHash_npmInstallIsNotExecuted() - throws IOException, ExecutionFailedException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - - new File(nodeModules, "foo").createNewFile(); - - writeLocalHash(""); - getNodeUpdater().modified = false; - task.execute(); - - ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - Mockito.verify(logger).info(captor.capture(), - Mockito.matches(getToolName()), - Mockito.matches(nodeModules.getAbsolutePath().replaceAll("\\\\", - "\\\\\\\\")), - Mockito.any(), Mockito.matches(Constants.PACKAGE_JSON)); - Assert.assertEquals( - "Skipping `{} install` because the frontend packages are already installed in the folder '{}' and the hash in the file '{}' is the same as in '{}'", - captor.getValue()); - } - - @Test - public void runNpmInstall_matchingHashButEmptyModules_npmInstallIsExecuted() - throws IOException, ExecutionFailedException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - - writeLocalHash(""); - getNodeUpdater().modified = false; - ensurePackageJson(); - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - public void writeLocalHash(String hash) throws IOException { - final JsonObject localHash = Json.createObject(); - localHash.put(HASH_KEY, hash); - - final File localHashFile = new File(getNodeUpdater().nodeModulesFolder, - ".vaadin/vaadin.json"); - FileUtils.forceMkdirParent(localHashFile); - getNodeUpdater().writePackageFile(localHash, localHashFile); - } - - @Test - public void runNpmInstall_modified_npmInstallIsExecuted() - throws ExecutionFailedException, IOException { - getNodeUpdater().modified = true; - ensurePackageJson(); - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - @Test - public void runNpmInstall_vaadinHomeNodeIsAFolder_throws() - throws IOException, ExecutionFailedException { - exception.expectMessage( - "it's either not a file or not a 'node' executable."); - assertRunNpmInstallThrows_vaadinHomeNodeIsAFolder( - new TaskRunNpmInstall(getNodeUpdater(), false, true, - FrontendTools.DEFAULT_NODE_VERSION, - URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT), - false, false, new ArrayList<>())); - } - - @Test - public void runNpmInstall_externalUpdateOfPackages_npmInstallIsRerun() - throws ExecutionFailedException, IOException { - getNodeUpdater().modified = true; - - // manually fake TaskUpdatePackages. - JsonObject packageJson = getNodeUpdater().getPackageJson(); - updatePackageHash(packageJson); - getNodeUpdater().writePackageFile(packageJson); - - task.execute(); - - final File localHashFile = new File(getNodeUpdater().nodeModulesFolder, - ".vaadin/vaadin.json"); - Assert.assertTrue("Local has file was not created after install.", - localHashFile.exists()); - - String fileContent = FileUtils.readFileToString(localHashFile, - UTF_8.name()); - JsonObject localHash = Json.parse(fileContent); - Assert.assertNotEquals("We should have a non empty hash key", "", - localHash.getString(HASH_KEY)); - - // Update package json and hash as if someone had pushed to code repo. - packageJson = getNodeUpdater().getPackageJson(); - packageJson.getObject(VAADIN_DEP_KEY).getObject(DEPENDENCIES) - .put("a-avataaar", "^1.2.5"); - String hash = packageJson.getObject(VAADIN_DEP_KEY).getString(HASH_KEY); - updatePackageHash(packageJson); - - Assert.assertNotEquals("Hash should have been updated", hash, - packageJson.getObject(VAADIN_DEP_KEY).getString(HASH_KEY)); - - getNodeUpdater().writePackageFile(packageJson); - logger = Mockito.mock(Logger.class); - - task.execute(); - - Mockito.verify(logger).info(getRunningMsg()); - } - - protected void setupEsbuildAndFooInstallation() throws IOException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - nodeModules.mkdir(); - getNodeUpdater().modified = false; - - // Fake that we have installed "esbuild" - File esbuildPackageJson = new File( - new File(nodeModules.getParentFile(), "fake-esbuild"), - "package.json"); - String esbuildPackageJsonContents = IOUtils.toString( - getClass().getResourceAsStream( - "fake-package-with-postinstall.json"), - StandardCharsets.UTF_8); - FileUtils.write(esbuildPackageJson, esbuildPackageJsonContents, - StandardCharsets.UTF_8); - - // Fake that we have installed "foo" - File fooPackageJson = new File( - new File(nodeModules.getParentFile(), "fake-foo"), - "package.json"); - String fooPackageJsonContents = IOUtils.toString( - getClass().getResourceAsStream( - "fake-package-with-postinstall.json"), - StandardCharsets.UTF_8); - FileUtils.write(fooPackageJson, fooPackageJsonContents, - StandardCharsets.UTF_8); - - File packageJsonFile = ensurePackageJson(); - JsonObject packageJson = getNodeUpdater().getPackageJson(); - packageJson.getObject(DEV_DEPENDENCIES).put("esbuild", - "./fake-esbuild"); - packageJson.getObject(DEV_DEPENDENCIES).put("foo", "./fake-foo"); - FileUtils.write(packageJsonFile, packageJson.toJson(), - StandardCharsets.UTF_8); - - } - - @Test - public void runNpmInstall_noPostinstallScript_postIntstallNotExecuted() - throws IOException, ExecutionFailedException { - setupEsbuildAndFooInstallation(); - - // Remove postinstall script from "esbuild" - File esbuildPackageJson = new File( - new File(getNodeUpdater().nodeModulesFolder.getParentFile(), - "fake-esbuild"), - "package.json"); - JsonObject esbuildPackageJsonContents = Json.parse(IOUtils.toString( - getClass().getResourceAsStream( - "fake-package-with-postinstall.json"), - StandardCharsets.UTF_8)); - esbuildPackageJsonContents.getObject("scripts").remove("postinstall"); - FileUtils.write(esbuildPackageJson, esbuildPackageJsonContents.toJson(), - StandardCharsets.UTF_8); - - logger = new MockLogger(); - Assert.assertTrue(logger.isDebugEnabled()); - task.execute(); - - Assert.assertFalse( - "esbuild without postinstall should not have been executed", - ((MockLogger) logger).getLogs() - .contains("Running postinstall for 'esbuild'")); - } - - @Test - public void runNpmInstall_postInstall_runOnlyForDefaultPackages() - throws ExecutionFailedException, IOException { - setupEsbuildAndFooInstallation(); - task.execute(); - - Assert.assertTrue("Postinstall for 'esbuild' was not run", - new File( - new File(getNodeUpdater().nodeModulesFolder, "esbuild"), - "postinstall-file.txt").exists()); - Assert.assertFalse("Postinstall for 'foo' should not have been run", - new File(new File(getNodeUpdater().nodeModulesFolder, "foo"), - "postinstall-file.txt").exists()); - } - - @Test - public void runNpmInstall_postInstall_runForDefinedAdditionalPackages() - throws ExecutionFailedException, IOException { - setupEsbuildAndFooInstallation(); - task = createTask(Collections.singletonList("foo")); - task.execute(); - - Assert.assertTrue("Postinstall for 'esbuild' was not run", - new File( - new File(getNodeUpdater().nodeModulesFolder, "esbuild"), - "postinstall-file.txt").exists()); - Assert.assertTrue("Postinstall for 'foo' was not run", - new File(new File(getNodeUpdater().nodeModulesFolder, "foo"), - "postinstall-file.txt").exists()); - } - - @Test - public void shouldRunNpmInstallWhenFolderChanges() throws Exception { - setupEsbuildAndFooInstallation(); - - String packageJsonHash = getNodeUpdater().getPackageJson() - .getObject(VAADIN_DEP_KEY).getString(HASH_KEY); - JsonObject vaadinJson = Json.createObject(); - vaadinJson.put(HASH_KEY, packageJsonHash); - vaadinJson.put(PROJECT_FOLDER, - getNodeUpdater().npmFolder.getAbsolutePath()); - File vaadinJsonFile = getNodeUpdater().getVaadinJsonFile(); - - FileUtils.writeStringToFile(vaadinJsonFile, vaadinJson.toJson(), UTF_8); - - Assert.assertFalse(task.isVaadinHashOrProjectFolderUpdated()); - vaadinJson.put(PROJECT_FOLDER, - getNodeUpdater().npmFolder.getAbsolutePath() + "foo"); - FileUtils.writeStringToFile(vaadinJsonFile, vaadinJson.toJson(), UTF_8); - Assert.assertTrue(task.isVaadinHashOrProjectFolderUpdated()); - } - - /** - * Update the vaadin package hash to match dependencies. The hash is - * calculated from dependencies and devDependencies but not from the vaadin - * object. We copy the vaadin object dependencies and calculate the hash, - * then we remove the dependencies and devDependencies to not have to - * install anything for the test to keep the running time in ~1.4s instead - * of ~50s - * - * @param packageJson - * package.json json object - */ - public void updatePackageHash(JsonObject packageJson) { - final JsonObject vaadinDep = packageJson.getObject(VAADIN_DEP_KEY) - .getObject(DEPENDENCIES); - JsonObject dependencies = Json.createObject(); - for (String key : vaadinDep.keys()) { - dependencies.put(key, vaadinDep.getString(key)); - } - JsonObject vaadinDevDep = packageJson.getObject(VAADIN_DEP_KEY) - .getObject(DEV_DEPENDENCIES); - JsonObject devDependencies = Json.createObject(); - for (String key : vaadinDevDep.keys()) { - devDependencies.put(key, vaadinDevDep.getString(key)); - } - packageJson.put(DEPENDENCIES, dependencies); - packageJson.put(DEV_DEPENDENCIES, devDependencies); - packageJson.getObject(VAADIN_DEP_KEY).put(HASH_KEY, - TaskUpdatePackages.generatePackageJsonHash(packageJson)); - packageJson.remove(DEPENDENCIES); - packageJson.remove(DEV_DEPENDENCIES); - } - - protected void assertRunNpmInstallThrows_vaadinHomeNodeIsAFolder( - TaskRunNpmInstall task) - throws IOException, ExecutionFailedException { - String userHome = "user.home"; - String originalHome = System.getProperty(userHome); - File home = temporaryFolder.newFolder(); - System.setProperty(userHome, home.getPath()); - try { - File homeDir = new File(home, ".vaadin"); - File node = new File(homeDir, - FrontendUtils.isWindows() ? "node/node.exe" : "node/node"); - FileUtils.forceMkdir(node); - - task.execute(); - } finally { - System.setProperty(userHome, originalHome); - } - } - - private String getRunningMsg() { - return "Running `" + getToolName() + " install` to " - + "resolve and optionally download frontend dependencies. " - + "This may take a moment, please stand by..."; - } - - protected NodeUpdater getNodeUpdater() { - return nodeUpdater; - } - - protected ClassFinder getClassFinder() { - return finder; - } - - protected String getToolName() { - return "npm"; - } - - private File ensurePackageJson() throws IOException { - File file = new File(npmFolder, PACKAGE_JSON); - if (!file.exists()) { - JsonObject packageJson = getNodeUpdater().getPackageJson(); - getNodeUpdater().writePackageFile(packageJson); - } - return file; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java index a84f508c7cd..9e502451a7b 100644 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java +++ b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskRunPnpmInstallTest.java @@ -17,706 +17,259 @@ import static com.vaadin.flow.server.Constants.PACKAGE_JSON; import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.testutil.FrontendStubs.createStubNode; +import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; +import java.io.InputStreamReader; import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Assume; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.Constants; import com.vaadin.flow.server.ExecutionFailedException; import com.vaadin.flow.server.frontend.installer.NodeInstaller; import com.vaadin.flow.server.frontend.scanner.ClassFinder; import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; -import com.vaadin.flow.testcategory.SlowTests; -import com.vaadin.flow.testutil.FrontendStubs; - -import elemental.json.Json; -import elemental.json.JsonObject; - -@Category(SlowTests.class) -public class TaskRunPnpmInstallTest extends TaskRunNpmInstallTest { - - private static final String PINNED_VERSION = "3.2.17"; - private static final List POSTINSTALL_PACKAGES = Collections - .singletonList("esbuild"); - - @Override - @Before - public void setUp() throws IOException { - super.setUp(); - - // create an empty package.json so as pnpm can be run without - // error - FileUtils.write(new File(getNodeUpdater().npmFolder, PACKAGE_JSON), - "{}", StandardCharsets.UTF_8); - } - - @Test - public void runPnpmInstall_overlayVersionIsPinnedViaPlatform_installedOverlayVersionIsSpecifiedByPlatform() - throws IOException, ExecutionFailedException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file: dialog doesn't pin its Overlay - // version which - // is transitive dependency. - FileUtils.write(packageJson, - "{\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.2.1\"}}", - StandardCharsets.UTF_8); - - // Platform defines a pinned version - TaskRunNpmInstall task = createTask( - "{ \"@vaadin/vaadin-overlay\":\"" + PINNED_VERSION + "\"}"); - task.execute(); - - File overlayPackageJson = new File(getNodeUpdater().nodeModulesFolder, - "@vaadin/vaadin-overlay/package.json"); - - // The resulting version should be the one specified via - // platform - // versions file - JsonObject overlayPackage = Json.parse(FileUtils - .readFileToString(overlayPackageJson, StandardCharsets.UTF_8)); - Assert.assertEquals(PINNED_VERSION, - overlayPackage.getString("version")); - } - - @Override - @Test - public void runNpmInstall_toolIsChanged_nodeModulesIsRemoved() - throws ExecutionFailedException, IOException { - File nodeModules = getNodeUpdater().nodeModulesFolder; - FileUtils.forceMkdir(nodeModules); - - // create a fake file in the node modules dir to check that it's - // removed - File fakeFile = new File(nodeModules, ".fake.file"); - fakeFile.createNewFile(); - - getNodeUpdater().modified = true; - createTask().execute(); - - Assert.assertFalse(fakeFile.exists()); - } - - @Override - @Test - public void runNpmInstall_toolIsNotChanged_nodeModulesIsNotRemoved() - throws ExecutionFailedException, IOException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // create some package.json file so pnpm does some installation - // into - // node_modules folder - FileUtils.write(packageJson, - "{\"dependencies\": {" + "\"pnpm\": \"5.15.1\"}}", - StandardCharsets.UTF_8); - - getNodeUpdater().modified = true; - createTask().execute(); - - // create a fake file in the node modules dir to check that it's - // removed - File fakeFile = new File(getNodeUpdater().nodeModulesFolder, - ".fake.file"); - fakeFile.createNewFile(); - - getNodeUpdater().modified = true; - createTask().execute(); - - Assert.assertTrue(fakeFile.exists()); - } - - @Override - public void runNpmInstall_vaadinHomeNodeIsAFolder_throws() - throws IOException, ExecutionFailedException { - exception.expectMessage( - "it's either not a file or not a 'node' executable."); - assertRunNpmInstallThrows_vaadinHomeNodeIsAFolder( - new TaskRunNpmInstall(getNodeUpdater(), true, true, - FrontendTools.DEFAULT_NODE_VERSION, - URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT), - false, false, POSTINSTALL_PACKAGES)); - } - - @Test - public void runPnpmInstall_versionsJsonIsFound_pnpmHookFileIsGenerated() - throws IOException, ExecutionFailedException { - ClassFinder classFinder = getClassFinder(); - File versions = temporaryFolder.newFile(); - FileUtils.write(versions, "{}", StandardCharsets.UTF_8); - Mockito.when( - classFinder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versions.toURI().toURL()); - - TaskRunNpmInstall task = createTask(); - getNodeUpdater().modified = true; - getNodeUpdater().versionsPath = "./versions.json"; - task.execute(); - - File file = new File(getNodeUpdater().npmFolder, "pnpmfile.js"); - File cjsFile = new File(getNodeUpdater().npmFolder, ".pnpmfile.cjs"); - Assert.assertTrue(file.exists() || cjsFile.exists()); - String content; - if (file.exists()) { - content = FileUtils.readFileToString(file, StandardCharsets.UTF_8); - } else { - content = FileUtils.readFileToString(cjsFile, - StandardCharsets.UTF_8); + +public class TaskRunPnpmInstallTest { + + protected NodeUpdater nodeUpdater; + + protected File npmFolder; + + protected ClassFinder finder; + + protected File generatedPath; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void setUp() throws IOException { + npmFolder = temporaryFolder.newFolder(); + generatedPath = new File(npmFolder, "generated"); + generatedPath.mkdir(); + finder = Mockito.mock(ClassFinder.class); + nodeUpdater = new NodeUpdater(finder, + Mockito.mock(FrontendDependencies.class), npmFolder, + generatedPath, TARGET, Mockito.mock(FeatureFlags.class)) { + + @Override + public void execute() { + } + + @Override + Logger log() { + return LoggerFactory.getLogger(getClass()); + } + + }; } - MatcherAssert.assertThat(content, - CoreMatchers.containsString("JSON.parse(fs.readFileSync")); - } - - @Test - public void runPnpmInstall_versionsJsonIsNotFound_pnpmHookFileIsGeneratedFromPackageJson() - throws IOException, ExecutionFailedException { - TaskRunNpmInstall task = createTask(); - getNodeUpdater().modified = true; - getNodeUpdater().versionsPath = "./versions.json"; - task.execute(); - - File file = new File(getNodeUpdater().npmFolder, "pnpmfile.js"); - File cjsFile = new File(getNodeUpdater().npmFolder, ".pnpmfile.cjs"); - Assert.assertTrue(file.exists() || cjsFile.exists()); - String content; - if (file.exists()) { - content = FileUtils.readFileToString(file, StandardCharsets.UTF_8); - } else { - content = FileUtils.readFileToString(cjsFile, - StandardCharsets.UTF_8); + + @Test + public void a1() throws Exception { + tst(); } - MatcherAssert.assertThat(content, - CoreMatchers.containsString("JSON.parse(fs.readFileSync")); - } - - @Test - public void generateVersionsJson_userHasNoCustomVersions_platformIsMergedWithDevDeps() - throws IOException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - FileUtils.write(packageJson, "{}", StandardCharsets.UTF_8); - - File versions = temporaryFolder.newFile(); - // Platform defines a pinned version - // @formatter:off - FileUtils.write(versions, String.format( - "{" - + "\"vaadin-overlay\": {" - + "\"npmName\": \"@vaadin/vaadin-overlay\"," - + "\"jsVersion\": \"%s\"" - + "}" - + "}", PINNED_VERSION), StandardCharsets.UTF_8); - // @formatter:on - - JsonObject object = getGeneratedVersionsContent(versions, packageJson); - Assert.assertTrue(object.hasKey("@vaadin/vaadin-overlay")); - - // Platform version takes precedence over dev deps - Assert.assertEquals(PINNED_VERSION, - object.getString("@vaadin/vaadin-overlay")); - } - - @Test - public void generateVersionsJson_userVersionNewerThanPinned_intalledOverlayVersionIsUserVersion() - throws IOException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - final String customOverlayVersion = "3.3.0"; - // @formatter:off - FileUtils.write(packageJson, - "{" - + "\"vaadin\": {" - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + PINNED_VERSION + "\"" - - + "}," - + "\"devDependencies\": {" - + "\"@vaadin/vaadin-notification\": \"1.3.9\"" - + "}," - + "}," - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + customOverlayVersion + "\"" - + "}," - + "\"devDependencies\": {" - + "\"@vaadin/vaadin-notification\": \"1.4.0\"" - + "}," - + "}", - StandardCharsets.UTF_8); - // @formatter:on - - File versions = temporaryFolder.newFile(); - // Platform defines a pinned version - // @formatter:off - FileUtils.write(versions, String.format( - "{" - + "\"vaadin-overlay\": {" - + "\"npmName\": \"@vaadin/vaadin-overlay\"," - + "\"jsVersion\": \"%s\"" - + "}" - + "}", PINNED_VERSION), StandardCharsets.UTF_8); - // @formatter:on - - JsonObject versionsJson = getGeneratedVersionsContent(versions, - packageJson); - Assert.assertEquals( - "Generated versions json should have keys for each dependency", - 3, versionsJson.keys().length); - Assert.assertEquals("Overlay should be pinned to user version", - customOverlayVersion, - versionsJson.getString("@vaadin/vaadin-overlay")); - } - - @Test - public void generateVersionsJson_userVersionOlderThanPinned_installedOverlayPinnedVersionIsUserVersion() - throws IOException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - final String customOverlayVersion = "3.1.0"; - - // @formatter:off - FileUtils.write(packageJson, - "{" - + "\"vaadin\": {" - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + PINNED_VERSION + "\"" - + "}," - + "\"devDependencies\": {" - + "\"@vaadin/vaadin-notification\": \"1.4.0\"" - + "}," - + "}," - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + customOverlayVersion + "\"" - + "}," - + "\"devDependencies\": {" - + "\"@vaadin/vaadin-notification\": \"1.3.9\"" - + "}," - + "}", - StandardCharsets.UTF_8); - // @formatter:on - - File versions = temporaryFolder.newFile(); - // Platform defines a pinned version - // @formatter:off - FileUtils.write(versions,String.format( - "{" - + "\"vaadin-overlay\": {" - + "\"npmName\": \"@vaadin/vaadin-overlay\"," - + "\"jsVersion\": \"%s\"" - + "}" - + "}", PINNED_VERSION), StandardCharsets.UTF_8); - // @formatter:on - - JsonObject versionsJson = getGeneratedVersionsContent(versions, - packageJson); - Assert.assertEquals( - "Generated versions json should have keys for package.json dependencies (also dev)", - 3, versionsJson.keys().length); - Assert.assertEquals("Overlay should be pinned to user version", - customOverlayVersion, - versionsJson.getString("@vaadin/vaadin-overlay")); - } - - @Test - public void generateVersionsJson_userDefinedVersions_versionOnlyPinnedForNotAddedDependencies() - throws IOException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - String loginVersion = "1.1.0-alpha1"; - String menuVersion = "1.1.0-alpha2"; - String notificationVersion = "1.4.0"; - String uploadVersion = "4.2.0"; - // @formatter:off - FileUtils.write(packageJson, String.format( - "{" - + "\"vaadin\": {" - + "\"dependencies\": {" - + "\"@vaadin/vaadin-login\": \"%s\"," - + "\"@vaadin/vaadin-menu-bar\": \"%s\"," - + "\"@vaadin/vaadin-notification\": \"%s\"," - + "\"@vaadin/vaadin-upload\": \"%s\"" - + "}" - + "}," - + "\"dependencies\": {" - + "\"@vaadin/vaadin-login\": \"%s\"," - + "\"@vaadin/vaadin-menu-bar\": \"%s\"," - + "\"@vaadin/vaadin-notification\": \"%s\"," - + "\"@vaadin/vaadin-upload\": \"%s\"" - + "}" - + "}", - loginVersion, "1.0.0", notificationVersion, - "4.0.0", loginVersion, menuVersion, notificationVersion, - uploadVersion), StandardCharsets.UTF_8); - // @formatter:on - // Platform defines a pinned version - - String versionsLoginVersion = "1.1.0-alpha1"; - String versionsMenuBarVersion = "1.1.0-alpha1"; - String versionsNotificationVersion = "1.5.0-alpha1"; - String versionsUploadVersion = "4.2.0-beta2"; - - File versions = temporaryFolder.newFile(); - // @formatter:off - FileUtils.write(versions,String.format( - "{" - + "\"vaadin-login\": {" - + "\"npmName\": \"@vaadin/vaadin-login\"," - + "\"jsVersion\": \"%s\"" - + "}," - + "\"vaadin-menu-bar\": {" - + "\"npmName\": \"@vaadin/vaadin-menu-bar\"," - + "\"jsVersion\": \"%s\"" - + "}," - + "\"vaadin-notification\": {" - + "\"npmName\": \"@vaadin/vaadin-notification\"," - + "\"jsVersion\": \"%s\"" - + "}," - + "\"vaadin-upload\": {" - + "\"npmName\": \"@vaadin/vaadin-upload\"," - + "\"jsVersion\": \"%s\"" - + "}" - + "}", - versionsLoginVersion, versionsMenuBarVersion, - versionsNotificationVersion, versionsUploadVersion), StandardCharsets.UTF_8); - // @formatter:on - - JsonObject generatedVersions = getGeneratedVersionsContent(versions, - packageJson); - - Assert.assertEquals("Login version is the same for user and platform.", - loginVersion, - generatedVersions.getString("@vaadin/vaadin-login")); - Assert.assertEquals("Menu Bar should be pinned to user version.", - menuVersion, - generatedVersions.getString("@vaadin/vaadin-menu-bar")); - Assert.assertEquals("Notification version should use platform", - versionsNotificationVersion, - generatedVersions.getString("@vaadin/vaadin-notification")); - Assert.assertEquals("Upload should be pinned to user version.", - uploadVersion, - generatedVersions.getString("@vaadin/vaadin-upload")); - } - - @Test - public void runPnpmInstall_npmRcFileNotFound_newNpmRcFileIsGenerated() - throws IOException, ExecutionFailedException { - TaskRunNpmInstall task = createTask(); - task.execute(); - - File npmRcFile = new File(getNodeUpdater().npmFolder, ".npmrc"); - Assert.assertTrue(npmRcFile.exists()); - String content = FileUtils.readFileToString(npmRcFile, - StandardCharsets.UTF_8); - Assert.assertTrue(content.contains("shamefully-hoist")); - } - - @Test - public void runPnpmInstall_npmRcFileGeneratedByVaadinFound_npmRcFileIsGenerated() - throws IOException, ExecutionFailedException { - File oldNpmRcFile = new File(getNodeUpdater().npmFolder, ".npmrc"); - // @formatter:off - String originalContent = "# NOTICE: this is an auto-generated file\n" - + "shamefully-hoist=true\n" - + "symlink=true\n"; - // @formatter:on - FileUtils.writeStringToFile(oldNpmRcFile, originalContent, - StandardCharsets.UTF_8); - - TaskRunNpmInstall task = createTask(); - task.execute(); - - File newNpmRcFile = new File(getNodeUpdater().npmFolder, ".npmrc"); - Assert.assertTrue(newNpmRcFile.exists()); - String content = FileUtils.readFileToString(newNpmRcFile, - StandardCharsets.UTF_8); - Assert.assertTrue(content.contains("shamefully-hoist")); - Assert.assertFalse(content.contains("symlink=true")); - } - - @Test - public void runPnpmInstall_customNpmRcFileFound_npmRcFileIsNotGenerated() - throws IOException, ExecutionFailedException { - File oldNpmRcFile = new File(getNodeUpdater().npmFolder, ".npmrc"); - // @formatter:off - String originalContent = "# A custom npmrc file for my project\n" - + "symlink=true\n"; - // @formatter:on - FileUtils.writeStringToFile(oldNpmRcFile, originalContent, - StandardCharsets.UTF_8); - - TaskRunNpmInstall task = createTask(); - task.execute(); - - File newNpmRcFile = new File(getNodeUpdater().npmFolder, ".npmrc"); - Assert.assertTrue(newNpmRcFile.exists()); - String content = FileUtils.readFileToString(newNpmRcFile, - StandardCharsets.UTF_8); - Assert.assertEquals(originalContent, content); - } - - @Test - public void runPnpmInstall_userVersionNewerThanPinned_installedOverlayVersionIsNotSpecifiedByPlatform() - throws IOException, ExecutionFailedException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - final String customOverlayVersion = "3.3.0"; - // @formatter:off - final String packageJsonContent = - "{" - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + customOverlayVersion + "\"" - + "}" - + "}"; - // @formatter:on - FileUtils.write(packageJson, packageJsonContent, - StandardCharsets.UTF_8); - - final VersionsJsonFilter versionsJsonFilter = new VersionsJsonFilter( - Json.parse(packageJsonContent), NodeUpdater.DEPENDENCIES); - // Platform defines a pinned version - TaskRunNpmInstall task = createTask(versionsJsonFilter - .getFilteredVersions( - Json.parse("{ \"@vaadin/vaadin-overlay\":\"" - + PINNED_VERSION + "\"}"), - "test-versions.json") - .toJson()); - task.execute(); - - File overlayPackageJson = new File(getNodeUpdater().nodeModulesFolder, - "@vaadin/vaadin-overlay/package.json"); - - // The resulting version should be the one specified by the user - JsonObject overlayPackage = Json.parse(FileUtils - .readFileToString(overlayPackageJson, StandardCharsets.UTF_8)); - Assert.assertEquals(customOverlayVersion, - overlayPackage.getString("version")); - } - - @Test - public void runPnpmInstall_frameworkCollectedVersionNewerThanPinned_installedOverlayVersionIsNotSpecifiedByPlatform() - throws IOException, ExecutionFailedException { - File packageJson = new File(getNodeUpdater().npmFolder, PACKAGE_JSON); - packageJson.createNewFile(); - - // Write package json file - final String customOverlayVersion = "3.3.0"; - // @formatter:off - final String packageJsonContent = - "{" - + "\"vaadin\": {" - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + customOverlayVersion + "\"" - + "}" - + "}," - + "\"dependencies\": {" - + "\"@vaadin/vaadin-dialog\": \"2.3.0\"," - + "\"@vaadin/vaadin-overlay\": \"" + customOverlayVersion + "\"" - + "}" - + "}"; - // @formatter:on - - FileUtils.write(packageJson, packageJsonContent, - StandardCharsets.UTF_8); - - final VersionsJsonFilter versionsJsonFilter = new VersionsJsonFilter( - Json.parse(packageJsonContent), NodeUpdater.DEPENDENCIES); - // Platform defines a pinned version - TaskRunNpmInstall task = createTask(versionsJsonFilter - .getFilteredVersions( - Json.parse("{ \"@vaadin/vaadin-overlay\":\"" - + PINNED_VERSION + "\"}"), - "test-versions.json") - .toJson()); - task.execute(); - - File overlayPackageJson = new File(getNodeUpdater().nodeModulesFolder, - "@vaadin/vaadin-overlay/package.json"); - - // The resulting version should be the one collected from the - // annotations in the project - JsonObject overlayPackage = Json.parse(FileUtils - .readFileToString(overlayPackageJson, StandardCharsets.UTF_8)); - Assert.assertEquals(customOverlayVersion, - overlayPackage.getString("version")); - } - - @Test - public void runPnpmInstall_checkFolderIsAcceptableByNpm_throwsOnWindows() - throws ExecutionFailedException, IOException { - Assume.assumeTrue("This test is only for Windows, since the issue with " - + "whitespaces in npm processed directories reproduces only on " - + "Windows", FrontendUtils.isWindows()); - - // given - File npmCacheFolder = temporaryFolder.newFolder("Foo Bar"); - FrontendStubs.ToolStubInfo nodeStub = FrontendStubs.ToolStubInfo.none(); - FrontendStubs.ToolStubInfo npmStub = FrontendStubs.ToolStubInfo - .builder(FrontendStubs.Tool.NPM).withVersion("6.0.0") - .withCacheDir(npmCacheFolder.getAbsolutePath()).build(); - createStubNode(nodeStub, npmStub, - getNodeUpdater().npmFolder.getAbsolutePath()); - - exception.expect(ExecutionFailedException.class); - exception.expectMessage(CoreMatchers.containsString( - "The path to npm cache contains whitespaces, and the currently installed npm version doesn't accept this.")); - - TaskRunNpmInstall task = createTask(); - getNodeUpdater().modified = true; - - // when - task.execute(); - - // then exception is thrown - } - - @Test - public void runPnpmInstall_postInstall_runOnlyForDefaultPackages() - throws ExecutionFailedException, IOException { - setupEsbuildAndFooInstallation(); - TaskRunNpmInstall task = createTask(); - task.execute(); - - Assert.assertTrue("Postinstall for 'esbuild' was not run", - new File( - new File(getNodeUpdater().nodeModulesFolder, "esbuild"), - "postinstall-file.txt").exists()); - Assert.assertFalse("Postinstall for 'foo' should not have been run", - new File(new File(getNodeUpdater().nodeModulesFolder, "foo"), - "postinstall-file.txt").exists()); - } - - @Test - public void runPnpmInstall_postInstall_runForDefinedAdditionalPackages() - throws ExecutionFailedException, IOException { - setupEsbuildAndFooInstallation(); - TaskRunNpmInstall task = createTask(Collections.singletonList("foo")); - task.execute(); - - Assert.assertTrue("Postinstall for 'esbuild' was not run", - new File( - new File(getNodeUpdater().nodeModulesFolder, "esbuild"), - "postinstall-file.txt").exists()); - Assert.assertTrue("Postinstall for 'foo' was not run", - new File(new File(getNodeUpdater().nodeModulesFolder, "foo"), - "postinstall-file.txt").exists()); - } - - @Override - protected String getToolName() { - return "pnpm"; - } - - protected TaskRunNpmInstall createTask() { - return createTask(new ArrayList<>()); - } - - @Override - protected TaskRunNpmInstall createTask(List additionalPostInstall) { - return new TaskRunNpmInstall(getNodeUpdater(), true, false, - FrontendTools.DEFAULT_NODE_VERSION, - URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT), false, - false, additionalPostInstall); - } - - protected TaskRunNpmInstall createTask(String versionsContent) { - return new TaskRunNpmInstall(createAndRunNodeUpdater(versionsContent), - true, false, FrontendTools.DEFAULT_NODE_VERSION, - URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT), false, - false, new ArrayList<>()); - } - - private JsonObject getGeneratedVersionsContent(File versions, - File packageJsonFile) throws IOException { - ClassFinder classFinder = getClassFinder(); - Mockito.when( - classFinder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versions.toURI().toURL()); - - JsonObject packageJson = Json.parse(FileUtils - .readFileToString(packageJsonFile, StandardCharsets.UTF_8)); - String path = getNodeUpdater().generateVersionsJson(packageJson); - - File generatedVersionsFile = new File(getNodeUpdater().npmFolder, path); - return Json.parse(FileUtils.readFileToString(generatedVersionsFile, - StandardCharsets.UTF_8)); - - } - - private NodeUpdater createAndRunNodeUpdater(String versionsContent) { - NodeUpdater nodeUpdater = createNodeUpdater(versionsContent); - try { - nodeUpdater.execute(); - } catch (Exception e) { - throw new IllegalStateException( - "NodeUpdater failed to genereate the versions.json file"); + + @Test + public void a2() throws Exception { + tst(); } - return nodeUpdater; - } + @Test + public void a3() throws Exception { + tst(); + } - private NodeUpdater createNodeUpdater(String versionsContent) { - return new NodeUpdater(finder, Mockito.mock(FrontendDependencies.class), - npmFolder, generatedPath, TARGET, - Mockito.mock(FeatureFlags.class)) { + @Test + public void a4() throws Exception { + tst(); + } - @Override - public void execute() { - try { - versionsPath = generateVersionsJson(Json.createObject()); - } catch (Exception e) { - versionsPath = null; - } - } + @Test + public void a5() throws Exception { + tst(); + } + + @Test + public void a6() throws Exception { + tst(); + } + + @Test + public void a7() throws Exception { + tst(); + } + + @Test + public void a8() throws Exception { + tst(); + } + + @Test + public void a9() throws Exception { + tst(); + } + + @Test + public void a10() throws Exception { + tst(); + } + + @Test + public void b1() throws Exception { + tst(); + } + + @Test + public void b2() throws Exception { + tst(); + } - @Override - protected String generateVersionsJson(JsonObject packageJson) - throws IOException { + @Test + public void b3() throws Exception { + tst(); + } + + @Test + public void b4() throws Exception { + tst(); + } + + @Test + public void b5() throws Exception { + tst(); + } + + @Test + public void b6() throws Exception { + tst(); + } + + @Test + public void b7() throws Exception { + tst(); + } + + @Test + public void b8() throws Exception { + tst(); + } + + @Test + public void b9() throws Exception { + tst(); + } + + @Test + public void b10() throws Exception { + tst(); + } + + public void tst() + throws Exception { +tst2(); + } + + public void tst2() throws Exception { + File packageJson = new File(nodeUpdater.npmFolder, PACKAGE_JSON); + packageJson.createNewFile(); + FileUtils.write(packageJson, + "{\"dependencies\": {" + + "\"@vaadin/vaadin-dialog\": \"2.2.1\"}}", + StandardCharsets.UTF_8); + + runNpmInstall(); + } + + private void runNpmInstall() throws Exception { + String baseDir = nodeUpdater.npmFolder.getAbsolutePath(); + + FrontendToolsSettings settings = new FrontendToolsSettings(baseDir, + () -> FrontendUtils.getVaadinHomeDirectory().getAbsolutePath()); + settings.setNodeDownloadRoot(URI.create(NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT)); + settings.setForceAlternativeNode(false); + settings.setUseGlobalPnpm(false); + settings.setAutoUpdate(false); + settings.setNodeVersion(FrontendTools.DEFAULT_NODE_VERSION); + FrontendTools tools = new FrontendTools(settings); + // tools.validateNodeAndNpmVersion(); + + List npmExecutable = tools.getPnpmExecutable(); + List npmInstallCommand = new ArrayList<>(npmExecutable); + npmInstallCommand.add("--ignore-scripts"); + npmInstallCommand.add("install"); + + runCommand(npmInstallCommand, + nodeUpdater.npmFolder); + + } + + private void runCommand(List command, File workingDirectory) throws Exception { + + ProcessBuilder builder = FrontendUtils.createProcessBuilder(command); + builder.directory(workingDirectory); + builder.redirectInput(ProcessBuilder.Redirect.INHERIT); + builder.redirectError(ProcessBuilder.Redirect.INHERIT); + + System.err.println("Running '" + command.stream().collect(Collectors.joining(" ")) + "'"); + Process process = builder.start(); try { - if (versionsContent != null) { - FileUtils.write(new File(npmFolder, "versions.json"), - versionsContent, StandardCharsets.UTF_8); - } - } catch (IOException e) { - throw new RuntimeException(e); + // This will allow to destroy the process which does IO regardless + // whether it's executed in the same thread or another (may be + // daemon) thread + Runtime.getRuntime() + .addShutdownHook(new Thread(() -> { + System.err.println("Shutdown hook"); + if (process != null) { + process.destroyForcibly(); + } + })); + + // logger.debug("Output of `{}`:", commandString); + StringBuilder toolOutput = new StringBuilder(); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream(), + StandardCharsets.UTF_8))) { + String stdoutLine; + while ((stdoutLine = reader.readLine()) != null) { + // logger.debug(stdoutLine); + toolOutput.append(stdoutLine) + .append(System.lineSeparator()); + } + } + + int errorCode = process.waitFor(); + + if (errorCode != 0) { + throw new RuntimeException("It failed"); + } + } catch (Exception e) { + if (e instanceof InterruptedException) { + // Restore interrupted state + Thread.currentThread().interrupt(); + } + throw new RuntimeException( + "Command failed to finish", e); + } finally { + if (process != null) { + System.err.println("Destroy forcible at end"); + + process.destroyForcibly(); + } } - return "./versions.json"; - } - }; - } + } } diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdatePackagesNpmTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdatePackagesNpmTest.java deleted file mode 100644 index 073cfe5b87a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdatePackagesNpmTest.java +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; - -import net.jcip.annotations.NotThreadSafe; -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonValue; - -import static com.vaadin.flow.server.Constants.PACKAGE_JSON; -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEPENDENCIES; -import static com.vaadin.flow.server.frontend.NodeUpdater.DEV_DEPENDENCIES; -import static com.vaadin.flow.server.frontend.NodeUpdater.VAADIN_DEP_KEY; -import static com.vaadin.flow.server.frontend.NodeUpdater.OVERRIDES; -import static com.vaadin.flow.server.frontend.VersionsJsonConverter.VAADIN_CORE_NPM_PACKAGE; - -@NotThreadSafe -public class TaskUpdatePackagesNpmTest { - - private static final String PLATFORM_DIALOG_VERSION = "2.5.2"; - private static final String USER_SPECIFIED_MIXIN_VERSION = "2.4.1"; - private static final String VAADIN_ELEMENT_MIXIN = "@vaadin/vaadin-element-mixin"; - private static final String VAADIN_DIALOG = "@vaadin/vaadin-dialog"; - private static final String VAADIN_OVERLAY = "@vaadin/vaadin-overlay"; - private static final String PLATFORM_ELEMENT_MIXIN_VERSION = "2.4.2"; - private static final String PLATFORM_OVERLAY_VERSION = "3.5.1"; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File npmFolder; - - private ClassFinder finder; - - private Logger logger = Mockito - .spy(LoggerFactory.getLogger(NodeUpdater.class)); - private File generatedPath; - - private File versionJsonFile; - - private File packageJson; - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Before - public void setUp() throws IOException { - npmFolder = temporaryFolder.newFolder(); - generatedPath = new File(npmFolder, "generated"); - generatedPath.mkdir(); - versionJsonFile = new File(npmFolder, "versions.json"); - finder = Mockito.mock(ClassFinder.class); - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versionJsonFile.toURI().toURL()); - - packageJson = new File(npmFolder, PACKAGE_JSON); - } - - @Test - public void npmIsInUse_platformVersionsJsonHasPinnedVersions_versionsArePinned() - throws IOException { - runTestWithoutPreexistingPackageJson(); - } - - private void runTestWithoutPreexistingPackageJson() throws IOException { - createBasicVaadinVersionsJson(); - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - Assert.assertTrue("Updates we're not written", task.modified); - verifyVersions(PLATFORM_DIALOG_VERSION, PLATFORM_ELEMENT_MIXIN_VERSION, - PLATFORM_OVERLAY_VERSION); - verifyVersionLockingWithNpmOverrides(true, true, true); - } - - @Test - public void npmIsInUse_userHasPinnedPlatformProvidedVersionInPackageJson_userPinnedVersionUsed() - throws IOException { - // run the basic test to produce an existing package.json - runTestWithoutPreexistingPackageJson(); - - // user pins a transitive dependency in package.json - final JsonObject packageJsonJson = getOrCreatePackageJson(); - JsonObject dependencies = packageJsonJson.getObject(DEPENDENCIES); - dependencies.put(VAADIN_ELEMENT_MIXIN, USER_SPECIFIED_MIXIN_VERSION); - FileUtils.writeStringToFile(new File(npmFolder, PACKAGE_JSON), - packageJsonJson.toJson(), StandardCharsets.UTF_8); - - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - Assert.assertTrue( - "User's updates in package.json should have been noticed.", - task.modified); - - // versions should be the same, except overridden mixin - verifyVersions(PLATFORM_DIALOG_VERSION, USER_SPECIFIED_MIXIN_VERSION, - PLATFORM_OVERLAY_VERSION); - } - - @Test - public void npmIsInUse_applicationHasPinnedPlatformProvidedVersionInAddon_applicationPinnedVersionIsUsed() - throws IOException { - // run the basic test to produce an existing package.json - runTestWithoutPreexistingPackageJson(); - - // user adds an application/add-on specific version, - // in practice excludes the vaadin brought in version - final Map applicationDependencies = createApplicationDependencies(); - applicationDependencies.put(VAADIN_ELEMENT_MIXIN, - USER_SPECIFIED_MIXIN_VERSION); - final TaskUpdatePackages task = createTask(applicationDependencies); - task.execute(); - Assert.assertTrue( - "User's added application dependency updates should have been noticed", - task.modified); - - // versions should be the same, except overridden mixin - verifyVersions(PLATFORM_DIALOG_VERSION, USER_SPECIFIED_MIXIN_VERSION, - PLATFORM_OVERLAY_VERSION); - } - - @Test - public void npmIsInUse_platformVersionIsBumped_versionsAreUpdated() - throws IOException { - // run the basic test to produce an existing package.json - runTestWithoutPreexistingPackageJson(); - // write new versions json and scanned deps - final String newVersion = "20.0.0"; - createVaadinVersionsJson(newVersion, newVersion, newVersion); - - final Map applicationDependencies = createApplicationDependencies(); - applicationDependencies.put(VAADIN_DIALOG, newVersion); - final TaskUpdatePackages task = createTask(applicationDependencies); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersions(newVersion, newVersion, newVersion); - verifyVersionLockingWithNpmOverrides(true, true, true); - } - - @Test - public void npmIsInUse_noPlatformVersionJsonPresent_noFailure() - throws IOException { - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(null); - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versionJsonFile.toURI().toURL()); - JsonObject dependencies = getOrCreatePackageJson() - .getObject(DEPENDENCIES); - Assert.assertEquals(PLATFORM_DIALOG_VERSION, - dependencies.get(VAADIN_DIALOG).asString()); - } - - @Test - public void npmIsInUse_platformVersionsJsonAdded_versionsPinned() - throws IOException { - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(null); - createTask(createApplicationDependencies()).execute(); - - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versionJsonFile.toURI().toURL()); - final String newVersion = "20.0.0"; - createVaadinVersionsJson(newVersion, newVersion, newVersion); - - final Map applicationDependencies = createApplicationDependencies(); - applicationDependencies.put(VAADIN_DIALOG, newVersion); - final TaskUpdatePackages task = createTask(applicationDependencies); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersions(newVersion, newVersion, newVersion); - verifyVersionLockingWithNpmOverrides(true, true, true); - } - - @Test - public void pnpmIsInUse_platformVersionsJsonAdded_dependenciesAdded() - throws IOException { - verifyPlatformDependenciesAreAdded(true); - } - - @Test - public void npmIsInUse_platformVersionsJsonAdded_dependenciesAdded() - throws IOException { - verifyPlatformDependenciesAreAdded(false); - } - - @Test - public void npmIsInUse_versionJsonHasBadVersion_noFailureNothingAdded() - throws IOException { - createVaadinVersionsJson(PLATFORM_DIALOG_VERSION, - PLATFORM_ELEMENT_MIXIN_VERSION, "{{{foobar}}"); - - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersions(PLATFORM_DIALOG_VERSION, PLATFORM_ELEMENT_MIXIN_VERSION, - null); - verifyVersionLockingWithNpmOverrides(true, true, false); - } - - @Test - public void npmIsInUse_executionAfterDependencyRemoved_overlayIsCleanedOfDependency() - throws IOException { - createVaadinVersionsJson(PLATFORM_DIALOG_VERSION, - PLATFORM_ELEMENT_MIXIN_VERSION, PLATFORM_OVERLAY_VERSION); - - final Map applicationDependencies = createApplicationDependencies(); - applicationDependencies.put(VAADIN_ELEMENT_MIXIN, - PLATFORM_ELEMENT_MIXIN_VERSION); - applicationDependencies.put(VAADIN_OVERLAY, PLATFORM_OVERLAY_VERSION); - TaskUpdatePackages task = createTask(applicationDependencies); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersionLockingWithNpmOverrides(true, true, true); - - // Remove platform lock for vaadin-element-mixin - final JsonObject versions = Json.parse(FileUtils - .readFileToString(versionJsonFile, StandardCharsets.UTF_8)); - versions.getObject("core").remove("vaadin-element-mixin"); - FileUtils.writeStringToFile(versionJsonFile, versions.toJson(), - StandardCharsets.UTF_8); - - // Remove VAADIN_ELEMENT_MIXIN from the application dependencies - applicationDependencies.remove(VAADIN_ELEMENT_MIXIN); - task = createTask(applicationDependencies); - - task.execute(); - - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersionLockingWithNpmOverrides(true, false, true); - } - - @Test - public void npmIsInUse_dependencyMovedToDevDependencies_overrideNotRemoved() - throws IOException { - createVaadinVersionsJson(PLATFORM_DIALOG_VERSION, - PLATFORM_ELEMENT_MIXIN_VERSION, PLATFORM_OVERLAY_VERSION); - - final Map applicationDependencies = createApplicationDependencies(); - applicationDependencies.put(VAADIN_ELEMENT_MIXIN, - PLATFORM_ELEMENT_MIXIN_VERSION); - applicationDependencies.put(VAADIN_OVERLAY, PLATFORM_OVERLAY_VERSION); - TaskUpdatePackages task = createTask(applicationDependencies); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersionLockingWithNpmOverrides(true, true, true); - - // Remove platform lock for vaadin-element-mixin - final JsonObject versions = Json.parse(FileUtils - .readFileToString(versionJsonFile, StandardCharsets.UTF_8)); - versions.getObject("core").remove("vaadin-element-mixin"); - FileUtils.writeStringToFile(versionJsonFile, versions.toJson(), - StandardCharsets.UTF_8); - - // Move element-mixin to devDependencies - JsonObject packageJson = getOrCreatePackageJson(); - packageJson.getObject(DEV_DEPENDENCIES).put(VAADIN_ELEMENT_MIXIN, - PLATFORM_ELEMENT_MIXIN_VERSION); - FileUtils.writeStringToFile(this.packageJson, packageJson.toJson(), - StandardCharsets.UTF_8); - - // Remove VAADIN_ELEMENT_MIXIN from the application dependencies - applicationDependencies.remove(VAADIN_ELEMENT_MIXIN); - task = createTask(applicationDependencies); - - task.execute(); - - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersionLockingWithNpmOverrides(true, true, true); - } - - @Test - public void npmIsInUse_versionsJsonHasSnapshotVersions_notAddedToPackageJson() - throws IOException { - createVaadinVersionsJson(PLATFORM_DIALOG_VERSION, - PLATFORM_ELEMENT_MIXIN_VERSION, "20.0-SNAPSHOT"); - - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersions(PLATFORM_DIALOG_VERSION, PLATFORM_ELEMENT_MIXIN_VERSION, - null); - verifyVersionLockingWithNpmOverrides(true, true, false); - } - - @Test - public void npmIsInUse_packageJsonHasBadVersion_pinnedVersionUsed() - throws IOException { - final JsonObject packageJson = getOrCreatePackageJson(); - JsonObject dependencies = packageJson.getObject(DEPENDENCIES); - dependencies.put(VAADIN_ELEMENT_MIXIN, "asdfasagqae4rat"); - FileUtils.writeStringToFile(new File(npmFolder, PACKAGE_JSON), - packageJson.toJson(), StandardCharsets.UTF_8); - - createBasicVaadinVersionsJson(); - - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersions(PLATFORM_DIALOG_VERSION, PLATFORM_ELEMENT_MIXIN_VERSION, - PLATFORM_OVERLAY_VERSION); - verifyVersionLockingWithNpmOverrides(true, true, true); - } - - // #11025 - @Test - public void npmIsInUse_versionsJsonHasVaadinCoreVersionPinned_vaadinCoreVersionIgnored() - throws IOException { - final String expectedElementMixinVersion = "21.0.0-alpha2"; - String versionJsonString = //@formatter:off - "{ \"core\": {" + "\"vaadin-element-mixin\": {\n" - + " \"jsVersion\": \"" + expectedElementMixinVersion - + "\",\n" + " \"npmName\": \"" + VAADIN_ELEMENT_MIXIN - + "\"\n" + "},\n" + "\"vaadin-core\": {\n" - + " \"jsVersion\": \"21.0.0.alpha1\",\n" - // broken for npm - + " \"npmName\": \"" + VAADIN_CORE_NPM_PACKAGE - + "\"\n" + "},\n" + "}}},\n";//@formatter:on - FileUtils.write(versionJsonFile, versionJsonString, - StandardCharsets.UTF_8); - - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - Assert.assertTrue("Updates not picked", task.modified); - - verifyVersions(PLATFORM_DIALOG_VERSION, expectedElementMixinVersion, - null); - verifyVersionLockingWithNpmOverrides(true, true, false); - final JsonObject packageJson = getOrCreatePackageJson(); - JsonObject dependencies = packageJson.getObject(DEPENDENCIES); - - Assert.assertFalse( - VAADIN_CORE_NPM_PACKAGE - + " version should not be written to package.json", - dependencies.hasKey(VAADIN_CORE_NPM_PACKAGE)); - final JsonObject vaadinDependencies = packageJson - .getObject(VAADIN_DEP_KEY).getObject(DEPENDENCIES); - Assert.assertFalse(VAADIN_CORE_NPM_PACKAGE - + " version should not be written to vaadin dependencies in package.json", - vaadinDependencies.hasKey(VAADIN_CORE_NPM_PACKAGE)); - } - - @Test - public void passUnorderedApplicationDependenciesAndReadUnorderedPackageJson_resultingPackageJsonIsOrdered() - throws IOException { - createBasicVaadinVersionsJson(); - - LinkedHashMap map = new LinkedHashMap<>(); - map.put("foo", "bar"); - // "bar" is lexicographically before the "foo" but in the linked hash - // map it's set after - map.put("baz", "foobar"); - - JsonObject packageJson = getOrCreatePackageJson(); - JsonObject dependencies = packageJson.getObject(DEPENDENCIES); - - packageJson.remove(DEPENDENCIES); - - packageJson.put("name", "a"); - packageJson.put("license", "b"); - packageJson.put("version", "c"); - - LinkedHashSet mainKeys = new LinkedHashSet<>( - Arrays.asList(packageJson.keys())); - - packageJson.put(DEPENDENCIES, dependencies); - - // Json object preserve the order of keys - dependencies.put("foo-pack", "bar"); - dependencies.put("baz-pack", "foobar"); - FileUtils.writeStringToFile(new File(npmFolder, PACKAGE_JSON), - packageJson.toJson(), StandardCharsets.UTF_8); - - TaskUpdatePackages task = createTask(map); - - task.execute(); - - // now read the package json file - packageJson = getOrCreatePackageJson(); - - List list = Arrays.asList(packageJson.keys()); - int indexOfOverrides = list.indexOf(OVERRIDES); - if (indexOfOverrides == -1) { - // the "vaadin" key is the last one if no overrides - Assert.assertEquals(list.size() - 1, list.indexOf(VAADIN_DEP_KEY)); - } else { - // the "vaadin" key is the second to the last one with overrides - Assert.assertEquals(list.size() - 2, list.indexOf(VAADIN_DEP_KEY)); - } - - List keysBeforeDeps = new ArrayList<>(); - - for (String key : packageJson.keys()) { - if (key.equals(DEV_DEPENDENCIES) || key.equals(DEPENDENCIES)) { - break; - } - if (mainKeys.contains(key)) { - keysBeforeDeps.add(key); - } - } - - // the order of the main keys is the same - Assert.assertArrayEquals(mainKeys.toArray(), keysBeforeDeps.toArray()); - - checkOrder(DEPENDENCIES, packageJson.getObject(DEPENDENCIES)); - checkOrder(DEV_DEPENDENCIES, packageJson.getObject(DEV_DEPENDENCIES)); - checkOrder(VAADIN_DEP_KEY, packageJson.getObject(VAADIN_DEP_KEY)); - } - - private void checkOrder(String path, JsonObject object) { - String[] keys = object.keys(); - if (path.isEmpty()) { - Assert.assertTrue("Keys in the package Json are not sorted", - isSorted(keys)); - } else { - Assert.assertTrue( - "Keys for the object " + path - + " in the package Json are not sorted", - isSorted(keys)); - } - for (String key : keys) { - JsonValue value = object.get(key); - if (value instanceof JsonObject) { - checkOrder(path + "/" + key, (JsonObject) value); - } - } - } - - private boolean isSorted(String[] array) { - if (array.length < 2) { - return true; - } - for (int i = 0; i < array.length - 1; i++) { - if (array[i].compareTo(array[i + 1]) > 0) { - return false; - } - } - return true; - } - - // #11888 - @Test - public void npmIsInUse_versionsJsonContainsSameVersions_nothingIsModified() - throws IOException { - String versionJsonString = //@formatter:off - "{ \"core\": {" + "\"vaadin-element-mixin\": {\n" - + " \"jsVersion\": \"" + PLATFORM_DIALOG_VERSION - + "\",\n" + " \"npmName\": \"" + VAADIN_DIALOG - + "\"\n" + "},\n" + "}}},\n";//@formatter:on - FileUtils.write(versionJsonFile, versionJsonString, - StandardCharsets.UTF_8); - - TaskUpdatePackages task = createTask(createApplicationDependencies()); - task.execute(); - Assert.assertTrue( - "Creation of package.json should be marked with modified", - task.modified); - - // Rewriting with the same packages should not mark as modified - task = createTask(createApplicationDependencies()); - task.execute(); - Assert.assertFalse("PackageJson modified without changes.", - task.modified); - } - - @Test - public void nonNumericVersionsNotPinned() throws IOException { - final JsonObject packageJson = getOrCreatePackageJson(); - createBasicVaadinVersionsJson(); - JsonObject dependencies = packageJson.getObject(DEPENDENCIES); - dependencies.put("localdep", "./localdeps/localdep"); - File file = new File(npmFolder, PACKAGE_JSON); - FileUtils.writeStringToFile(file, packageJson.toJson(), - StandardCharsets.UTF_8); - - Assert.assertFalse(packageJson.hasKey("overrides") - && packageJson.getObject("overrides").hasKey("localdep")); - - final TaskUpdatePackages task = createTask( - createApplicationDependencies()); - task.execute(); - - final JsonObject newPackageJson = getOrCreatePackageJson(); - - Assert.assertFalse(newPackageJson.hasKey("overrides") - && newPackageJson.getObject("overrides").hasKey("localdep")); - } - - private void createBasicVaadinVersionsJson() { - createVaadinVersionsJson(PLATFORM_DIALOG_VERSION, - PLATFORM_ELEMENT_MIXIN_VERSION, PLATFORM_OVERLAY_VERSION); - } - - private void createVaadinVersionsJson(String dialogVersion, - String elementMixinVersion, String overlayVersion) { - // testing with exact versions json content instead of mocking parsing - String versionJsonString = //@formatter:off - "{ \"core\": {" - + "\"vaadin-dialog\": {\n" - + " \"component\": true,\n" - + " \"javaVersion\": \"{{version}}\",\n" - + " \"jsVersion\": \"" + dialogVersion + "\",\n" - + " \"npmName\": \"" + VAADIN_DIALOG + "\"\n" - + "},\n" - + "\"vaadin-element-mixin\": {\n" - + " \"jsVersion\": \"" + elementMixinVersion - + "\",\n" + " \"npmName\": \"" + VAADIN_ELEMENT_MIXIN - + "\"\n" + "},\n" - + "\"vaadin-overlay\": {\n" - + " \"jsVersion\": \"" + overlayVersion + "\",\n" - + " \"npmName\": \"" + VAADIN_OVERLAY + "\",\n" - + " \"releasenotes\": true\n" - + "}}},\n";//@formatter:on - try { - FileUtils.write(versionJsonFile, versionJsonString, - StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private Map createApplicationDependencies() { - Map applicationScannedDependencies = new HashMap<>(); - applicationScannedDependencies.put(VAADIN_DIALOG, - PLATFORM_DIALOG_VERSION); - return applicationScannedDependencies; - } - - private TaskUpdatePackages createTask( - Map applicationDependencies) { - return createTask(applicationDependencies, false); - } - - private TaskUpdatePackages createTask( - Map applicationDependencies, boolean enablePnpm) { - final FrontendDependencies frontendDependenciesScanner = Mockito - .mock(FrontendDependencies.class); - Mockito.when(frontendDependenciesScanner.getPackages()) - .thenReturn(applicationDependencies); - return new TaskUpdatePackages(finder, frontendDependenciesScanner, - npmFolder, generatedPath, null, false, enablePnpm, TARGET, - Mockito.mock(FeatureFlags.class)) { - }; - } - - private JsonObject getOrCreatePackageJson() throws IOException { - if (packageJson.exists()) { - return Json.parse(FileUtils.readFileToString(packageJson, - StandardCharsets.UTF_8)); - } else { - final JsonObject packageJsonJson = Json.createObject(); - packageJsonJson.put(DEPENDENCIES, Json.createObject()); - FileUtils.writeStringToFile(new File(npmFolder, PACKAGE_JSON), - packageJsonJson.toJson(), StandardCharsets.UTF_8); - return packageJsonJson; - } - } - - private void verifyVersions(String expectedDialogVersion, - String expectedElementMixinVersion, String expectedOverlayVersion) - throws IOException { - JsonObject dependencies = getOrCreatePackageJson() - .getObject(DEPENDENCIES); - if (expectedDialogVersion == null) { - Assert.assertNull("Dependency added when it should not have been", - dependencies.get(VAADIN_DIALOG)); - } else { - Assert.assertEquals(expectedDialogVersion, - dependencies.getString(VAADIN_DIALOG)); - } - if (expectedElementMixinVersion == null) { - Assert.assertNull("Dependency added when it should not have been", - dependencies.get(VAADIN_ELEMENT_MIXIN)); - } else { - Assert.assertEquals(expectedElementMixinVersion, - dependencies.getString(VAADIN_ELEMENT_MIXIN)); - } - if (expectedOverlayVersion == null) { - Assert.assertNull("Dependency added when it should not have been", - dependencies.get(VAADIN_OVERLAY)); - } else { - Assert.assertEquals(expectedOverlayVersion, - dependencies.getString(VAADIN_OVERLAY)); - } - } - - private void verifyVersionLockingWithNpmOverrides(boolean hasDialogLocking, - boolean hasElementMixinLocking, boolean hasOverlayLocking) - throws IOException { - JsonObject overrides = getOrCreatePackageJson().getObject(OVERRIDES); - - if (hasDialogLocking) { - Assert.assertTrue("Dialog override was not present", - overrides.hasKey(VAADIN_DIALOG)); - Assert.assertEquals("$" + VAADIN_DIALOG, - overrides.getString(VAADIN_DIALOG)); - } else { - Assert.assertNull("vaadin-dialog dependency should not be present", - overrides.get(VAADIN_DIALOG)); - } - if (hasElementMixinLocking) { - Assert.assertTrue("Element-Mixin override was not present", - overrides.hasKey(VAADIN_ELEMENT_MIXIN)); - Assert.assertEquals("$" + VAADIN_ELEMENT_MIXIN, - overrides.getString(VAADIN_ELEMENT_MIXIN)); - } else { - Assert.assertNull( - "vaadin-element-mixin dependency should not be present", - overrides.get(VAADIN_ELEMENT_MIXIN)); - } - if (hasOverlayLocking) { - Assert.assertTrue("Overlay override was not present", - overrides.hasKey(VAADIN_OVERLAY)); - Assert.assertEquals("$" + VAADIN_OVERLAY, - overrides.getString(VAADIN_OVERLAY)); - } else { - Assert.assertNull("vaadin-overlay dependency should not be present", - overrides.get(VAADIN_OVERLAY)); - } - } - - private void verifyPlatformDependenciesAreAdded(boolean enablePnpm) - throws IOException { - Mockito.when(finder.getResource(Constants.VAADIN_CORE_VERSIONS_JSON)) - .thenReturn(versionJsonFile.toURI().toURL()); - final String newVersion = "20.0.0"; - createVaadinVersionsJson(newVersion, newVersion, newVersion); - - final Map applicationDependencies = Collections - .emptyMap(); - final TaskUpdatePackages task = createTask(applicationDependencies, - enablePnpm); - - verifyVersions(null, null, null); - - task.execute(); - - verifyVersions(newVersion, newVersion, newVersion); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdateThemeImportTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdateThemeImportTest.java deleted file mode 100644 index 98b8dc9b14f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdateThemeImportTest.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.server.ExecutionFailedException; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.ThemeDefinition; - -import static com.vaadin.flow.server.Constants.APPLICATION_THEME_ROOT; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES; -import static com.vaadin.flow.server.frontend.FrontendUtils.THEME_IMPORTS_D_TS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.THEME_IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.TaskUpdateThemeImport.APPLICATION_META_INF_RESOURCES; -import static com.vaadin.flow.server.frontend.TaskUpdateThemeImport.APPLICATION_STATIC_RESOURCES; - -@NotThreadSafe -public class TaskUpdateThemeImportTest { - - private static final String CUSTOM_THEME_NAME = "custom-theme"; - private static final String CUSTOM_VARIANT_NAME = "custom-variant"; - private static final String CUSTOM_THEME_PATH = String.join("/", - APPLICATION_THEME_ROOT, CUSTOM_THEME_NAME); - public static final String EMPTY_BEFORE_EXECUTION = "%s should not exist before executing TaskUpdateThemeImport."; - public static final String SHOULD_EXIST_AFTER_EXECUTION = "%s should be created as the result of executing TaskUpdateThemeImport."; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private File projectRoot; - private File npmFolder; - private File frontendDirectory; - private File themeImportFile; - private File themeImportTsFile; - private Class dummyThemeClass; - private ThemeDefinition customTheme; - private TaskUpdateThemeImport taskUpdateThemeImport; - - @Before - public void setUp() throws IOException { - projectRoot = temporaryFolder.getRoot(); - npmFolder = temporaryFolder.getRoot(); - frontendDirectory = new File(projectRoot, DEFAULT_FRONTEND_DIR); - - File frontendFolder = new File(npmFolder, - FrontendUtils.DEFAULT_FRONTEND_DIR); - themeImportFile = new File( - new File(frontendFolder, FrontendUtils.GENERATED), - THEME_IMPORTS_NAME); - themeImportTsFile = new File( - new File(frontendFolder, FrontendUtils.GENERATED), - THEME_IMPORTS_D_TS_NAME); - dummyThemeClass = Mockito.mock(AbstractTheme.class).getClass(); - customTheme = new ThemeDefinition(dummyThemeClass, CUSTOM_VARIANT_NAME, - CUSTOM_THEME_NAME); - taskUpdateThemeImport = new TaskUpdateThemeImport(npmFolder, - customTheme, frontendDirectory); - } - - @Test - public void taskExecuted_customThemeWithNonExistingThemeFolder_throwsException() { - - File faultyFrontendDirectory = new File(projectRoot, - DEFAULT_FRONTEND_DIR); - - TaskUpdateThemeImport taskUpdateThemeImportWithNonExistentThemeFolder = new TaskUpdateThemeImport( - npmFolder, customTheme, faultyFrontendDirectory); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, - taskUpdateThemeImportWithNonExistentThemeFolder::execute); - - Assert.assertTrue(e.getMessage().contains(String.format( - "Discovered @Theme annotation with theme name '%s', " - + "but could not find the theme directory in the " - + "project or available as a jar dependency.", - CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeWithThemeFolderInFrontend_ensuresThemeGeneratedJsCreatedSuccessfully() - throws Exception { - - File themesDir = new File(frontendDirectory, APPLICATION_THEME_ROOT); - File aCustomThemeDir = new File(themesDir, CUSTOM_THEME_NAME); - - boolean customThemeDirCreatedSuccessfully = aCustomThemeDir.mkdirs(); - - Assert.assertTrue(String.format( - "%s directory should be created at '%s%s/%s' but failed.", - CUSTOM_THEME_NAME, DEFAULT_FRONTEND_DIR, APPLICATION_THEME_ROOT, - CUSTOM_THEME_NAME), customThemeDirCreatedSuccessfully); - - assertNoThemeGeneratedDefinitionFilesExist(EMPTY_BEFORE_EXECUTION); - taskUpdateThemeImport.execute(); - assertThemeGeneratedDefinitionFilesExist(SHOULD_EXIST_AFTER_EXECUTION); - } - - @Test - public void taskExecuted_customThemeWithThemeFolderInMetaInf_ensuresThemeGeneratedJsCreatedSuccessfully() - throws Exception { - - File correctMetaInfResourcesDirectory = new File(projectRoot, - APPLICATION_META_INF_RESOURCES); - File themesDir = new File(correctMetaInfResourcesDirectory, - APPLICATION_THEME_ROOT); - File aCustomThemeDir = new File(themesDir, CUSTOM_THEME_NAME); - - boolean customThemeDirCreatedSuccessfully = aCustomThemeDir.mkdirs(); - - Assert.assertTrue(String.format( - "%s directory should be created at '%s/%s/%s' but failed.", - CUSTOM_THEME_NAME, APPLICATION_META_INF_RESOURCES, - APPLICATION_THEME_ROOT, CUSTOM_THEME_NAME), - customThemeDirCreatedSuccessfully); - - assertNoThemeGeneratedDefinitionFilesExist(EMPTY_BEFORE_EXECUTION); - taskUpdateThemeImport.execute(); - assertThemeGeneratedDefinitionFilesExist(SHOULD_EXIST_AFTER_EXECUTION); - } - - @Test - public void taskExecuted_customThemeWithThemeFolderInStatic_ensuresThemeGeneratedJsCreatedSuccessfully() - throws Exception { - - File correctStaticResourcesDirectory = new File(projectRoot, - APPLICATION_STATIC_RESOURCES); - File themesDir = new File(correctStaticResourcesDirectory, - APPLICATION_THEME_ROOT); - File aCustomThemeDir = new File(themesDir, CUSTOM_THEME_NAME); - - boolean customThemeDirCreatedSuccessfully = aCustomThemeDir.mkdirs(); - - Assert.assertTrue(String.format( - "%s directory should be created at '%s/%s/%s' but failed.", - CUSTOM_THEME_NAME, APPLICATION_STATIC_RESOURCES, - APPLICATION_THEME_ROOT, CUSTOM_THEME_NAME), - customThemeDirCreatedSuccessfully); - - assertNoThemeGeneratedDefinitionFilesExist(EMPTY_BEFORE_EXECUTION); - taskUpdateThemeImport.execute(); - assertThemeGeneratedDefinitionFilesExist(SHOULD_EXIST_AFTER_EXECUTION); - } - - @Test - public void taskExecuted_customThemeWithThemeFolderInClasspath_ensuresThemeGeneratedJsCreatedSuccessfully() - throws Exception { - - File jarResourcesFolder = new File( - new File(frontendDirectory, FrontendUtils.GENERATED), - FrontendUtils.JAR_RESOURCES_FOLDER); - File themesDir = new File(jarResourcesFolder, APPLICATION_THEME_ROOT); - File aCustomThemeDir = new File(themesDir, CUSTOM_THEME_NAME); - - boolean customThemeDirCreatedSuccessfully = aCustomThemeDir.mkdirs(); - - Assert.assertTrue( - String.format( - "%s directory should be created at '%s' but failed.", - CUSTOM_THEME_NAME, aCustomThemeDir), - customThemeDirCreatedSuccessfully); - - assertNoThemeGeneratedDefinitionFilesExist(EMPTY_BEFORE_EXECUTION); - taskUpdateThemeImport.execute(); - assertThemeGeneratedDefinitionFilesExist(SHOULD_EXIST_AFTER_EXECUTION); - } - - @Test - public void runTaskWithTheme_createsThemeFile_afterRunWithoutTheme_removesThemeFile() - throws Exception { - - File themesDir = new File(frontendDirectory, APPLICATION_THEME_ROOT); - File aCustomThemeDir = new File(themesDir, CUSTOM_THEME_NAME); - - boolean customThemeDirCreatedSuccessfully = aCustomThemeDir.mkdirs(); - - Assert.assertTrue(String.format( - "%s directory should be created at '%s%s/%s' but failed.", - CUSTOM_THEME_NAME, DEFAULT_FRONTEND_DIR, APPLICATION_THEME_ROOT, - CUSTOM_THEME_NAME), customThemeDirCreatedSuccessfully); - - assertNoThemeGeneratedDefinitionFilesExist(EMPTY_BEFORE_EXECUTION); - taskUpdateThemeImport.execute(); - assertThemeGeneratedDefinitionFilesExist(SHOULD_EXIST_AFTER_EXECUTION); - - taskUpdateThemeImport = new TaskUpdateThemeImport(npmFolder, null, - frontendDirectory); - - taskUpdateThemeImport.execute(); - - assertNoThemeGeneratedDefinitionFilesExist( - "After removal of theme %s should be removed"); - } - - private void assertNoThemeGeneratedDefinitionFilesExist( - String errorMessage) { - Assert.assertFalse(String.format(errorMessage, "\"theme.js\""), - themeImportFile.exists()); - - Assert.assertFalse(String.format(errorMessage, "\theme.d.ts\""), - themeImportTsFile.exists()); - } - - private void assertThemeGeneratedDefinitionFilesExist(String errorMessage) { - Assert.assertTrue(String.format(errorMessage, "\"theme.js\""), - themeImportFile.exists()); - - Assert.assertTrue(String.format(errorMessage, "\theme.d.ts\""), - themeImportTsFile.exists()); - } - - @Test - public void taskExecuted_customThemeFolderExistsInBothFrontendAndInClasspath_throwsException() { - - File themeDir = new File(frontendDirectory, CUSTOM_THEME_PATH); - Assert.assertTrue(themeDir.mkdirs()); - - String classPathThemePath = "frontend/" + FrontendUtils.GENERATED - + FrontendUtils.JAR_RESOURCES_FOLDER + "/" + CUSTOM_THEME_PATH; - File classPathThemeDir = new File(projectRoot, classPathThemePath); - Assert.assertTrue(classPathThemeDir.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage() - .contains(String.format( - "Theme '%s' should not exist inside a " - + "jar and in the project at the same time.", - CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInBothMetaInfResourcesAndInClasspath_throwsException() { - - String metaInfResources = String.join("/", - APPLICATION_META_INF_RESOURCES, CUSTOM_THEME_PATH); - File themeDir = new File(projectRoot, metaInfResources); - Assert.assertTrue(themeDir.mkdirs()); - - String classPathThemePath = "frontend/" + FrontendUtils.GENERATED - + FrontendUtils.JAR_RESOURCES_FOLDER + "/" + CUSTOM_THEME_PATH; - File classPathThemeDir = new File(projectRoot, classPathThemePath); - Assert.assertTrue(classPathThemeDir.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage() - .contains(String.format( - "Theme '%s' should not exist inside a " - + "jar and in the project at the same time.", - CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInBothStaticResourcesAndInClasspath_throwsException() { - - String staticResources = String.join("/", APPLICATION_STATIC_RESOURCES, - CUSTOM_THEME_PATH); - File themeDir = new File(projectRoot, staticResources); - Assert.assertTrue(themeDir.mkdirs()); - - String classPathThemePath = "frontend/" + FrontendUtils.GENERATED - + FrontendUtils.JAR_RESOURCES_FOLDER + "/" + CUSTOM_THEME_PATH; - File classPathThemeDir = new File(projectRoot, classPathThemePath); - Assert.assertTrue(classPathThemeDir.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage(), - e.getMessage().contains(String.format( - "Theme '%s' should not exist inside a " - + "jar and in the project at the same time.", - CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInBothStaticAndMetaInfResources_throwsException() { - - String staticResources = String.join("/", APPLICATION_STATIC_RESOURCES, - CUSTOM_THEME_PATH); - File themeDirInStatic = new File(projectRoot, staticResources); - Assert.assertTrue(themeDirInStatic.mkdirs()); - - String metaInfResources = String.join("/", - APPLICATION_META_INF_RESOURCES, CUSTOM_THEME_PATH); - File themeDirInMetaInf = new File(projectRoot, metaInfResources); - Assert.assertTrue(themeDirInMetaInf.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage().contains(String.format( - "Discovered Theme folder for theme '%s' " - + "in more than one place in the project. Please " - + "make sure there is only one theme folder with name '%s' " - + "exists in the your project. ", - CUSTOM_THEME_NAME, CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInBothFrontendAndMetaInfResources_throwsException() { - - File themeDir = new File(frontendDirectory, CUSTOM_THEME_PATH); - Assert.assertTrue(themeDir.mkdirs()); - - String metaInfResources = String.join("/", - APPLICATION_META_INF_RESOURCES, CUSTOM_THEME_PATH); - File themeDirInMetaInf = new File(projectRoot, metaInfResources); - Assert.assertTrue(themeDirInMetaInf.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage().contains(String.format( - "Discovered Theme folder for theme '%s' " - + "in more than one place in the project. Please " - + "make sure there is only one theme folder with name '%s' " - + "exists in the your project. ", - CUSTOM_THEME_NAME, CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInBothFrontendAndStaticResources_throwsException() { - - File themeDir = new File(frontendDirectory, CUSTOM_THEME_PATH); - Assert.assertTrue(themeDir.mkdirs()); - - String staticResources = String.join("/", APPLICATION_STATIC_RESOURCES, - CUSTOM_THEME_PATH); - File themeDirInStatic = new File(projectRoot, staticResources); - Assert.assertTrue(themeDirInStatic.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage().contains(String.format( - "Discovered Theme folder for theme '%s' " - + "in more than one place in the project. Please " - + "make sure there is only one theme folder with name '%s' " - + "exists in the your project. ", - CUSTOM_THEME_NAME, CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInFrontendAndStaticAndMetaInfResources_throwsException() { - - File themeDir = new File(frontendDirectory, CUSTOM_THEME_PATH); - Assert.assertTrue(themeDir.mkdirs()); - - String staticResources = String.join("/", APPLICATION_STATIC_RESOURCES, - CUSTOM_THEME_PATH); - File themeDirInStatic = new File(projectRoot, staticResources); - Assert.assertTrue(themeDirInStatic.mkdirs()); - - String metaInfResources = String.join("/", - APPLICATION_META_INF_RESOURCES, CUSTOM_THEME_PATH); - File themeDirInMetaInf = new File(projectRoot, metaInfResources); - Assert.assertTrue(themeDirInMetaInf.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage().contains(String.format( - "Discovered Theme folder for theme '%s' " - + "in more than one place in the project. Please " - + "make sure there is only one theme folder with name '%s' " - + "exists in the your project. ", - CUSTOM_THEME_NAME, CUSTOM_THEME_NAME))); - } - - @Test - public void taskExecuted_customThemeFolderExistsInClassPathAndStaticAndMetaInfResources_throwsException() { - - String classPathThemePath = "frontend/" + FrontendUtils.GENERATED - + FrontendUtils.JAR_RESOURCES_FOLDER + "/" + CUSTOM_THEME_PATH; - File classPathThemeDir = new File(projectRoot, classPathThemePath); - Assert.assertTrue(classPathThemeDir.mkdirs()); - - String staticResources = String.join("/", APPLICATION_STATIC_RESOURCES, - CUSTOM_THEME_PATH); - File themeDirInStatic = new File(projectRoot, staticResources); - Assert.assertTrue(themeDirInStatic.mkdirs()); - - String metaInfResources = String.join("/", - APPLICATION_META_INF_RESOURCES, CUSTOM_THEME_PATH); - File themeDirInMetaInf = new File(projectRoot, metaInfResources); - Assert.assertTrue(themeDirInMetaInf.mkdirs()); - - ExecutionFailedException e = Assert.assertThrows( - ExecutionFailedException.class, taskUpdateThemeImport::execute); - - Assert.assertTrue(e.getMessage() - .contains(String.format( - "Theme '%s' should not exist inside a " - + "jar and in the project at the same time.", - CUSTOM_THEME_NAME))); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdateViteTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdateViteTest.java deleted file mode 100644 index 1744c22b4f7..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/TaskUpdateViteTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.PwaConfiguration; - -import elemental.json.Json; -import elemental.json.JsonObject; -import static com.vaadin.flow.server.frontend.TaskUpdateSettingsFile.DEV_SETTINGS_FILE; - -public class TaskUpdateViteTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Test - public void generatedTemplate_correctSettingsPath() throws IOException { - TaskUpdateVite task = new TaskUpdateVite(temporaryFolder.getRoot(), - "build"); - task.execute(); - - File configFile = new File(temporaryFolder.getRoot(), - FrontendUtils.VITE_GENERATED_CONFIG); - - String template = IOUtils.toString(configFile.toURI(), - StandardCharsets.UTF_8); - - Assert.assertTrue("Settings file folder was not correctly updated.", - template.contains("./build/" + DEV_SETTINGS_FILE)); - } - - @Test - public void configFileExists_fileNotOverwritten() throws IOException { - File configFile = new File(temporaryFolder.getRoot(), - FrontendUtils.VITE_CONFIG); - final String importString = "Hello Fake configuration"; - FileUtils.write(configFile, importString, StandardCharsets.UTF_8); - - new TaskUpdateVite(temporaryFolder.getRoot(), "build").execute(); - - String template = IOUtils.toString(configFile.toURI(), - StandardCharsets.UTF_8); - - Assert.assertEquals("Settings file content was changed", importString, - template); - } - - @Test - public void generatedConfigFileExists_alwaysOverwritten() - throws IOException { - File generatedConfigFile = new File(temporaryFolder.getRoot(), - FrontendUtils.VITE_GENERATED_CONFIG); - final String importString = "Hello Fake generated configuration"; - FileUtils.write(generatedConfigFile, importString, - StandardCharsets.UTF_8); - - new TaskUpdateVite(temporaryFolder.getRoot(), "build").execute(); - - String template = IOUtils.toString(generatedConfigFile.toURI(), - StandardCharsets.UTF_8); - - Assert.assertNotEquals("Generated file should have been overwritten", - importString, template); - } - - @Test - public void usedSettings_matchThoseCreatedToSettingsFile() - throws IOException { - TaskUpdateVite task = new TaskUpdateVite(temporaryFolder.getRoot(), - "build"); - task.execute(); - - File generatedConfigFile = new File(temporaryFolder.getRoot(), - FrontendUtils.VITE_GENERATED_CONFIG); - - String template = IOUtils.toString(generatedConfigFile.toURI(), - StandardCharsets.UTF_8); - NodeTasks.Builder builder = new NodeTasks.Builder( - Mockito.mock(Lookup.class), temporaryFolder.getRoot(), - temporaryFolder.newFolder("generated"), - temporaryFolder.newFolder("frontend"), "target"); - builder.withJarFrontendResourcesFolder( - temporaryFolder.newFolder("resources")); - - TaskUpdateSettingsFile updateSettings = new TaskUpdateSettingsFile( - builder, "theme", new PwaConfiguration()); - updateSettings.execute(); - File settings = new File(temporaryFolder.getRoot(), - "target/" + DEV_SETTINGS_FILE); - JsonObject settingsJson = Json.parse( - IOUtils.toString(settings.toURI(), StandardCharsets.UTF_8)); - - final Matcher matcher = Pattern - .compile("settings\\.(?!json)([a-zA-z]*)").matcher(template); - StringBuilder faulty = new StringBuilder(); - while (matcher.find()) { - if (!settingsJson.hasKey(matcher.group(1))) { - faulty.append(matcher.group(1)).append('\n'); - } - } - Assert.assertTrue( - "Configuration uses settings keys\n" + faulty - + "that are not generated in settings file.", - faulty.toString().isEmpty()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateImportsWithByteCodeScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateImportsWithByteCodeScannerTest.java deleted file mode 100644 index a3415281931..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateImportsWithByteCodeScannerTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -public class UpdateImportsWithByteCodeScannerTest - extends AbstractUpdateImportsTest { - - @Override - protected FrontendDependenciesScanner getScanner(ClassFinder finder) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(false, finder, true); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateImportsWithFullCPScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateImportsWithFullCPScannerTest.java deleted file mode 100644 index 10e78b2bda3..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateImportsWithFullCPScannerTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner; - -public class UpdateImportsWithFullCPScannerTest - extends AbstractUpdateImportsTest { - - @Override - protected FrontendDependenciesScanner getScanner(ClassFinder finder) { - return new FrontendDependenciesScanner.FrontendDependenciesScannerFactory() - .createScanner(true, finder, true); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateThemedImportsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateThemedImportsTest.java deleted file mode 100644 index 69e2a459dc2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/UpdateThemedImportsTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.experimental.FeatureFlags; -import com.vaadin.flow.server.frontend.scanner.ClassFinder; -import com.vaadin.flow.server.frontend.scanner.FrontendDependencies; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.ThemeDefinition; - -import static com.vaadin.flow.server.Constants.TARGET; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR; -import static com.vaadin.flow.server.frontend.FrontendUtils.IMPORTS_NAME; -import static com.vaadin.flow.server.frontend.FrontendUtils.NODE_MODULES; - -public class UpdateThemedImportsTest extends NodeUpdateTestUtil { - - public static class MyTheme implements AbstractTheme { - @Override - public String getBaseUrl() { - return "src/"; - } - - @Override - public String getThemeUrl() { - return "theme/myTheme/"; - } - - @Override - public List getHeaderInlineContents() { - return Collections.emptyList(); - } - } - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private File importsFile; - private File generatedPath; - private File frontendDirectory; - private File nodeModulesPath; - private TaskUpdateImports updater; - - @Before - public void setup() throws Exception { - File tmpRoot = temporaryFolder.getRoot(); - - frontendDirectory = new File(tmpRoot, DEFAULT_FRONTEND_DIR); - nodeModulesPath = new File(tmpRoot, NODE_MODULES); - generatedPath = new File(tmpRoot, - Paths.get(TARGET, DEFAULT_GENERATED_DIR).toString()); - importsFile = new File(generatedPath, IMPORTS_NAME); - - Assert.assertTrue(nodeModulesPath.mkdirs()); - createImport("./src/subfolder/sub-template.js", ""); - createImport("./src/client-side-template.js", - "import 'xx' from './subfolder/sub-template.js';" - + "import '@vaadin/vaadin-button/src/vaadin-button.js'"); - createImport("./src/client-side-no-themed-template.js", ""); - createImport("./src/main-template.js", - "import 'xx' from './client-side-template.js';" - + "import \"./client-side-no-themed-template.js\";" - + "import './src/wrong-themed-template.js';" - + "import '@vaadin/vaadin-button/src/vaadin-button.js'"); - - // create themed modules - createImport("./theme/myTheme/subfolder/sub-template.js", ""); - createImport("./theme/myTheme/client-side-template.js", ""); - createImport("./theme/myTheme/main-template.js", ""); - - // wrong-themed-template.js should not be resolved inside node_modules. - // It should be searched only inside frontend directory - createImport("theme/myTheme/wrong-themed-template.js", ""); - // create css files to avoid exception when files not found during the - // test - createImport("./foo.css", ""); - createImport("@vaadin/vaadin-mixed-component/bar.css", ""); - - // make external component's module and its themed version - createImport("@vaadin/vaadin-button/src/vaadin-button.js", ""); - createImport("@vaadin/vaadin-button/theme/myTheme/vaadin-button.js", - ""); - - ClassFinder finder = getClassFinder(); - FrontendDependencies deps = new FrontendDependencies(finder) { - - @Override - public List getModules() { - return Stream.of("./src/main-template.js") - .collect(Collectors.toList()); - } - - @Override - public Set getScripts() { - return Collections.emptySet(); - } - - @Override - public AbstractTheme getTheme() { - return new MyTheme(); - } - - @Override - public ThemeDefinition getThemeDefinition() { - return new ThemeDefinition(MyTheme.class, "", ""); - } - }; - updater = new TaskUpdateImports(finder, deps, cf -> null, tmpRoot, - generatedPath, frontendDirectory, null, null, false, TARGET, - true, false, Mockito.mock(FeatureFlags.class)); - } - - @Test - public void themedClientSideModulesAreWrittenIntoImportsFile() - throws Exception { - updater.execute(); - - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - MatcherAssert.assertThat(content, CoreMatchers.allOf( - CoreMatchers.containsString( - "import 'Frontend/theme/myTheme/main-template.js';"), - CoreMatchers.containsString( - "import 'Frontend/theme/myTheme/client-side-template.js';"), - CoreMatchers.containsString( - "import 'Frontend/theme/myTheme/subfolder/sub-template.js';"), - CoreMatchers.containsString( - "import '@vaadin/vaadin-button/theme/myTheme/vaadin-button.js';"), - CoreMatchers.not(CoreMatchers.containsString( - "import 'theme/myTheme/wrong-themed-template.js';")))); - } - - @Test - public void noDuplicateImportEntryIsWrittenIntoImportsFile() - throws Exception { - updater.execute(); - - String content = FileUtils.readFileToString(importsFile, - Charset.defaultCharset()); - int count = StringUtils.countMatches(content, - "import '@vaadin/vaadin-button/theme/myTheme/vaadin-button.js';"); - Assert.assertEquals( - "Import entries in the imports file should be unique.", 1, - count); - } - - private void createImport(String path, String content) throws IOException { - File newFile = resolveImportFile(frontendDirectory, nodeModulesPath, - path); - newFile.getParentFile().mkdirs(); - newFile.delete(); - Assert.assertTrue(newFile.createNewFile()); - if (content != null) { - Files.write(newFile.toPath(), Collections.singletonList(content)); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/VersionsJsonConverterTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/VersionsJsonConverterTest.java deleted file mode 100644 index 648bbcaf253..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/VersionsJsonConverterTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import elemental.json.Json; -import elemental.json.JsonObject; - -import static com.vaadin.flow.server.frontend.VersionsJsonConverter.VAADIN_CORE_NPM_PACKAGE; - -public class VersionsJsonConverterTest { - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Test - public void convertPlatformVersions() throws IOException { - // @formatter:off - String json = "{\"core\": {"+ - "\"flow\": { " - + " \"javaVersion\": \"3.0.0.alpha17\"" - + "}, " - + " \"vaadin-progress-bar\": { " - + " \"npmName\": \"@vaadin/vaadin-progress-bar\", " - + "\"jsVersion\": \"1.1.2\" " - + "}," - + "}," //core - + "\"vaadin-upload\": { " - + "\"npmName\": \"@vaadin/vaadin-upload\", " - + "\"jsVersion\": \"4.2.2\"" - + "},"+ - "\"iron-list\": {\n" + - " \"npmName\": \"@polymer/iron-list\",\n" + - " \"npmVersion\": \"3.0.2\",\n" + - " \"javaVersion\": \"3.0.0.beta1\",\n" + - " \"jsVersion\": \"2.0.19\"\n" + - " }," - + "\"vaadin-core\": {\n" + - " \"jsVersion\": \"21.0.0.alpha1\",\n" + // broken for npm - " \"npmName\": \""+VAADIN_CORE_NPM_PACKAGE+"\"\n" + - "},\n" - +"\"platform\": \"foo\"" - + "}"; - // @formatter:on - - VersionsJsonConverter convert = new VersionsJsonConverter( - Json.parse(json)); - JsonObject convertedJson = convert.getConvertedJson(); - Assert.assertTrue(convertedJson.hasKey("@vaadin/vaadin-progress-bar")); - Assert.assertTrue(convertedJson.hasKey("@vaadin/vaadin-upload")); - Assert.assertTrue(convertedJson.hasKey("@polymer/iron-list")); - - Assert.assertFalse(convertedJson.hasKey("flow")); - Assert.assertFalse(convertedJson.hasKey("core")); - Assert.assertFalse(convertedJson.hasKey(VAADIN_CORE_NPM_PACKAGE)); - Assert.assertFalse(convertedJson.hasKey("platform")); - - Assert.assertEquals("1.1.2", - convertedJson.getString("@vaadin/vaadin-progress-bar")); - Assert.assertEquals("4.2.2", - convertedJson.getString("@vaadin/vaadin-upload")); - Assert.assertEquals("3.0.2", - convertedJson.getString("@polymer/iron-list")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/VersionsJsonFilterTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/VersionsJsonFilterTest.java deleted file mode 100644 index 3d1d0755101..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/VersionsJsonFilterTest.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import elemental.json.Json; -import elemental.json.JsonObject; - -public class VersionsJsonFilterTest { - - @Test - public void filterPlatformVersions_dependencies() throws IOException { - assertFilterPlatformVersions(NodeUpdater.DEPENDENCIES); - } - - @Test - public void filterPlatformVersions_devDependencies() throws IOException { - assertFilterPlatformVersions(NodeUpdater.DEV_DEPENDENCIES); - } - - @Test - public void filterPlatformDependenciesVersions_multipleUserChanged_correctlyIgnored() - throws IOException { - assertFilterPlatformVersions_multipleUserChanged_correctlyIgnored( - NodeUpdater.DEPENDENCIES); - } - - @Test - public void filterPlatformDevDependenciesVersions_multipleUserChanged_correctlyIgnored() - throws IOException { - assertFilterPlatformVersions_multipleUserChanged_correctlyIgnored( - NodeUpdater.DEV_DEPENDENCIES); - } - - @Test - public void missingVaadinDependencies_allDependenciesShouldBeUserHandled() - throws IOException { - assertMissingVaadinDependencies_allDependenciesSholdBeUserHandled( - NodeUpdater.DEPENDENCIES); - } - - @Test - public void missingVaadinDevDependencies_allDependenciesSholdBeUserHandled() - throws IOException { - assertMissingVaadinDependencies_allDependenciesSholdBeUserHandled( - NodeUpdater.DEV_DEPENDENCIES); - } - - @Test - public void testGetFilteredVersions_whenErrorHappens_versionOriginParameterIsUsedInErrorLogs() - throws IOException { - String pkgJson = IOUtils.toString( - Objects.requireNonNull( - getClass().getClassLoader().getResourceAsStream( - "versions/no_vaadin_package.json")), - StandardCharsets.UTF_8); - JsonObject packageJson = Json.parse(pkgJson); - VersionsJsonFilter filter = new VersionsJsonFilter(packageJson, - NodeUpdater.DEPENDENCIES); - String versionOrigin = "dummy-origin.json"; - - Logger logger = Mockito.spy(Logger.class); - try (MockedStatic loggerFactoryMocked = Mockito - .mockStatic(LoggerFactory.class)) { - loggerFactoryMocked - .when(() -> LoggerFactory.getLogger(FrontendVersion.class)) - .thenReturn(logger); - - JsonObject sourceJsonMocked = getMockedJsonObject(); - - Mockito.when(sourceJsonMocked.getString(Mockito.anyString())) - .thenThrow(new ClassCastException()); - filter.getFilteredVersions(sourceJsonMocked, versionOrigin); - Mockito.verify(logger, Mockito.times(1)).warn( - "Ignoring error while parsing frontend dependency version for package '{}' in '{}'", - "test", versionOrigin); - - sourceJsonMocked = getMockedJsonObject(); - - String nfeMessage = "NFE MSG"; - Mockito.when(sourceJsonMocked.getString(Mockito.anyString())) - .thenThrow(new NumberFormatException(nfeMessage)); - filter.getFilteredVersions(sourceJsonMocked, versionOrigin); - Mockito.verify(logger, Mockito.times(1)).warn( - "Ignoring error while parsing frontend dependency version in {}: {}", - versionOrigin, nfeMessage); - } - } - - private JsonObject getMockedJsonObject() { - JsonObject jsonObject = Mockito.mock(JsonObject.class); - Mockito.when(jsonObject.keys()).thenReturn(new String[] { "test" }); - Mockito.when(jsonObject.hasKey("test")).thenReturn(true); - return jsonObject; - } - - private void assertMissingVaadinDependencies_allDependenciesSholdBeUserHandled( - String depKey) throws IOException { - String versions = IOUtils.toString( - Objects.requireNonNull(getClass().getClassLoader() - .getResourceAsStream("versions/versions.json")), - StandardCharsets.UTF_8); - String pkgJson = IOUtils.toString( - Objects.requireNonNull( - getClass().getClassLoader().getResourceAsStream( - "versions/no_vaadin_package.json")), - StandardCharsets.UTF_8); - - VersionsJsonFilter filter = new VersionsJsonFilter(Json.parse(pkgJson), - depKey); - JsonObject filteredJson = filter.getFilteredVersions( - Json.parse(versions), "versions/versions.json"); - Assert.assertTrue(filteredJson.hasKey("@vaadin/vaadin-progress-bar")); - Assert.assertTrue(filteredJson.hasKey("@vaadin/vaadin-upload")); - Assert.assertTrue(filteredJson.hasKey("@polymer/iron-list")); - - Assert.assertEquals("1.1.2", - filteredJson.getString("@vaadin/vaadin-progress-bar")); - } - - private void assertFilterPlatformVersions_multipleUserChanged_correctlyIgnored( - String depKey) throws IOException { - String versions = IOUtils.toString( - Objects.requireNonNull(getClass().getClassLoader() - .getResourceAsStream("versions/user_versions.json")), - StandardCharsets.UTF_8); - String pkgJson = IOUtils.toString( - Objects.requireNonNull(getClass().getClassLoader() - .getResourceAsStream("versions/user_package.json")), - StandardCharsets.UTF_8); - - VersionsJsonFilter filter = new VersionsJsonFilter(Json.parse(pkgJson), - depKey); - JsonObject filteredJson = filter.getFilteredVersions( - Json.parse(versions), "versions/user_versions.json"); - List expectedKeys = Arrays.asList("@vaadin/vaadin-notification", - "@vaadin/vaadin-overlay", "@vaadin/vaadin-select", - "@vaadin/vaadin-split-layout", "@vaadin/vaadin-tabs"); - - for (String key : expectedKeys) { - Assert.assertTrue( - String.format("Key '%s' was expected, but not found", key), - filteredJson.hasKey(key)); - } - - List droppedKeys = Arrays.asList("flow", "core", "platform"); - for (String key : droppedKeys) { - Assert.assertFalse( - String.format("User managed key '%s' was found.", key), - filteredJson.hasKey(key)); - } - - Map expectedValues = new HashMap<>(); - expectedValues.put("@vaadin/vaadin-notification", "1.4.0"); - expectedValues.put("@vaadin/vaadin-overlay", "3.2.19"); - expectedValues.put("@vaadin/vaadin-select", "2.1.7"); - expectedValues.put("@vaadin/vaadin-split-layout", "4.1.1"); - expectedValues.put("@vaadin/vaadin-tabs", "3.0.5"); - - for (Map.Entry entry : expectedValues.entrySet()) { - Assert.assertEquals( - String.format("Got wrong version for '%s'", entry.getKey()), - entry.getValue(), filteredJson.getString(entry.getKey())); - } - } - - private void assertFilterPlatformVersions(String depKey) - throws IOException { - String versions = IOUtils.toString( - Objects.requireNonNull(getClass().getClassLoader() - .getResourceAsStream("versions/versions.json")), - StandardCharsets.UTF_8); - String pkgJson = IOUtils.toString( - Objects.requireNonNull(getClass().getClassLoader() - .getResourceAsStream("versions/package.json")), - StandardCharsets.UTF_8); - - VersionsJsonFilter filter = new VersionsJsonFilter(Json.parse(pkgJson), - depKey); - JsonObject filteredJson = filter.getFilteredVersions( - Json.parse(versions), "versions/versions.json"); - Assert.assertTrue(filteredJson.hasKey("@vaadin/vaadin-progress-bar")); - Assert.assertTrue(filteredJson.hasKey("@vaadin/vaadin-upload")); - Assert.assertTrue(filteredJson.hasKey("@polymer/iron-list")); - - Assert.assertEquals( - "'progress-bar' should be the same in package and versions", - "1.1.2", filteredJson.getString("@vaadin/vaadin-progress-bar")); - Assert.assertEquals( - "'upload' should be the same in package and versions", "4.2.2", - filteredJson.getString("@vaadin/vaadin-upload")); - Assert.assertEquals("'enforced' version should come from platform", - "1.5.0", filteredJson.getString("enforced")); - Assert.assertEquals("'iron-list' should be framework defined version", - "3.0.2", filteredJson.getString("@polymer/iron-list")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/DefaultArchiveExtractorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/DefaultArchiveExtractorTest.java deleted file mode 100644 index 28d5d2dd4b5..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/DefaultArchiveExtractorTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.vaadin.flow.server.frontend.installer; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; -import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class DefaultArchiveExtractorTest { - - public static final String ROOT_FILE = "root.file"; - public static final String SUBFOLDER_FILE = "subfolder/folder.file"; - @Rule - public final TemporaryFolder tmpDir = new TemporaryFolder(); - - private String baseDir; - private File targetDir; - - @Before - public void setup() { - baseDir = tmpDir.getRoot().getAbsolutePath(); - targetDir = new File(baseDir + "/extract"); - } - - @Test - public void extractZip_contentsAreExtracted() - throws IOException, ArchiveExtractionException { - File archiveFile = new File(baseDir, "archive.zip"); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - try (ZipOutputStream zipOutputStream = new ZipOutputStream( - Files.newOutputStream(tempArchive))) { - zipOutputStream.putNextEntry(new ZipEntry(ROOT_FILE)); - zipOutputStream.closeEntry(); - zipOutputStream.putNextEntry(new ZipEntry(SUBFOLDER_FILE)); - zipOutputStream.closeEntry(); - } - - new DefaultArchiveExtractor().extract(archiveFile, targetDir); - - Assert.assertTrue("Archive root.file was not extracted", - new File(targetDir, ROOT_FILE).exists()); - Assert.assertTrue("Archive subfolder/folder.file was not extracted", - new File(targetDir, SUBFOLDER_FILE).exists()); - } - - @Test - public void extractTarGz_contentsAreExtracted() - throws IOException, ArchiveExtractionException { - File archiveFile = new File(baseDir, "archive.tar.gz"); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - try (OutputStream fo = Files.newOutputStream(tempArchive); - OutputStream gzo = new GzipCompressorOutputStream(fo); - ArchiveOutputStream o = new TarArchiveOutputStream(gzo)) { - o.putArchiveEntry( - o.createArchiveEntry(new File(ROOT_FILE), ROOT_FILE)); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry(new File(SUBFOLDER_FILE), - SUBFOLDER_FILE)); - o.closeArchiveEntry(); - } - - new DefaultArchiveExtractor().extract(archiveFile, targetDir); - - Assert.assertTrue("Archive root.file was not extracted", - new File(targetDir, ROOT_FILE).exists()); - Assert.assertTrue("Archive subfolder/folder.file was not extracted", - new File(targetDir, SUBFOLDER_FILE).exists()); - } - - @Test(expected = ArchiveExtractionException.class) - public void extractTarAsZip_ArchiveExtractionExceptionIsThrown() - throws IOException, ArchiveExtractionException { - File archiveFile = new File(baseDir, "archive.zip"); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - try (OutputStream fo = Files.newOutputStream(tempArchive); - OutputStream gzo = new GzipCompressorOutputStream(fo); - ArchiveOutputStream o = new TarArchiveOutputStream(gzo)) { - o.putArchiveEntry( - o.createArchiveEntry(new File(ROOT_FILE), ROOT_FILE)); - o.closeArchiveEntry(); - } - - new DefaultArchiveExtractor().extract(archiveFile, targetDir); - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/DefaultFileDownloaderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/DefaultFileDownloaderTest.java deleted file mode 100644 index 2d23b728d10..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/DefaultFileDownloaderTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.vaadin.flow.server.frontend.installer; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Collections; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import com.vaadin.flow.server.frontend.FrontendTools; - -public class DefaultFileDownloaderTest { - - @Rule - public final TemporaryFolder tmpDir = new TemporaryFolder(); - - private String baseDir; - - @Before - public void setup() { - baseDir = tmpDir.getRoot().getAbsolutePath(); - } - - @Test - public void installNodeFromFileSystem_NodeIsInstalledToTargetDirectory() - throws IOException, DownloadException { - File targetDir = new File(baseDir + "/installation"); - - Assert.assertFalse( - "Clean test should not contain a installation folder", - targetDir.exists()); - File downloadDir = tmpDir.newFolder(FrontendTools.DEFAULT_NODE_VERSION); - String downloadFileName = "MyDownload.zip"; - - File archiveFile = new File(downloadDir, downloadFileName); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - DefaultFileDownloader downloader = new DefaultFileDownloader( - new ProxyConfig(Collections.emptyList())); - - downloader.download(tempArchive.toUri(), - new File(targetDir, downloadFileName), null, null); - - Assert.assertTrue("File was not 'downloaded' to target directory", - new File(targetDir, downloadFileName).exists()); - Assert.assertFalse( - "File 'downloaded' was a directory event though file expected", - new File(targetDir, downloadFileName).isDirectory()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/NodeInstallerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/NodeInstallerTest.java deleted file mode 100644 index 04f9079dcfb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/NodeInstallerTest.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.vaadin.flow.server.frontend.installer; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; -import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import com.vaadin.flow.server.frontend.FrontendTools; -import com.vaadin.flow.server.frontend.FrontendVersion; - -public class NodeInstallerTest { - - @Rule - public final TemporaryFolder tmpDir = new TemporaryFolder(); - - private String baseDir; - - @Before - public void setup() { - baseDir = tmpDir.getRoot().getAbsolutePath(); - } - - @Test - public void installNodeFromFileSystem_NodeIsInstalledToTargetDirectory() - throws IOException { - Platform platform = Platform.guess(); - String nodeExec = platform.isWindows() ? "node.exe" : "node"; - String prefix = String.format("node-%s-%s", - FrontendTools.DEFAULT_NODE_VERSION, - platform.getNodeClassifier(new FrontendVersion( - FrontendTools.DEFAULT_NODE_VERSION))); - - File targetDir = new File(baseDir + "/installation"); - - Assert.assertFalse( - "Clean test should not contain a installation folder", - targetDir.exists()); - File downloadDir = tmpDir.newFolder(FrontendTools.DEFAULT_NODE_VERSION); - File archiveFile = new File(downloadDir, - prefix + "." + platform.getArchiveExtension()); - archiveFile.createNewFile(); - Path tempArchive = archiveFile.toPath(); - - if (platform.getArchiveExtension().equals("zip")) { - try (ZipOutputStream zipOutputStream = new ZipOutputStream( - Files.newOutputStream(tempArchive))) { - zipOutputStream - .putNextEntry(new ZipEntry(prefix + "/" + nodeExec)); - zipOutputStream.closeEntry(); - zipOutputStream.putNextEntry( - new ZipEntry(prefix + "/node_modules/npm/bin/npm")); - zipOutputStream.closeEntry(); - zipOutputStream.putNextEntry( - new ZipEntry(prefix + "/node_modules/npm/bin/npm.cmd")); - zipOutputStream.closeEntry(); - } - } else { - try (OutputStream fo = Files.newOutputStream(tempArchive); - OutputStream gzo = new GzipCompressorOutputStream(fo); - ArchiveOutputStream o = new TarArchiveOutputStream(gzo)) { - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/bin/" + nodeExec), - prefix + "/bin/" + nodeExec)); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/bin/npm"), prefix + "/bin/npm")); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/lib/node_modules/npm/bin/npm"), - prefix + "/lib/node_modules/npm/bin/npm")); - o.closeArchiveEntry(); - o.putArchiveEntry(o.createArchiveEntry( - new File(prefix + "/lib/node_modules/npm/bin/npm.cmd"), - prefix + "/lib/node_modules/npm/bin/npm.cmd")); - o.closeArchiveEntry(); - } - } - - // add a file to node/node_modules_npm that should be cleaned out - File nodeDirectory = new File(targetDir, "node"); - String nodeModulesPath = platform.isWindows() ? "node_modules" - : "lib/node_modules"; - File nodeModulesDirectory = new File(nodeDirectory, nodeModulesPath); - File npmDirectory = new File(nodeModulesDirectory, "npm"); - File garbage = new File(npmDirectory, "garbage"); - FileUtils.forceMkdir(npmDirectory); - Assert.assertTrue("garbage file should be created", - garbage.createNewFile()); - - File oldNpm = new File(nodeDirectory, "node_modules/npm"); - File oldGarbage = new File(oldNpm, "oldGarbage"); - FileUtils.forceMkdir(oldNpm); - Assert.assertTrue("oldGarbage file should be created", - oldGarbage.createNewFile()); - - NodeInstaller nodeInstaller = new NodeInstaller(targetDir, - Collections.emptyList()) - .setNodeVersion(FrontendTools.DEFAULT_NODE_VERSION) - .setNodeDownloadRoot(new File(baseDir).toPath().toUri()); - - try { - nodeInstaller.install(); - } catch (InstallationException e) { - throw new IllegalStateException("Failed to install Node", e); - } - - Assert.assertTrue("npm should have been copied to node_modules", - new File(targetDir, "node/" + nodeExec).exists()); - String npmInstallPath = platform.isWindows() - ? "node/node_modules/npm/bin/npm" - : "node/lib/node_modules/npm/bin/npm"; - Assert.assertTrue("npm should have been copied to node_modules", - new File(targetDir, npmInstallPath).exists()); - Assert.assertFalse("old npm files should have been removed", - garbage.exists()); - Assert.assertFalse( - "old style node_modules files should have been removed", - oldGarbage.exists()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/PlatformTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/PlatformTest.java deleted file mode 100644 index f908bfea96d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/installer/PlatformTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.installer; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import com.vaadin.flow.server.frontend.FrontendVersion; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import static com.vaadin.flow.server.frontend.installer.NodeInstaller.DEFAULT_NODEJS_DOWNLOAD_ROOT; -import static com.vaadin.flow.server.frontend.installer.NodeInstaller.UNOFFICIAL_NODEJS_DOWNLOAD_ROOT; -import static com.vaadin.flow.server.frontend.installer.Platform.ALPINE_RELEASE_FILE_PATH; - -public class PlatformTest { - - @Test - public void testGuess_whenOsIsLinuxAndAlpineReleaseFileExists_unofficialNodeDownloadPathReturned() { - try (MockedStatic os = Mockito - .mockStatic(Platform.OS.class); - MockedStatic paths = Mockito.mockStatic(Paths.class); - MockedStatic files = Mockito.mockStatic(Files.class)) { - - os.when(Platform.OS::guess).thenReturn(Platform.OS.LINUX); - Path alpineReleaseFilePath = Paths.get(ALPINE_RELEASE_FILE_PATH); - paths.when(() -> Paths.get(ALPINE_RELEASE_FILE_PATH)) - .thenReturn(alpineReleaseFilePath); - files.when(() -> Files.exists(alpineReleaseFilePath)) - .thenReturn(true); - - Platform platform = Platform.guess(); - Assert.assertEquals(UNOFFICIAL_NODEJS_DOWNLOAD_ROOT, - platform.getNodeDownloadRoot()); - - FrontendVersion frontendVersion = Mockito - .mock(FrontendVersion.class); - Assert.assertTrue(platform.getNodeClassifier(frontendVersion) - .contains("-musl")); - } - } - - @Test - public void testGuess_whenOsIsLinuxAndAlpineReleaseFileDoesNotExist_officialNodeDownloadPathReturned() { - try (MockedStatic os = Mockito - .mockStatic(Platform.OS.class)) { - - os.when(Platform.OS::guess).thenReturn(Platform.OS.LINUX); - - Platform platform = Platform.guess(); - Assert.assertEquals(DEFAULT_NODEJS_DOWNLOAD_ROOT, - platform.getNodeDownloadRoot()); - - FrontendVersion frontendVersion = Mockito - .mock(FrontendVersion.class); - Assert.assertFalse(platform.getNodeClassifier(frontendVersion) - .contains("-musl")); - } - } - - @Test - public void testGuess_whenOsIsAnythingOtherThanLinuxAlpineRelease_officialNodeDownloadPathReturned() { - try (MockedStatic os = Mockito - .mockStatic(Platform.OS.class)) { - - os.when(Platform.OS::guess).thenReturn(Platform.OS.WINDOWS); - - Platform platform = Platform.guess(); - Assert.assertEquals(DEFAULT_NODEJS_DOWNLOAD_ROOT, - platform.getNodeDownloadRoot()); - - os.when(Platform.OS::guess).thenReturn(Platform.OS.MAC); - - platform = Platform.guess(); - Assert.assertEquals(DEFAULT_NODEJS_DOWNLOAD_ROOT, - platform.getNodeDownloadRoot()); - - os.when(Platform.OS::guess).thenReturn(Platform.OS.SUN_OS); - - platform = Platform.guess(); - Assert.assertEquals(DEFAULT_NODEJS_DOWNLOAD_ROOT, - platform.getNodeDownloadRoot()); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/AbstractScannerPwaTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/AbstractScannerPwaTest.java deleted file mode 100644 index 10fb9d15ea5..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/AbstractScannerPwaTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner; - -import org.junit.Test; - -import com.vaadin.flow.server.PwaConfiguration; -import com.vaadin.flow.server.frontend.scanner.samples.pwa.AnotherAppShellWithPwa; -import com.vaadin.flow.server.frontend.scanner.samples.pwa.AppShellWithPwa; -import com.vaadin.flow.server.frontend.scanner.samples.pwa.AppShellWithoutPwa; -import com.vaadin.flow.server.frontend.scanner.samples.pwa.NonAppShellWithPwa; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -public abstract class AbstractScannerPwaTest { - abstract protected PwaConfiguration getPwaConfiguration(Class... classes) - throws Exception; - - @Test - public void should_findPwaOnAppShell() throws Exception { - PwaConfiguration pwaConfiguration = getPwaConfiguration( - AppShellWithPwa.class); - assertEquals("PWA Application", pwaConfiguration.getAppName()); - assertEquals("PWA", pwaConfiguration.getShortName()); - assertEquals("Testing PWA", pwaConfiguration.getDescription()); - assertEquals("minimal-ui", pwaConfiguration.getDisplay()); - assertEquals("#eee", pwaConfiguration.getBackgroundColor()); - assertEquals("#369", pwaConfiguration.getThemeColor()); - assertEquals("pwa.png", pwaConfiguration.getIconPath()); - assertEquals("appmanifest.json", pwaConfiguration.getManifestPath()); - assertEquals("pwa.html", pwaConfiguration.getOfflinePath()); - String[] expectedOfflineResources = { "pwa.js", "pwa.css" }; - assertArrayEquals(expectedOfflineResources, - pwaConfiguration.getOfflineResources().toArray()); - } - - @Test - public void should_returnDefaultConfiguration_When_AppShellWithoutPwa() - throws Exception { - PwaConfiguration pwaConfiguration = getPwaConfiguration( - AppShellWithoutPwa.class); - assertEquals(PwaConfiguration.DEFAULT_NAME, - pwaConfiguration.getAppName()); - assertEquals("Flow PWA", pwaConfiguration.getShortName()); - assertEquals("", pwaConfiguration.getDescription()); - assertEquals(PwaConfiguration.DEFAULT_DISPLAY, - pwaConfiguration.getDisplay()); - assertEquals(PwaConfiguration.DEFAULT_BACKGROUND_COLOR, - pwaConfiguration.getBackgroundColor()); - assertEquals(PwaConfiguration.DEFAULT_THEME_COLOR, - pwaConfiguration.getThemeColor()); - assertEquals(PwaConfiguration.DEFAULT_ICON, - pwaConfiguration.getIconPath()); - assertEquals(PwaConfiguration.DEFAULT_PATH, - pwaConfiguration.getManifestPath()); - assertEquals(PwaConfiguration.DEFAULT_OFFLINE_PATH, - pwaConfiguration.getOfflinePath()); - String[] defaultOfflineResources = {}; - assertArrayEquals(defaultOfflineResources, - pwaConfiguration.getOfflineResources().toArray()); - } - - @Test - public void should_returnDefaultConfiguration_When_NoAppShell() - throws Exception { - PwaConfiguration pwaConfiguration = getPwaConfiguration( - this.getClass()); - assertEquals(PwaConfiguration.DEFAULT_NAME, - pwaConfiguration.getAppName()); - assertEquals("Flow PWA", pwaConfiguration.getShortName()); - assertEquals("", pwaConfiguration.getDescription()); - assertEquals(PwaConfiguration.DEFAULT_DISPLAY, - pwaConfiguration.getDisplay()); - assertEquals(PwaConfiguration.DEFAULT_BACKGROUND_COLOR, - pwaConfiguration.getBackgroundColor()); - assertEquals(PwaConfiguration.DEFAULT_THEME_COLOR, - pwaConfiguration.getThemeColor()); - assertEquals(PwaConfiguration.DEFAULT_ICON, - pwaConfiguration.getIconPath()); - assertEquals(PwaConfiguration.DEFAULT_PATH, - pwaConfiguration.getManifestPath()); - assertEquals(PwaConfiguration.DEFAULT_OFFLINE_PATH, - pwaConfiguration.getOfflinePath()); - String[] defaultOfflineResources = {}; - assertArrayEquals(defaultOfflineResources, - pwaConfiguration.getOfflineResources().toArray()); - } - - @Test(expected = IllegalStateException.class) - public void should_throw_When_PwaNotOnAppShell() throws Exception { - getPwaConfiguration(NonAppShellWithPwa.class); - } - - @Test(expected = IllegalStateException.class) - public void should_throw_When_MultipleAppShellPwa() throws Exception { - getPwaConfiguration(AppShellWithPwa.class, - AnotherAppShellWithPwa.class); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ClassFinderTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ClassFinderTest.java deleted file mode 100644 index 110bbff741a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ClassFinderTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.vaadin.flow.server.frontend.scanner; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.vaadin.flow.server.frontend.NodeTestComponents; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Component1; - -public class ClassFinderTest { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private static class TestList extends ArrayList { - - } - - @Test - public void should_Fail_when_DifferentClasLoader() throws Exception { - ClassLoader loader = new ClassLoader() { - @Override - public Class loadClass(String name) - throws ClassNotFoundException { - throw new ClassNotFoundException(); - } - }; - - exception.expect(ClassNotFoundException.class); - DefaultClassFinder finder = new DefaultClassFinder(loader, - Component1.class); - finder.loadClass(Component1.class.getName()); - } - - @Test - public void should_LoadClasses() throws Exception { - DefaultClassFinder finder = new DefaultClassFinder( - new HashSet<>(Arrays.asList(Component1.class))); - Assert.assertNotNull(finder.loadClass(Component1.class.getName())); - } - - @Test - public void should_LoadClasses_when_NoClassListProvided() throws Exception { - DefaultClassFinder finder = new DefaultClassFinder( - Collections.emptySet()); - Assert.assertNotNull(finder.loadClass(Component1.class.getName())); - } - - @Test - public void getSubTypesOf_returnsPlainSubtypes() { - DefaultClassFinder finder = new DefaultClassFinder(new HashSet<>( - Arrays.asList(Double.class, Integer.class, String.class))); - Set> subTypes = finder - .getSubTypesOf(Number.class); - Assert.assertEquals(2, subTypes.size()); - Assert.assertTrue(subTypes.contains(Double.class)); - Assert.assertTrue(subTypes.contains(Integer.class)); - } - - @Test - public void getSubTypesOf_returnsGenericSubtypes() { - DefaultClassFinder finder = new DefaultClassFinder(new HashSet<>( - Arrays.asList(ArrayList.class, TestList.class, String.class))); - Set> subTypes = finder.getSubTypesOf(List.class); - Assert.assertEquals(2, subTypes.size()); - Assert.assertTrue(subTypes.contains(ArrayList.class)); - Assert.assertTrue(subTypes.contains(TestList.class)); - } - - @Test - public void orderIsDeterministic() { - Set> testClasses = new HashSet<>(); - testClasses.add(NodeTestComponents.ExtraImport.class); - testClasses.add(NodeTestComponents.VaadinBowerComponent.class); - testClasses.add(NodeTestComponents.TranslatedImports.class); - Set> allClasses = new DefaultClassFinder(testClasses) - .getSubTypesOf(Object.class); - LinkedHashSet> expected = new LinkedHashSet<>(); - expected.add(NodeTestComponents.ExtraImport.class); - expected.add(NodeTestComponents.TranslatedImports.class); - expected.add(NodeTestComponents.VaadinBowerComponent.class); - Assert.assertEquals(expected, allClasses); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendDependenciesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendDependenciesTest.java deleted file mode 100644 index 0977d8c30be..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendDependenciesTest.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.NotFoundException; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.server.UIInitListener; -import com.vaadin.flow.server.VaadinServiceInitListener; -import com.vaadin.flow.server.frontend.scanner.samples.ErrorComponent; -import com.vaadin.flow.server.frontend.scanner.samples.JsOrderComponent; -import com.vaadin.flow.server.frontend.scanner.samples.MyServiceListener; -import com.vaadin.flow.server.frontend.scanner.samples.MyUIInitListener; -import com.vaadin.flow.server.frontend.scanner.samples.RouteComponent; -import com.vaadin.flow.server.frontend.scanner.samples.RouteComponentWithLayout; -import com.vaadin.flow.server.frontend.scanner.samples.RouteComponentWithMethodReference; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.Theme; -import com.vaadin.flow.theme.ThemeDefinition; - -public class FrontendDependenciesTest { - - private ClassFinder classFinder = Mockito.mock(ClassFinder.class); - - @Before - public void setUp() throws ClassNotFoundException { - Mockito.when(classFinder.loadClass(Route.class.getName())) - .thenReturn((Class) Route.class); - - Mockito.when(classFinder.loadClass(UIInitListener.class.getName())) - .thenReturn((Class) UIInitListener.class); - - Mockito.when(classFinder - .loadClass(VaadinServiceInitListener.class.getName())) - .thenReturn((Class) VaadinServiceInitListener.class); - - Mockito.when( - classFinder.loadClass(WebComponentExporter.class.getName())) - .thenReturn((Class) WebComponentExporter.class); - - Mockito.when(classFinder.loadClass(HasErrorParameter.class.getName())) - .thenReturn((Class) HasErrorParameter.class); - - Mockito.when(classFinder.loadClass(FrontendDependencies.LUMO)) - .thenReturn((Class) FakeLumo.class); - - Mockito.when( - classFinder.loadClass(AppShellConfigurator.class.getName())) - .thenReturn((Class) AppShellConfigurator.class); - - Mockito.doAnswer(invocation -> FrontendDependenciesTest.class - .getClassLoader().getResource(invocation.getArgument(0))) - .when(classFinder).getResource(Mockito.anyString()); - - Mockito.when(classFinder.loadClass(UI.class.getName())) - .thenReturn((Class) UI.class); - } - - @Test - public void routedComponent_endpointsAreCollected() { - Mockito.when(classFinder.getAnnotatedClasses(Route.class)) - .thenReturn(Collections.singleton(RouteComponent.class)); - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - List modules = dependencies.getModules(); - Assert.assertTrue(1 <= modules.size()); - Assert.assertTrue(modules.contains("foo.js")); - - Set scripts = dependencies.getScripts(); - Assert.assertEquals(1, scripts.size()); - Assert.assertEquals("bar.js", scripts.iterator().next()); - } - - @Test - public void appShellConfigurator_collectedAsEndpoint() - throws ClassNotFoundException { - Mockito.when(classFinder.getSubTypesOf(AppShellConfigurator.class)) - .thenReturn(Collections.singleton(MyAppShell.class)); - Mockito.when(classFinder.loadClass(FakeLumo.class.getName())) - .thenReturn((Class) FakeLumo.class); - - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - - Assert.assertEquals("UI and AppShell should be found", 2, - dependencies.getEndPoints().size()); - - AbstractTheme theme = dependencies.getTheme(); - Assert.assertNotNull("Theme not found in endpoint", theme); - - ThemeDefinition themeDefinition = dependencies.getThemeDefinition(); - Assert.assertNotNull("ThemeDefinition is not filled", themeDefinition); - Assert.assertEquals(FakeLumo.class, themeDefinition.getTheme()); - } - - @Test - public void themeDefiningClassAndName_throwsException() - throws ClassNotFoundException { - Mockito.when(classFinder.getSubTypesOf(AppShellConfigurator.class)) - .thenReturn(Collections.singleton(FaultyThemeAnnotation.class)); - Mockito.when(classFinder.loadClass(FakeLumo.class.getName())) - .thenReturn((Class) FakeLumo.class); - - IllegalStateException exception = Assert.assertThrows( - IllegalStateException.class, - () -> new FrontendDependencies(classFinder, false)); - - Assert.assertEquals("Unexpected message for the thrown exception", - "Theme name and theme class can not both be specified. " - + "Theme name uses Lumo and can not be used in combination with custom theme class.", - exception.getMessage()); - } - - @Test - public void noDefaultThemeAvailable_throwsException() - throws ClassNotFoundException { - Mockito.when(classFinder.getSubTypesOf(AppShellConfigurator.class)) - .thenReturn(Collections.singleton(MyAppThemeShell.class)); - Mockito.when(classFinder.loadClass(FrontendDependencies.LUMO)) - .thenThrow(ClassNotFoundException.class); - - IllegalStateException exception = Assert.assertThrows( - IllegalStateException.class, - () -> new FrontendDependencies(classFinder, false)); - - Assert.assertEquals("Thrown exception didn't contain correct message", - "Lumo dependency needs to be available on the classpath when using a theme name.", - exception.getMessage()); - } - - @Test - public void appThemeDefined_getsLumoAsTheme() { - Mockito.when(classFinder.getSubTypesOf(AppShellConfigurator.class)) - .thenReturn(Collections.singleton(MyAppThemeShell.class)); - - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - - Assert.assertEquals("Faulty default theme received", FakeLumo.class, - dependencies.getThemeDefinition().getTheme()); - - } - - @Test - public void hasErrorParameterComponent_endpointIsCollected() { - Mockito.when(classFinder.getSubTypesOf(HasErrorParameter.class)) - .thenReturn(Collections.singleton(ErrorComponent.class)); - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - List modules = dependencies.getModules(); - Assert.assertTrue(1 <= modules.size()); - Assert.assertTrue(modules.contains("./src/bar.js")); - - Set scripts = dependencies.getScripts(); - Assert.assertEquals(1, scripts.size()); - Assert.assertEquals("./src/baz.js", scripts.iterator().next()); - } - - @Test - public void componentInsideUiInitListener_endpointsAreCollected() { - Mockito.when(classFinder.getSubTypesOf(UIInitListener.class)) - .thenReturn(Collections.singleton(MyUIInitListener.class)); - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - List modules = dependencies.getModules(); - Assert.assertTrue(1 <= modules.size()); - Assert.assertTrue(modules.contains("baz.js")); - - Set scripts = dependencies.getScripts(); - Assert.assertEquals(1, scripts.size()); - Assert.assertEquals("foobar.js", scripts.iterator().next()); - } - - @Test - public void componentInsideUiInitListenerInsideServiceInitListener_endpointsAreCollected() { - Mockito.when(classFinder.getSubTypesOf(VaadinServiceInitListener.class)) - .thenReturn(Collections.singleton(MyServiceListener.class)); - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - List modules = dependencies.getModules(); - Assert.assertTrue(1 <= modules.size()); - Assert.assertTrue(modules.contains("baz.js")); - - Set scripts = dependencies.getScripts(); - Assert.assertEquals(1, scripts.size()); - Assert.assertEquals("foobar.js", scripts.iterator().next()); - } - - @Test - public void jsScriptOrderIsPreserved() { - Mockito.when(classFinder.getAnnotatedClasses(Route.class)) - .thenReturn(Collections.singleton(JsOrderComponent.class)); - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - - Set scripts = dependencies.getScripts(); - Assert.assertEquals(LinkedHashSet.class, scripts.getClass()); - - Assert.assertEquals(new ArrayList<>(dependencies.getScripts()), - Arrays.asList("a.js", "b.js", "c.js")); - } - - // flow #6408 - @Test - public void annotationsInRouterLayoutWontBeFlaggedAsBelongingToTheme() { - Mockito.when(classFinder.getAnnotatedClasses(Route.class)).thenReturn( - Collections.singleton(RouteComponentWithLayout.class)); - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - - List modules = dependencies.getModules(); - Assert.assertEquals("Theme's annotations should come first", - "theme-foo.js", modules.get(0)); - } - - // flow #6524 - @Test - public void extractsAndScansClassesFromMethodReferences() { - Mockito.when(classFinder.getAnnotatedClasses(Route.class)).thenReturn( - Collections.singleton(RouteComponentWithMethodReference.class)); - - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - - List modules = dependencies.getModules(); - Assert.assertTrue(3 <= modules.size()); - Assert.assertTrue(modules.contains("foo.js")); - Assert.assertTrue(modules.contains("bar.js")); - Assert.assertTrue(modules.contains("baz.js")); - } - - @Test - public void defaultThemeIsLoadedForExporters() throws Exception { - FakeLumo.class.newInstance(); - Mockito.when(classFinder.getSubTypesOf(WebComponentExporter.class)) - .thenReturn(Stream.of(MyExporter.class) - .collect(Collectors.toSet())); - - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, true); - - Assert.assertNotNull(dependencies.getTheme()); - Assert.assertNotNull(dependencies.getThemeDefinition()); - } - - @Test // #9861 - public void collectEndpoints_uiIsAlwaysCollected() { - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - - Assert.assertEquals("UI should be visited found", 1, - dependencies.getEndPoints().size()); - } - - @Test // #9861 - public void classInMultipleEndpoints_collectEndpointsNotOverrideInitial() { - // Reference found through first endpoint - Mockito.when(classFinder.getAnnotatedClasses(Route.class)) - .thenReturn(Collections.singleton(TestRoute.class)); - // Reference found through second endpoint, should not clear - Mockito.when(classFinder.getSubTypesOf(HasErrorParameter.class)) - .thenReturn(Collections.singleton(TestRoute.class)); - - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, false); - List modules = dependencies.getModules(); - - Assert.assertEquals("Should contain UI and Referenced modules", 2, - modules.size()); - Assert.assertTrue(modules.contains("reference.js")); - } - - @Test // #9861 - public void visitedExporter_previousEndpointsNotOverridden() - throws InstantiationException, IllegalAccessException { - - FakeLumo.class.newInstance(); - // Reference found through first endpoint - Mockito.when(classFinder.getAnnotatedClasses(Route.class)) - .thenReturn(Collections.singleton(ReferenceExporter.class)); - // Re-visit through exporter. - Mockito.when(classFinder.getSubTypesOf(WebComponentExporter.class)) - .thenReturn(Stream.of(ReferenceExporter.class) - .collect(Collectors.toSet())); - - FrontendDependencies dependencies = new FrontendDependencies( - classFinder, true); - - List modules = dependencies.getModules(); - - Assert.assertEquals(3, dependencies.getEndPoints().size()); - Assert.assertEquals("Should contain UI and Referenced modules", 2, - modules.size()); - Assert.assertTrue(modules.contains("reference.js")); - } - - public static class MyComponent extends Component { - } - - public static class MyExporter extends WebComponentExporter { - public MyExporter() { - super("tag-tag"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - MyComponent component) { - } - } - - public static class FakeLumo implements AbstractTheme { - public FakeLumo() { - } - - @Override - public String getBaseUrl() { - return null; - } - - @Override - public String getThemeUrl() { - return null; - } - } - - @Theme(themeClass = FakeLumo.class) - public static class MyAppShell implements AppShellConfigurator { - } - - @Theme("my-theme") - public static class MyAppThemeShell implements AppShellConfigurator { - } - - @Theme(value = "my-theme", themeClass = FakeLumo.class) - public static class FaultyThemeAnnotation implements AppShellConfigurator { - } - - @JsModule("reference.js") - @Tag("div") - public static class Referenced extends Component { - } - - @Route("reference") - public static class ReferenceExporter - extends WebComponentExporter { - public ReferenceExporter() { - super("tag-tag"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - MyComponent component) { - Referenced ref = new Referenced(); - } - } - - @Route("reference") - @Tag("div") - public static class TestRoute extends Component - implements HasErrorParameter { - Referenced ref; - - public TestRoute() { - ref = new Referenced(); - } - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 0; - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendScannerPwaTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendScannerPwaTest.java deleted file mode 100644 index 28d2f9a4e3d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FrontendScannerPwaTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.vaadin.flow.server.frontend.scanner; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; - -import com.vaadin.flow.server.PwaConfiguration; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; - -public class FrontendScannerPwaTest extends AbstractScannerPwaTest { - protected PwaConfiguration getPwaConfiguration(Class... classes) - throws Exception { - FrontendDependencies frontendDependencies = new FrontendDependencies( - new DefaultClassFinder(new HashSet<>( - new ArrayList<>(Arrays.asList(classes))))); - return frontendDependencies.getPwaConfiguration(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FullDependenciesScannerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FullDependenciesScannerTest.java deleted file mode 100644 index 4eab700da6c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FullDependenciesScannerTest.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.component.dependency.NpmPackage; -import com.vaadin.flow.function.SerializableBiFunction; -import com.vaadin.flow.server.frontend.NodeTestComponents; -import com.vaadin.flow.server.frontend.NodeTestComponents.ExtraImport; -import com.vaadin.flow.server.frontend.NodeTestComponents.FlatImport; -import com.vaadin.flow.server.frontend.NodeTestComponents.JavaScriptOrder; -import com.vaadin.flow.server.frontend.NodeTestComponents.LocalP3Template; -import com.vaadin.flow.server.frontend.NodeTestComponents.LocalTemplate; -import com.vaadin.flow.server.frontend.NodeTestComponents.LumoTest; -import com.vaadin.flow.server.frontend.NodeTestComponents.MainLayout; -import com.vaadin.flow.server.frontend.NodeTestComponents.UnresolvedComponent; -import com.vaadin.flow.server.frontend.NodeTestComponents.VaadinBowerComponent; -import com.vaadin.flow.server.frontend.NodeTestComponents.VaadinElementMixin; -import com.vaadin.flow.server.frontend.NodeTestComponents.VaadinMixedComponent; -import com.vaadin.flow.server.frontend.NodeTestComponents.VaadinNpmComponent; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.NoTheme; -import com.vaadin.flow.theme.Theme; - -public class FullDependenciesScannerTest { - - private ClassFinder finder = Mockito.mock(ClassFinder.class); - - @JsModule("./foo-bar-baz.js") - public static class FakeLumoTheme implements AbstractTheme { - - @Override - public String getBaseUrl() { - return "foo"; - } - - @Override - public String getThemeUrl() { - return null; - } - - } - - @Theme(themeClass = FakeLumoTheme.class) - public static class ThemedComponent extends Component { - - } - - @NoTheme - private static class NoThemeComponent extends Component { - - } - - @NoTheme - private static class NoThemeComponent1 extends Component { - - } - - @Before - public void setUp() throws ClassNotFoundException { - Mockito.when(finder.loadClass(AbstractTheme.class.getName())) - .thenReturn((Class) AbstractTheme.class); - } - - @Test - public void getTheme_noExplicitTheme_lumoThemeIsDiscovered() - throws ClassNotFoundException { - FrontendDependenciesScanner scanner = setUpThemeScanner( - Collections.emptySet(), Collections.emptySet(), - (type, annotationType) -> Collections.emptyList()); - - Mockito.verify(finder).loadClass(AbstractTheme.class.getName()); - - Assert.assertNotNull(scanner.getTheme()); - Assert.assertEquals("foo", scanner.getTheme().getBaseUrl()); - Assert.assertEquals(FakeLumoTheme.class, - scanner.getThemeDefinition().getTheme()); - Assert.assertEquals("", scanner.getThemeDefinition().getVariant()); - - Assert.assertEquals(0, scanner.getClasses().size()); - } - - @Test - public void getTheme_noTheme_noThemeIsDiscovered() - throws ClassNotFoundException { - FrontendDependenciesScanner scanner = setUpThemeScanner( - Collections.emptySet(), - new HashSet<>(Arrays.asList(NoThemeComponent.class, - NoThemeComponent1.class)), - (type, annotationType) -> Collections.emptyList()); - - Mockito.verify(finder).loadClass(AbstractTheme.class.getName()); - - Assert.assertNull(scanner.getTheme()); - Assert.assertNull(scanner.getThemeDefinition()); - Assert.assertEquals(0, scanner.getClasses().size()); - } - - @Test - public void getTheme_explicitTheme_themeIsDiscovered() - throws ClassNotFoundException { - Mockito.when(finder.loadClass(LumoTest.class.getName())) - .thenReturn((Class) LumoTest.class); - - FrontendDependenciesScanner scanner = setUpThemeScanner( - getAnnotatedClasses(Theme.class), Collections.emptySet(), - (type, annotationType) -> findAnnotations(type, Theme.class)); - - Mockito.verify(finder).loadClass(AbstractTheme.class.getName()); - - Assert.assertNotNull(scanner.getTheme()); - Assert.assertEquals("theme/lumo/", scanner.getTheme().getThemeUrl()); - Assert.assertEquals(LumoTest.class, - scanner.getThemeDefinition().getTheme()); - Assert.assertEquals("dark", scanner.getThemeDefinition().getVariant()); - Assert.assertEquals(0, scanner.getClasses().size()); - } - - @Test(expected = IllegalStateException.class) - public void getTheme_noThemeAndExplicitTheme_throws() - throws ClassNotFoundException { - setUpThemeScanner(getAnnotatedClasses(Theme.class), - Collections.singleton(NoThemeComponent.class), - (type, annotationType) -> findAnnotations(type, Theme.class)); - } - - @Test(expected = IllegalStateException.class) - public void getTheme_severalExplicitThemes_throws() - throws ClassNotFoundException { - Set> themeAnnotatedClasses = getAnnotatedClasses(Theme.class); - themeAnnotatedClasses.add(ThemedComponent.class); - setUpThemeScanner(themeAnnotatedClasses, Collections.emptySet(), - (type, annotationType) -> findAnnotations(type, Theme.class)); - } - - @Test - public void getPackages_returnsAllPackages_getClassesReturnAllPackageAnnotatedComponents() - throws ClassNotFoundException { - FrontendDependenciesScanner scanner = setUpAnnotationScanner( - NpmPackage.class); - - Map packages = scanner.getPackages(); - - Assert.assertEquals(packages.get("@vaadin/vaadin-button"), "1.1.1"); - Assert.assertEquals(packages.get("@vaadin/vaadin-element-mixin"), - "1.1.2"); - Assert.assertEquals(packages.get("@foo/var-component"), "1.1.0"); - Assert.assertEquals(packages.get("@webcomponents/webcomponentsjs"), - "2.2.10"); - - Assert.assertEquals(4, packages.size()); - - Set visitedClasses = scanner.getClasses(); - Assert.assertTrue( - visitedClasses.contains(LocalP3Template.class.getName())); - Assert.assertTrue(visitedClasses - .contains(NodeTestComponents.BUTTON_COMPONENT_FQN)); - Assert.assertTrue( - visitedClasses.contains(VaadinElementMixin.class.getName())); - Assert.assertTrue(visitedClasses.contains(ExtraImport.class.getName())); - } - - @Test - public void getScripts_returnAllScripts_orderPerClassIsPreserved_getClassesReturnAllJSAnnotatedComponents() - throws ClassNotFoundException { - FrontendDependenciesScanner scanner = setUpAnnotationScanner( - JavaScript.class); - - Set scripts = scanner.getScripts(); - Assert.assertTrue(scripts.contains("javascript/a.js")); - Assert.assertTrue(scripts.contains("javascript/b.js")); - Assert.assertTrue(scripts.contains("javascript/c.js")); - - Assert.assertTrue(scripts.contains("ExampleConnector.js")); - - Assert.assertEquals(5, scripts.size()); - - List orderedJs = scripts.stream() - .filter(script -> script.startsWith("javascript")) - .collect(Collectors.toList()); - Assert.assertEquals(orderedJs.get(0), "javascript/a.js"); - Assert.assertEquals(orderedJs.get(1), "javascript/b.js"); - Assert.assertEquals(orderedJs.get(2), "javascript/c.js"); - - Set visitedClasses = scanner.getClasses(); - Assert.assertTrue( - visitedClasses.contains(VaadinBowerComponent.class.getName())); - Assert.assertTrue( - visitedClasses.contains(JavaScriptOrder.class.getName())); - } - - @Test - public void getCss_returnAllCss_orderPerClassIsPreserved_getClassesReturnAllCssAnnotatedComponents() - throws ClassNotFoundException { - FrontendDependenciesScanner scanner = setUpAnnotationScanner( - CssImport.class); - - List css = new ArrayList<>(scanner.getCss()); - - Assert.assertEquals(7, css.size()); - Assert.assertEquals( - createCssData("@vaadin/vaadin-mixed-component/bar.css", null, - null, null), - css.get(0)); - Assert.assertEquals(createCssData("./foo.css", null, null, null), - css.get(1)); - Assert.assertEquals(createCssData("./foo.css", null, "bar", null), - css.get(2)); - Assert.assertEquals(createCssData("./foo.css", "baz", null, null), - css.get(3)); - Assert.assertEquals(createCssData("./foo.css", "baz", "bar", null), - css.get(4)); - Assert.assertEquals(createCssData("./foo.css", null, null, "foo-bar"), - css.get(5)); - Assert.assertEquals(createCssData("./foo.css", null, "bar", "foo-bar"), - css.get(6)); - - Set visitedClasses = scanner.getClasses(); - Assert.assertEquals(1, visitedClasses.size()); - Assert.assertEquals(FlatImport.class.getName(), - visitedClasses.iterator().next()); - } - - @Test - public void getModules_noTheme_returnAllNoThemeModules_orderPerClassIsPreserved_getClassesReturnAllModuleAnnotatedComponents() - throws ClassNotFoundException { - FrontendDependenciesScanner scanner = setUpAnnotationScanner( - JsModule.class); - List modules = scanner.getModules(); - - Assert.assertEquals(19, modules.size()); - - assertJsModules(modules); - - Set classes = scanner.getClasses(); - Assert.assertEquals(13, classes.size()); - - assertJsModulesClasses(classes); - Assert.assertFalse(classes.contains(LumoTest.class.getName())); - } - - @Test - public void getModules_explcitTheme_returnAllModulesExcludingNotUsedTheme_getClassesReturnAllModuleAnnotatedComponents() - throws ClassNotFoundException { - // use this fake/mock class for the loaded class to check that annotated - // classes are requested for the loaded class and not for the - // annotationType - Class clazz = Object.class; - - Mockito.when(finder.loadClass(JsModule.class.getName())) - .thenReturn(clazz); - - Mockito.when(finder.getAnnotatedClasses(clazz)) - .thenReturn(getAnnotatedClasses(JsModule.class)); - - Class themeClass = Throwable.class; - - Mockito.when(finder.loadClass(Theme.class.getName())) - .thenReturn(themeClass); - - Set> themeClasses = getAnnotatedClasses(Theme.class); - themeClasses.add(FakeLumoTheme.class); - Mockito.when(finder.getAnnotatedClasses(themeClass)) - .thenReturn(themeClasses); - Assert.assertTrue(themeClasses.size() >= 2); - - Mockito.when(finder.loadClass(LumoTest.class.getName())) - .thenReturn((Class) LumoTest.class); - Mockito.when(finder.loadClass(FakeLumoTheme.class.getName())) - .thenReturn((Class) FakeLumoTheme.class); - - FrontendDependenciesScanner scanner = new FullDependenciesScanner( - finder, (type, annotation) -> { - if (annotation.equals(clazz)) { - return findAnnotations(type, JsModule.class); - } else if (annotation.equals(themeClass)) { - return findAnnotations(type, Theme.class); - } - Assert.fail(); - return null; - }, false, null, false); - - List modules = scanner.getModules(); - Assert.assertEquals(25, modules.size()); - assertJsModules(modules); - - // Theme modules should be included now - Assert.assertTrue( - modules.contains("@vaadin/vaadin-lumo-styles/color.js")); - Assert.assertTrue( - modules.contains("@vaadin/vaadin-lumo-styles/typography.js")); - Assert.assertTrue( - modules.contains("@vaadin/vaadin-lumo-styles/sizing.js")); - Assert.assertTrue( - modules.contains("@vaadin/vaadin-lumo-styles/spacing.js")); - Assert.assertTrue( - modules.contains("@vaadin/vaadin-lumo-styles/style.js")); - Assert.assertTrue( - modules.contains("@vaadin/vaadin-lumo-styles/icons.js")); - - // not used theme module is not included - Assert.assertFalse(modules.contains("./foo-bar-baz.js")); - - Set classes = scanner.getClasses(); - Assert.assertEquals(14, classes.size()); - - assertJsModulesClasses(classes); - Assert.assertTrue(classes.contains(LumoTest.class.getName())); - Assert.assertFalse(classes.contains(FakeLumoTheme.class.getName())); - } - - private CssData createCssData(String value, String id, String include, - String themefor) { - CssData data = new CssData(); - data.value = value; - data.id = id; - data.include = include; - data.themefor = themefor; - return data; - } - - private List findAnnotations(Class type, - Class annotationType) { - return Arrays.asList(type.getAnnotationsByType(annotationType)); - } - - private Set> getAnnotatedClasses( - Class annotationType) { - Class[] classes = NodeTestComponents.class.getDeclaredClasses(); - Set> result = new HashSet<>(); - for (Class clazz : classes) { - if (clazz.getAnnotationsByType(annotationType).length > 0) { - result.add(clazz); - } - } - return result; - } - - private FullDependenciesScanner setUpAnnotationScanner( - Class annotationType) - throws ClassNotFoundException { - // use this fake/mock class for the loaded class to check that annotated - // classes are requested for the loaded class and not for the - // annotationType - Class clazz = Object.class; - - Mockito.when(finder.loadClass(annotationType.getName())) - .thenReturn(clazz); - - Mockito.when(finder.getAnnotatedClasses(clazz)) - .thenReturn(getAnnotatedClasses(annotationType)); - - return new FullDependenciesScanner(finder, - (type, annotation) -> findAnnotations(type, annotationType), - false, null, false); - } - - private FullDependenciesScanner setUpThemeScanner( - Set> themedClasses, Set> noThemeClasses, - SerializableBiFunction, Class, List> annotationFinder) - throws ClassNotFoundException { - Class fakeThemeClass = Object.class; - Class fakeNoThemeClass = Throwable.class; - - Mockito.when(finder.loadClass(Theme.class.getName())) - .thenReturn(fakeThemeClass); - Mockito.when(finder.loadClass(NoTheme.class.getName())) - .thenReturn(fakeNoThemeClass); - - Mockito.when(finder.getAnnotatedClasses(fakeThemeClass)) - .thenReturn(themedClasses); - Mockito.when(finder.getAnnotatedClasses(fakeNoThemeClass)) - .thenReturn(noThemeClasses); - - return new FullDependenciesScanner(finder, annotationFinder, false, - null, false) { - @Override - protected Class getLumoTheme() { - return FakeLumoTheme.class; - } - }; - } - - private void assertJsModules(List modules) { - Assert.assertTrue(modules.contains("@polymer/iron-icon/iron-icon.js")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-date-picker/src/vaadin-date-picker.js")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-date-picker/src/vaadin-month-calendar.js")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-element-mixin/vaadin-element-mixin.js")); - Assert.assertTrue( - modules.contains("./foo-dir/vaadin-npm-component.js")); - Assert.assertTrue(modules.contains( - "vaadin-mixed-component/src/vaadin-mixed-component.js")); - Assert.assertTrue(modules.contains("./local-template.js")); - Assert.assertTrue(modules.contains("3rdparty/component.js")); - Assert.assertTrue(modules.contains("./local-p3-template.js")); - Assert.assertTrue(modules.contains("unresolved/component")); - Assert.assertTrue(modules.contains("./foo.js")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-mixed-component/src/vaadin-mixed-component.js")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-mixed-component/src/vaadin-something-else.js")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-mixed-component/src/vaadin-something-else")); - Assert.assertTrue(modules.contains( - "@vaadin/vaadin-mixed-component/src/vaadin-custom-themed-component.js")); - Assert.assertTrue(modules.contains("./common-js-file.js")); - Assert.assertTrue(modules.contains("jsmodule/g.js")); - - // Check the order for VaadinBowerComponent class - List modulesPerClass = modules.stream().filter( - module -> module.startsWith("@vaadin/vaadin-date-picker")) - .collect(Collectors.toList()); - Assert.assertEquals( - "@vaadin/vaadin-date-picker/src/vaadin-date-picker.js", - modulesPerClass.get(0)); - Assert.assertEquals( - "@vaadin/vaadin-date-picker/src/vaadin-month-calendar.js", - modulesPerClass.get(1)); - - // Check the order for TranslatedImports class - modulesPerClass = modules.stream().filter( - module -> module.startsWith("@vaadin/vaadin-mixed-component")) - .collect(Collectors.toList()); - Assert.assertEquals( - "@vaadin/vaadin-mixed-component/src/vaadin-mixed-component.js", - modulesPerClass.get(0)); - Assert.assertEquals( - "@vaadin/vaadin-mixed-component/src/vaadin-something-else.js", - modulesPerClass.get(1)); - Assert.assertEquals( - "@vaadin/vaadin-mixed-component/src/vaadin-something-else", - modulesPerClass.get(2)); - Assert.assertEquals( - "@vaadin/vaadin-mixed-component/src/vaadin-custom-themed-component.js", - modulesPerClass.get(3)); - } - - private void assertJsModulesClasses(Set classes) { - Assert.assertTrue( - classes.contains(NodeTestComponents.ICON_COMPONENT_FQN)); - Assert.assertTrue( - classes.contains(VaadinBowerComponent.class.getName())); - Assert.assertTrue(classes.contains(VaadinElementMixin.class.getName())); - Assert.assertTrue(classes.contains(VaadinNpmComponent.class.getName())); - Assert.assertTrue( - classes.contains(VaadinMixedComponent.class.getName())); - Assert.assertTrue(classes.contains(LocalTemplate.class.getName())); - Assert.assertTrue(classes.contains(LocalP3Template.class.getName())); - Assert.assertTrue( - classes.contains(UnresolvedComponent.class.getName())); - Assert.assertTrue(classes.contains(FlatImport.class.getName())); - Assert.assertTrue(classes.contains(MainLayout.class.getName())); - Assert.assertTrue(classes.contains(JavaScriptOrder.class.getName())); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FullScannerPwaTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FullScannerPwaTest.java deleted file mode 100644 index 03e540ccbfa..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/FullScannerPwaTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.vaadin.flow.server.frontend.scanner; - -import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.mockito.Mockito; - -import com.vaadin.flow.server.PWA; -import com.vaadin.flow.server.PwaConfiguration; - -public class FullScannerPwaTest extends AbstractScannerPwaTest { - private ClassFinder finder = Mockito.mock(ClassFinder.class); - - protected PwaConfiguration getPwaConfiguration(Class... classes) - throws Exception { - // use this fake/mock class for the loaded class to check that annotated - // classes are requested for the loaded class and not for the - // annotationType - Class clazz = Object.class; - - Mockito.doReturn(clazz).when(finder).loadClass(PWA.class.getName()); - - Mockito.doReturn(getPwaAnnotatedClasses(classes)).when(finder) - .getAnnotatedClasses(clazz); - - FullDependenciesScanner fullDependenciesScanner = new FullDependenciesScanner( - finder, (type, annotation) -> findPwaAnnotations(type), false, - null, false); - return fullDependenciesScanner.getPwaConfiguration(); - } - - private Set> getPwaAnnotatedClasses(Class[] classes) { - Set> result = new HashSet<>(); - for (Class clazz : classes) { - if (clazz.getAnnotationsByType(PWA.class).length > 0) { - result.add(clazz); - } - } - - return result; - } - - private List findPwaAnnotations(Class type) { - return Arrays.asList(type.getAnnotationsByType(PWA.class)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerCssTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerCssTest.java deleted file mode 100644 index c976265012b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerCssTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.vaadin.flow.server.frontend.scanner; - -import java.util.stream.Collectors; - -import org.junit.Test; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.CssClass1; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.CssClass2; - -import static com.vaadin.flow.server.frontend.scanner.ScannerDependenciesTest.getFrontendDependencies; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.hamcrest.collection.IsIterableContainingInOrder.contains; -import static org.junit.Assert.assertEquals; -import static org.hamcrest.MatcherAssert.assertThat; - -public class ScannerCssTest { - - @Test - public void should_visitCssImports() throws Exception { - FrontendDependencies deps = getFrontendDependencies(CssClass1.class, - CssClass2.class); - assertEquals(3, deps.getEndPoints().size()); - for (EndPointData endPoint : deps.getEndPoints()) { - if (endPoint.name.equals(UI.class.getName())) { - continue; - } - assertEquals("Wrong amount of css in " + endPoint.getName(), 4, - endPoint.getCss().size()); - - assertThat( - endPoint.getCss().stream().map(CssData::toString) - .collect(Collectors.toList()), - containsInAnyOrder("value: ./foo.css", - "value: ./foo.css include:bar", - "value: ./foo.css id:bar", - "value: ./foo.css themefor:bar")); - } - ; - } - - @Test - public void should_gatherCssImportsInOrderPerClass() throws Exception { - FrontendDependencies deps = getFrontendDependencies(CssClass3.class); - assertEquals(2, deps.getEndPoints().size()); - for (EndPointData endPoint : deps.getEndPoints()) { - if (endPoint.name.equals(UI.class.getName())) { - continue; - } - assertEquals("Wrong amount of css in " + endPoint.getName(), 4, - endPoint.getCss().size()); - - // verifies #6523 as sufficiently complex names can get mixed up - assertThat( - endPoint.getCss().stream().map(CssData::toString) - .collect(Collectors.toList()), - contains("value: ./foo.css", "value: ./bar.css", - "value: ./foofoo.css", "value: ./foobar.css")); - } - ; - } - - @Test - public void should_sumarizeCssImports() throws Exception { - FrontendDependencies deps = getFrontendDependencies(CssClass1.class, - CssClass2.class); - assertEquals(4, deps.getCss().size()); - } - - // Moved here from ScannerTestComponents. Otherwise this would affect - // NodeUpdateImportsTest.java - @Route("css-route-3") - @CssImport("./foo.css") - @CssImport(value = "./bar.css") - @CssImport(value = "./foofoo.css") - @CssImport(value = "./foobar.css") - public static class CssClass3 { - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerDependenciesTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerDependenciesTest.java deleted file mode 100644 index 2540134549f..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerDependenciesTest.java +++ /dev/null @@ -1,239 +0,0 @@ -package com.vaadin.flow.server.frontend.scanner; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Test; - -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.BridgeClass; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Component0; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Component1; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Component2; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.FirstView; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RouteWithNestedDynamicRouteClass; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RouteWithService; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RouteWithViewBean; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RoutedClass; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RoutedClassWithAnnotations; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RoutedClassWithoutAnnotations; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.SecondView; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Theme1; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.ThirdView; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.UnAnnotatedClass; -import com.vaadin.flow.server.frontend.scanner.samples.RouteInterfaceComponent; -import com.vaadin.flow.theme.NoTheme; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class ScannerDependenciesTest { - - static FrontendDependencies getFrontendDependencies(Class... classes) { - FrontendDependencies frontendDependencies = new FrontendDependencies( - new DefaultClassFinder(new HashSet<>( - new ArrayList<>(Arrays.asList(classes))))); - return frontendDependencies; - } - - @Test - public void visitRouteEntryPoint_ExpectToAlsoVisitImplementedInterface() { - FrontendDependencies deps = getFrontendDependencies( - RouteInterfaceComponent.class); - - assertTrue("Missing dependency from implemented interface", - deps.getModules().contains("myModule.js")); - - assertEquals("There should be 1 css import", 1, deps.getCss().size()); - - assertEquals("Invalid css import", "frontend://styles/interface.css", - deps.getCss().iterator().next().value); - } - - @Test - public void should_extractClassesFromSignatures() { - Set classes = new HashSet<>(); - FrontendClassVisitor visitor = new FrontendClassVisitor(null, null, - false); - - visitor.addSignatureToClasses(classes, - "(Lcom/vaadin/flow/component/tabs/Tabs;Ljava/lang/String;Ljava/lang/Character;CLjava/lang/Integer;ILjava/lang/Long;JLjava/lang/Double;DLjava/lang/Float;FLjava/lang/Byte;BLjava/lang/Boolean;Z)Lcom/vaadin/flow/component/button/Button;"); - assertEquals(11, classes.size()); - assertArrayEquals(new String[] { "", "java.lang.Float", - "com.vaadin.flow.component.button.Button", - "java.lang.Character", "java.lang.Long", "java.lang.Double", - "java.lang.Boolean", "com.vaadin.flow.component.tabs.Tabs", - "java.lang.String", "java.lang.Byte", "java.lang.Integer" }, - classes.toArray()); - - visitor.addSignatureToClasses(classes, - "([Lcom/vaadin/flow/component/Component;)V"); - assertEquals(12, classes.size()); - assertTrue(classes.contains("com.vaadin.flow.component.Component")); - - visitor.addSignatureToClasses(classes, - "(Lcom/vaadin/flow/component/orderedlayout/FlexComponent$Alignment;[Lcom/vaadin/flow/component/Component;)"); - assertEquals(13, classes.size()); - assertTrue(classes.contains( - "com.vaadin.flow.component.orderedlayout.FlexComponent$Alignment")); - - // Apart from proper signature representation, it should handle class - // names, and class paths - visitor.addSignatureToClasses(classes, this.getClass().getName()); - assertTrue(classes.contains(this.getClass().getName())); - - visitor.addSignatureToClasses(classes, - "com/vaadin/flow/server/frontend/FrontendDependenciesTestComponents$AnotherComponent"); - assertTrue(classes.contains( - "com.vaadin.flow.server.frontend.FrontendDependenciesTestComponents$AnotherComponent")); - - } - - @Test - public void should_visitNpmPakageAnnotations() { - FrontendDependencies deps = getFrontendDependencies(Component1.class, - Component2.class); - assertEquals(4, deps.getPackages().size()); - assertTrue(deps.getPackages().containsKey("@vaadin/component-1")); - assertTrue(deps.getPackages().containsKey("@vaadin/component-2")); - assertTrue(deps.getPackages().containsKey("@vaadin/component-0")); - assertTrue(deps.getPackages().containsKey("@vaadin/vaadin-foo")); - assertEquals("1.1.1", deps.getPackages().get("@vaadin/component-1")); - assertEquals("222.222.222", - deps.getPackages().get("@vaadin/component-2")); - assertEquals("=2.1.0", deps.getPackages().get("@vaadin/component-0")); - assertEquals("1.23.114-alpha1", - deps.getPackages().get("@vaadin/vaadin-foo")); - } - - @Test - public void should_visitSuperNpmPakageAnnotations() { - FrontendDependencies deps = getFrontendDependencies( - ScannerTestComponents.ComponentExtending.class); - assertEquals(1, deps.getPackages().size()); - assertTrue( - deps.getPackages().containsKey("@vaadin/component-extended")); - - assertEquals("2.1.0", - deps.getPackages().get("@vaadin/component-extended")); - } - - @Test - public void when_MultipleVersions_should_returnFirstVisitedOne() { - FrontendDependencies deps = getFrontendDependencies(Component0.class); - assertEquals("=2.1.0", deps.getPackages().get("@vaadin/component-0")); - } - - @Test - public void should_summarize_when_MultipleViews() { - FrontendDependencies deps = getFrontendDependencies(SecondView.class, - FirstView.class); - - assertEquals(Theme1.class, deps.getThemeDefinition().getTheme()); - - assertTrue(8 <= deps.getModules().size()); - assertEquals(1, deps.getPackages().size()); - assertEquals(6, deps.getScripts().size()); - } - - @Test - public void should_visit_Constructor() { - FrontendDependencies deps = getFrontendDependencies(SecondView.class); - assertTrue(deps.getModules().contains("./component-3.js")); - } - - @Test - public void should_resolveComponentFactories() { - FrontendDependencies deps = getFrontendDependencies(ThirdView.class); - - assertTrue(3 <= deps.getModules().size()); - assertEquals(0, deps.getPackages().size()); - assertEquals(0, deps.getScripts().size()); - assertTrue(deps.getModules().contains("./my-component.js")); - assertTrue(deps.getModules().contains("./my-static-factory.js")); - assertTrue(deps.getModules().contains("./my-another-component.js")); - } - - @Test - public void should_notVisitNonAnnotatredClasses() { - FrontendDependencies deps = getFrontendDependencies( - UnAnnotatedClass.class); - assertEquals("Only UI should be found", 1, deps.getEndPoints().size()); - } - - @Test - public void should_cacheVisitedClasses() { - FrontendDependencies deps = getFrontendDependencies( - RoutedClassWithoutAnnotations.class); - assertEquals(2, deps.getEndPoints().size()); - assertTrue("Should cache visited classes", - deps.getClasses().size() > 2); - assertTrue(deps.getClasses().contains(Route.class.getName())); - assertTrue(deps.getClasses() - .contains(RoutedClassWithoutAnnotations.class.getName())); - } - - @Test - public void should_cacheSuperVisitedClasses() { - List> visited = Arrays.asList(Route.class, NoTheme.class, - JsModule.class, RoutedClassWithAnnotations.class, - RoutedClassWithoutAnnotations.class, RoutedClass.class, - BridgeClass.class); - - // Visit a route that extends an extra routed class - FrontendDependencies deps = getFrontendDependencies(RoutedClass.class); - assertEquals("Should find RoutedClass and UI", 2, - deps.getEndPoints().size()); - int visitedClassesAmount = deps.getClasses().size(); - for (Class clz : visited) { - assertTrue("should cache " + clz.getName(), - deps.getClasses().contains(clz.getName())); - } - - // Visit the same route but also the super routed class, the number of - // visited classes should - // be the same, but number of entry points increases - deps = getFrontendDependencies(RoutedClassWithoutAnnotations.class, - RoutedClass.class); - assertEquals("Should contain UI, RoutedClass and its parent", 3, - deps.getEndPoints().size()); - assertEquals(visitedClassesAmount, deps.getClasses().size()); - for (Class clz : visited) { - assertTrue("should cache " + clz.getName(), - deps.getClasses().contains(clz.getName())); - } - } - - @Test // #5509 - public void should_visitDynamicRoute() { - FrontendDependencies deps = getFrontendDependencies( - RouteWithNestedDynamicRouteClass.class); - assertTrue(3 <= deps.getModules().size()); - assertTrue(deps.getModules().contains("dynamic-route.js")); - assertTrue(deps.getModules().contains("dynamic-component.js")); - assertTrue(deps.getModules().contains("dynamic-layout.js")); - } - - @Test // #5658 - public void should_visitFactoryBeans() { - FrontendDependencies deps = getFrontendDependencies( - RouteWithViewBean.class); - assertTrue(1 <= deps.getModules().size()); - assertTrue(deps.getModules().contains("dynamic-component.js")); - } - - @Test - public void should_visitServices() { - FrontendDependencies deps = getFrontendDependencies( - RouteWithService.class); - assertTrue(2 <= deps.getModules().size()); - assertTrue(deps.getModules().contains("dynamic-component.js")); - assertTrue(deps.getModules().contains("dynamic-layout.js")); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerTestComponents.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerTestComponents.java deleted file mode 100644 index 746dc91a1d7..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerTestComponents.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ -package com.vaadin.flow.server.frontend.scanner; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.component.dependency.NpmPackage; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.NoTheme; -import com.vaadin.flow.theme.Theme; - -/** - * A container class for all components used in tests. - */ -public class ScannerTestComponents { - - @NpmPackage(value = "@vaadin/theme-0", version = "1.1.1") - @JavaScript("frontend://theme-0.js") - static class Theme0 implements AbstractTheme { - public static final String DARK = "dark"; - public static final String FOO = "foo"; - - @Override - public String getBaseUrl() { - return null; - } - - @Override - public String getThemeUrl() { - return null; - } - } - - static class Theme1 extends Theme0 { - } - - static class Theme2 extends Theme0 { - } - - @JsModule("./theme-4.js") - static class Theme4 extends Theme0 { - } - - @JsModule("./theme-default.js") - static class ThemeDefault extends Theme0 { - } - - @NpmPackage(value = "@vaadin/component-0", version = "=2.1.0") - @JsModule("./component-0.js") - @JavaScript("frontend://component-0.js") - @Tag("component-0") - @NpmPackage(value = "@vaadin/component-0", version = "^1.1.0") - @NpmPackage(value = "@vaadin/vaadin-foo", version = "1.23.114-alpha1") - static class Component0 extends Component { - } - - @JsModule("./component-1.js") - @JavaScript("frontend://component-1.js") - @Tag("component-1") - @NpmPackage(value = "@vaadin/component-1", version = "1.1.1") - static class Component1 extends Component0 { - } - - @JsModule("./component-2.js") - @JavaScript("frontend://component-2.js") - @Tag("component-2") - @NpmPackage(value = "@vaadin/component-2", version = "222.222.222") - static class Component2 extends Component { - } - - @JsModule("./component-3.js") - @JavaScript("frontend://component-3.js") - @Tag("component-3") - @NpmPackage(value = "@vaadin/component-3", version = "~2.1.0") - static class Component3 extends Component { - } - - static class ComponentExtending extends GeneratedComponent { - - } - - @Tag("component-extends") - @NpmPackage(value = "@vaadin/component-extended", version = "2.1.0") - static abstract class GeneratedComponent extends Component { - - } - - @Theme(themeClass = Theme1.class, variant = Theme0.DARK) - @JsModule("./router-layout-1.js") - public class RouterLayout1 implements RouterLayout { - @Override - public Element getElement() { - return null; - } - } - - @Theme(themeClass = Theme1.class, variant = Theme0.DARK) - @JsModule("./router-layout-2.js") - public class RouterLayout2 extends RouterLayout1 { - } - - @JavaScript("frontend://view-0.js") - public static abstract class View0 extends Component { - } - - @Route(value = "") - @Theme(themeClass = Theme4.class) - public static class RootViewWithTheme extends Component { - } - - @Route(value = "") - public static class RootViewWithoutThemeAnnotation extends Component { - - } - - @Route(value = "", layout = RouterLayout1.class) - @JsModule("./view-3.js") - @NoTheme - public static class RootViewWithoutTheme extends View0 { - } - - @Route(value = "", layout = RouterLayout1.class) - public static class RootViewWithLayoutTheme extends FirstView { - } - - @Route(value = "2", layout = RouterLayout1.class) - public static class RootView2WithLayoutTheme { - } - - @Route(value = "", layout = RouterLayout2.class) - @Theme(themeClass = Theme2.class, variant = Theme2.FOO) - @JsModule("./view-2.js") - public static class RootViewWithMultipleTheme extends Component { - - public RootViewWithMultipleTheme() { - createView(); - } - - private void createView() { - new Component3(); - } - } - - @Route(value = "", layout = RouterLayout1.class) - @JsModule("./view-1.js") - @NpmPackage(value = "@foo/first-view", version = "0.0.1") - public static class FirstView extends View0 { - Component1 component1; - RootViewWithMultipleTheme second; - - public FirstView() { - createView(); - } - - private void createView() { - new Component2(); - } - } - - public static class MyComponent extends Component { - } - - @Route(value = "second", layout = RouterLayout2.class) - @JsModule("./view-2.js") - public static class SecondView extends Component { - public SecondView() { - new Component3(); - } - } - - @Route() - public static class ThirdView { - public void foo() { - new ComponentFactory().createMyComponent(); - this.add(StaticComponentsFactory.createAnotherComponent(null)); - } - - private void add(Object o) { - } - } - - @JsModule("./my-component.js") - public static class ComponentFactory { - public MyComponent createMyComponent() { - return new MyComponent(); - } - } - - @JsModule("./my-static-factory.js") - public static class StaticComponentsFactory { - public static AnotherComponent createAnotherComponent(String label) { - return AnotherComponent.createMyComponent(label); - } - } - - @JsModule("./my-another-component.js") - public static class AnotherComponent { - public static AnotherComponent createMyComponent(String label) { - return new AnotherComponent(); - } - } - - public static class NoThemeExporter - extends WebComponentExporter { - public NoThemeExporter() { - super("root-view"); - } - - @Override - public void configureInstance( - WebComponent webComponent, - RootViewWithTheme component) { - - } - } - - @Theme(themeClass = Theme2.class) - public static class ThemeExporter - extends WebComponentExporter { - public ThemeExporter() { - super("root-view"); - } - - @Override - public void configureInstance( - WebComponent webComponent, - RootViewWithTheme component) { - - } - } - - public static class UnAnnotatedClass { - } - - @Route - public static class RoutedClassWithoutAnnotations { - } - - @Route("route-1") - @NoTheme - @JsModule("./foo") - public static class RoutedClassWithAnnotations - extends RoutedClassWithoutAnnotations { - } - - public static class BridgeClass extends RoutedClassWithAnnotations { - } - - @Route("route-2") - public static class RoutedClass extends BridgeClass { - } - - @Route("css-route-1") - @CssImport("./foo.css") - @CssImport(value = "./foo.css", include = "bar") - @CssImport(value = "./foo.css", id = "bar") - @CssImport(value = "./foo.css", themeFor = "bar") - public static class CssClass1 { - } - - @Route("css-route-2") - @CssImport("./foo.css") - @CssImport(value = "./foo.css", include = "bar") - @CssImport(value = "./foo.css", id = "bar") - @CssImport(value = "./foo.css", themeFor = "bar") - public static class CssClass2 extends CssClass1 { - } - - @JsModule("dynamic-component.js") - public static class DynamicComponentClass extends Component { - } - - @JsModule("dynamic-layout.js") - public static class DynamicLayoutClass implements RouterLayout { - @Override - public Element getElement() { - return null; - } - } - - @Route("dynamic-route") - @JsModule("dynamic-route.js") - public static class RouteWithNestedDynamicRouteClass { - public RouteWithNestedDynamicRouteClass() { - registerRoute(); - } - - @SuppressWarnings("unchecked") - private void registerRoute() { - RouteConfiguration.forSessionScope().setRoute("foo", - DynamicComponentClass.class, DynamicLayoutClass.class); - } - } - - @Route() - public static class RouteWithViewBean { - public RouteWithViewBean() { - UI.getCurrent() - .add(BeanFactory.getBean(DynamicComponentClass.class)); - } - } - - public static class BeanFactory { - public static T getBean(Class type) { - return null; - } - } - - @Route() - public static class RouteWithService { - public RouteWithService() { - UserRouteService.registerUserRoute( - RouteConfiguration.forSessionScope(), "donald"); - } - } - - public static class UserRouteService { - @SuppressWarnings("unchecked") - public static void registerUserRoute(RouteConfiguration config, - String userId) { - config.setRoute(userId, DynamicComponentClass.class, - DynamicLayoutClass.class); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerThemeTest.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerThemeTest.java deleted file mode 100644 index 80d078c1996..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/ScannerThemeTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.vaadin.flow.server.frontend.scanner; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.UI; -import com.vaadin.flow.server.frontend.scanner.ClassFinder.DefaultClassFinder; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.FirstView; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.NoThemeExporter; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RootView2WithLayoutTheme; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RootViewWithLayoutTheme; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RootViewWithMultipleTheme; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RootViewWithTheme; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RootViewWithoutTheme; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.RootViewWithoutThemeAnnotation; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.SecondView; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Theme1; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Theme2; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.Theme4; -import com.vaadin.flow.server.frontend.scanner.ScannerTestComponents.ThemeExporter; - -import static com.vaadin.flow.server.frontend.scanner.ScannerDependenciesTest.getFrontendDependencies; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -public class ScannerThemeTest { - - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Test - public void should_takeThemeFromTheView() { - FrontendDependencies deps = getFrontendDependencies( - RootViewWithTheme.class); - - assertEquals(Theme4.class, deps.getThemeDefinition().getTheme()); - - assertTrue(1 <= deps.getModules().size()); - assertTrue(deps.getModules().contains("./theme-4.js")); - - assertEquals(0, deps.getPackages().size()); - - assertEquals(1, deps.getScripts().size()); - assertTrue(deps.getScripts().contains("frontend://theme-0.js")); - } - - @Test - public void should_not_takeTheme_when_NoTheme() { - FrontendDependencies deps = getFrontendDependencies( - RootViewWithoutTheme.class); - assertNull(deps.getThemeDefinition()); - - assertTrue(2 <= deps.getModules().size()); - assertEquals(0, deps.getPackages().size()); - assertEquals(2, deps.getScripts().size()); - } - - @Test - public void should_takeThemeFromLayout() { - FrontendDependencies deps = getFrontendDependencies( - RootViewWithLayoutTheme.class); - assertEquals(Theme1.class, deps.getThemeDefinition().getTheme()); - assertEquals(Theme1.DARK, deps.getThemeDefinition().getVariant()); - - assertTrue(8 <= deps.getModules().size()); - assertEquals(1, deps.getPackages().size()); - assertEquals(6, deps.getScripts().size()); - - assertTrue(deps.getPackages().containsKey("@foo/first-view")); - assertEquals("0.0.1", deps.getPackages().get("@foo/first-view")); - } - - @Test - public void should_takeThemeWhenMultipleTheme() { - FrontendDependencies deps = getFrontendDependencies( - RootViewWithMultipleTheme.class); - assertEquals(Theme2.class, deps.getThemeDefinition().getTheme()); - assertEquals(Theme2.FOO, deps.getThemeDefinition().getVariant()); - - assertTrue(4 <= deps.getModules().size()); - assertEquals(0, deps.getPackages().size()); - assertEquals(2, deps.getScripts().size()); - } - - @Test - public void should_takeTheme_when_AnyRouteValue() { - FrontendDependencies deps = getFrontendDependencies(SecondView.class); - - assertEquals(Theme1.class, deps.getThemeDefinition().getTheme()); - - assertTrue(4 <= deps.getModules().size()); - assertEquals(0, deps.getPackages().size()); - assertEquals(2, deps.getScripts().size()); - } - - @Test - public void should_throw_when_MultipleThemes() { - exception.expect(IllegalStateException.class); - getFrontendDependencies(RootViewWithMultipleTheme.class, - FirstView.class); - } - - @Test - public void should_throw_when_ThemeAndNoTheme() { - exception.expect(IllegalStateException.class); - getFrontendDependencies(FirstView.class, RootViewWithoutTheme.class); - } - - @Test - public void should_visitDefaultTheme_when_noThemeAnnotationIsGiven() - throws Exception { - - DefaultClassFinder finder = spy(new DefaultClassFinder( - Collections.singleton(RootViewWithoutThemeAnnotation.class))); - - // we'll do a partial mock here since we want to keep the other - // behavior of the DefaultClassFinder. Theme4 is used as a fake Lumo - // since it has @JsModule annotation which makes it easy to verify - // that the Theme was actually visited and modules collected - Mockito.doReturn(Theme4.class).when(finder) - .loadClass(FrontendDependencies.LUMO); - - FrontendDependencies deps = new FrontendDependencies(finder); - assertEquals( - "Theme4 should have been returned when default theme was selected", - Theme4.class, deps.getThemeDefinition().getTheme()); - assertTrue("Theme4 should have been visited and JsModule collected", - deps.getModules().contains("./theme-4.js")); - } - - @Test - public void should_takeThemeFromExporter_when_exporterFound() { - FrontendDependencies deps = getFrontendDependencies( - ThemeExporter.class); - - assertEquals(Theme2.class, deps.getThemeDefinition().getTheme()); - } - - @Test - public void should_defaultToLumoTheme_when_noThemeDefinedByExporter() - throws Exception { - // RootViewWithTheme is added to the list just to make sure exporter - // handles theming default, not the other crawlers - DefaultClassFinder finder = spy(new DefaultClassFinder( - new HashSet<>(Arrays.asList(NoThemeExporter.class, - RootViewWithTheme.class)))); - - Mockito.doReturn(Theme4.class).when(finder) - .loadClass(FrontendDependencies.LUMO); - - FrontendDependencies deps = new FrontendDependencies(finder); - assertEquals( - "Theme4 should have been returned when default theme was selected", - Theme4.class, deps.getThemeDefinition().getTheme()); - assertTrue("Theme4 should have been visited and JsModule collected", - deps.getModules().contains("./theme-4.js")); - } - - @Test // flow#5715 - public void should_notAttemptToOverrideTheme_when_noExportersFound() - throws ClassNotFoundException { - DefaultClassFinder finder = spy(new DefaultClassFinder( - Collections.singleton(RootViewWithTheme.class))); - - new FrontendDependencies(finder); - verify(finder, times(0)).loadClass(FrontendDependencies.LUMO); - } - - @Test - public void should_takeThemeFromLayout_ifLayoutAlreadyVisited() { - // Make sure that all entry-points sharing layouts are correctly - // theming-configured - FrontendDependencies deps = getFrontendDependencies( - RootViewWithLayoutTheme.class, RootView2WithLayoutTheme.class); - assertEquals(Theme1.class, deps.getThemeDefinition().getTheme()); - for (EndPointData endPoint : deps.getEndPoints()) { - if (endPoint.getName().equals(UI.class.getName())) { - continue; - } - assertEquals(Theme1.class.getName(), - endPoint.getTheme().getThemeClass()); - } - ; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/CustomTheme.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/CustomTheme.java deleted file mode 100644 index 72a127a9fe2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/CustomTheme.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.theme.AbstractTheme; - -@JsModule("theme-foo.js") -public class CustomTheme implements AbstractTheme { - @Override - public String getBaseUrl() { - return null; - } - - @Override - public String getThemeUrl() { - return null; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/ErrorComponent.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/ErrorComponent.java deleted file mode 100644 index 2e9db30ec3a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/ErrorComponent.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; - -@JsModule("./src/bar.js") -@JavaScript("./src/baz.js") -public class ErrorComponent implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 0; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/JsModuleComponent.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/JsModuleComponent.java deleted file mode 100644 index 2a807c9cd8d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/JsModuleComponent.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ - -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.dependency.JsModule; - -@JsModule("myModule.js") -public class JsModuleComponent { - - public void show() { - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/JsOrderComponent.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/JsOrderComponent.java deleted file mode 100644 index 350c20ffe45..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/JsOrderComponent.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.router.Route; - -@Route("foo") -@JavaScript("a.js") -@JavaScript("b.js") -@JavaScript("c.js") -public class JsOrderComponent extends Component { - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/MyServiceListener.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/MyServiceListener.java deleted file mode 100644 index 0559a5dd7cd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/MyServiceListener.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.server.ServiceInitEvent; -import com.vaadin.flow.server.VaadinServiceInitListener; - -public class MyServiceListener implements VaadinServiceInitListener { - - @Override - public void serviceInit(ServiceInitEvent event) { - event.getSource().addUIInitListener(new MyUIInitListener()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/MyUIInitListener.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/MyUIInitListener.java deleted file mode 100644 index 74d3d8fa95c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/MyUIInitListener.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.server.UIInitEvent; -import com.vaadin.flow.server.UIInitListener; - -public class MyUIInitListener implements UIInitListener { - - @JsModule("baz.js") - @JavaScript("foobar.js") - public static class MyComponent extends Component { - - } - - @Override - public void uiInit(UIInitEvent event) { - event.getSource().addUIInitListener(uiEvent -> { - final UI ui = uiEvent.getUI(); - ui.add(new MyComponent()); - }); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponent.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponent.java deleted file mode 100644 index 43dde44f859..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponent.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.dependency.JavaScript; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.router.Route; - -@Route("") -@JsModule("foo.js") -@JavaScript("bar.js") -public class RouteComponent extends Component { - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponentWithLayout.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponentWithLayout.java deleted file mode 100644 index f4655bc2157..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponentWithLayout.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.router.Route; - -@Route(value = "layout", layout = RouteLayoutComponent.class) -public class RouteComponentWithLayout extends Component { - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponentWithMethodReference.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponentWithMethodReference.java deleted file mode 100644 index 2d4730214f2..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteComponentWithMethodReference.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples; - -import java.util.Collections; -import java.util.List; -import java.util.function.Supplier; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.HasComponents; -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.router.Route; - -@Route("") -public class RouteComponentWithMethodReference extends Component - implements HasComponents { - - @JsModule("foo.js") - public static class MyComponent extends Component { - } - - @JsModule("bar.js") - public static class AnotherComponent extends Component { - } - - @JsModule("baz.js") - public static class YetAnotherComponent extends Component { - } - - private Supplier fieldGenerator = YetAnotherComponent::new; - - public RouteComponentWithMethodReference() { - List> suppliers = Collections - .singletonList(AnotherComponent::new); - - Supplier generator = MyComponent::new; - add(generator.get(), fieldGenerator.get()); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteInterface.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteInterface.java deleted file mode 100644 index e7ca21de794..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteInterface.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.dependency.CssImport; - -@CssImport("frontend://styles/interface.css") -public interface RouteInterface { - - default void doSomething() { - JsModuleComponent component = new JsModuleComponent(); - component.show(); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteInterfaceComponent.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteInterfaceComponent.java deleted file mode 100644 index 66a8eb0bf7d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteInterfaceComponent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - */ -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.router.Route; - -@Route("") -public class RouteInterfaceComponent extends Component - implements RouteInterface { - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteLayoutComponent.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteLayoutComponent.java deleted file mode 100644 index 10357b1c3cb..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/RouteLayoutComponent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples; - -import com.vaadin.flow.component.dependency.JsModule; -import com.vaadin.flow.dom.Element; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.theme.Theme; - -@JsModule("foo.js") -@Theme(themeClass = CustomTheme.class) -public class RouteLayoutComponent implements RouterLayout { - @Override - public Element getElement() { - return null; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AnotherAppShellWithPwa.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AnotherAppShellWithPwa.java deleted file mode 100644 index 1ab42765d35..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AnotherAppShellWithPwa.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples.pwa; - -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.server.PWA; - -@PWA(name = "Another PWA Application", shortName = "Another PWA", description = "Testing another PWA", display = "minimal-ui", backgroundColor = "#eee", themeColor = "#369", iconPath = "another_pwa.png", manifestPath = "appmanifest.json", offlinePath = "another_pwa.html", offlineResources = { - "another_pwa.js", "another_pwa.css" }) -public class AnotherAppShellWithPwa implements AppShellConfigurator { -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AppShellWithPwa.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AppShellWithPwa.java deleted file mode 100644 index 69cca33349a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AppShellWithPwa.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples.pwa; - -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.server.PWA; - -@PWA(name = "PWA Application", shortName = "PWA", description = "Testing PWA", display = "minimal-ui", backgroundColor = "#eee", themeColor = "#369", iconPath = "pwa.png", manifestPath = "appmanifest.json", offlinePath = "pwa.html", offlineResources = { - "pwa.js", "pwa.css" }) -public class AppShellWithPwa implements AppShellConfigurator { -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AppShellWithoutPwa.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AppShellWithoutPwa.java deleted file mode 100644 index 35360a35d04..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/AppShellWithoutPwa.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples.pwa; - -import com.vaadin.flow.component.page.AppShellConfigurator; - -public class AppShellWithoutPwa implements AppShellConfigurator { -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/NonAppShellWithPwa.java b/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/NonAppShellWithPwa.java deleted file mode 100644 index e1a82ac4e8a..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/frontend/scanner/samples/pwa/NonAppShellWithPwa.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.frontend.scanner.samples.pwa; - -import com.vaadin.flow.server.PWA; - -@PWA(name = "PWA Application", shortName = "PWA", description = "Testing PWA", display = "minimal-ui", backgroundColor = "#eee", themeColor = "#369", iconPath = "pwa.png", manifestPath = "appmanifest.json", offlinePath = "pwa.html", offlineResources = { - "pwa.js", "pwa.css" }) -public class NonAppShellWithPwa { -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/AbstractRouteRegistryInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/AbstractRouteRegistryInitializerTest.java deleted file mode 100644 index 98ce7ea5994..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/AbstractRouteRegistryInitializerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import java.util.Set; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.InvalidRouteLayoutConfigurationException; - -public class AbstractRouteRegistryInitializerTest { - - private AbstractRouteRegistryInitializer initializer = new AbstractRouteRegistryInitializer() { - - }; - - @Tag(Tag.DIV) - public static class TestParentLayout extends Component - implements RouterLayout { - - } - - @Tag(Tag.DIV) - @Route("foo") - @ParentLayout(TestParentLayout.class) - public static class RouteAndParentLayout extends Component { - - } - - @Tag(Tag.DIV) - @Route("foo") - @ParentLayout(TestParentLayout.class) - public static class RouteAndParentRouterLayout extends Component - implements RouterLayout { - - } - - @Test(expected = InvalidRouteLayoutConfigurationException.class) - public void routeAndParentLayout_notRouterLayout_throws() { - initializer.validateRouteClasses(null, - Stream.of(RouteAndParentLayout.class)); - - } - - @Test - public void routeAndParentLayout_routerLayout_returnsValidatedClass() { - Set> classes = initializer - .validateRouteClasses(null, - Stream.of(RouteAndParentRouterLayout.class)); - Assert.assertEquals(1, classes.size()); - Assert.assertEquals(RouteAndParentRouterLayout.class, - classes.iterator().next()); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/AnnotationValidatorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/AnnotationValidatorTest.java deleted file mode 100644 index b9497f27e5e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/AnnotationValidatorTest.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.vaadin.flow.server.startup; - -import static com.vaadin.flow.server.startup.AbstractAnnotationValidator.ERROR_MESSAGE_BEGINNING; -import static com.vaadin.flow.server.startup.AbstractAnnotationValidator.NON_PARENT; - -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jakarta.servlet.ServletContainerInitializer; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.HandlesTypes; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.page.BodySize; -import com.vaadin.flow.component.page.Inline; -import com.vaadin.flow.component.page.Viewport; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.InvalidApplicationConfigurationException; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -public class AnnotationValidatorTest { - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - private AnnotationValidator annotationValidator; - private ServletContext servletContext; - - @Before - public void init() { - annotationValidator = new AnnotationValidator(); - servletContext = Mockito.mock(ServletContext.class); - } - - @Tag(Tag.DIV) - public static class Parent extends Component implements RouterLayout { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - @Inline("inline.css") - public static class InlineViewportWithParent extends Component { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - @BodySize(width = "100vw") - public static class BodySizeViewportWithParent extends Component { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class ViewPortViewportWithParent extends Component { - } - - @Tag(Tag.DIV) - public static abstract class AbstractMain extends Component { - } - - @Route("multiple_annotations") - @Inline("inlie.css") - @BodySize(width = "100vw") - @Viewport("width=device-width") - public static class MultiAnnotation extends Component { - } - - @Route(value = "multiple_annotations", layout = Parent.class) - @Inline("inlie.css") - @BodySize(width = "100vw") - public static class FailingMultiAnnotation extends Component { - } - - @Test - public void onStartUp_all_failing_anotations_are_reported() - throws ServletException { - try { - annotationValidator.process(Stream - .of(InlineViewportWithParent.class, - BodySizeViewportWithParent.class, - ViewPortViewportWithParent.class) - .collect(Collectors.toSet()), servletContext); - Assert.fail("No exception was thrown for faulty setup."); - } catch (InvalidApplicationConfigurationException iace) { - String errorMessage = iace.getMessage(); - Assert.assertTrue("Exception has wrong beginning.", - errorMessage.startsWith(ERROR_MESSAGE_BEGINNING)); - Assert.assertTrue("Exception was missing Inline exception", - errorMessage.contains(String.format(NON_PARENT, - InlineViewportWithParent.class.getName(), - "@" + Inline.class.getSimpleName()))); - Assert.assertTrue("Exception was missing Viewport exception", - errorMessage.contains(String.format(NON_PARENT, - ViewPortViewportWithParent.class.getName(), - "@" + Viewport.class.getSimpleName()))); - Assert.assertTrue("Exception was missing BodySize exception", - errorMessage.contains(String.format(NON_PARENT, - BodySizeViewportWithParent.class.getName(), - "@" + BodySize.class.getSimpleName()))); - } - } - - @Test - public void onStartUp_all_failing_annotations_are_marked_for_class() - throws ServletException { - expectedEx.expect(InvalidApplicationConfigurationException.class); - expectedEx.expectMessage(ERROR_MESSAGE_BEGINNING + String.format( - NON_PARENT, FailingMultiAnnotation.class.getName(), - "@" + BodySize.class.getSimpleName() + ", " + "@" - + Inline.class.getSimpleName())); - - annotationValidator.process(Stream.of(FailingMultiAnnotation.class) - .collect(Collectors.toSet()), servletContext); - - Assert.fail("No exception was thrown for faulty setup."); - } - - @Test - public void onStartUp_no_exception_is_thrown_for_correctly_setup_classes() - throws ServletException { - annotationValidator - .process(Stream.of(MultiAnnotation.class, AbstractMain.class) - .collect(Collectors.toSet()), servletContext); - } - - @HandlesTypes({ Viewport.class, BodySize.class, Inline.class }) - public static class HandlesTypesTest - implements ServletContainerInitializer { - - @Override - public void onStartup(Set> c, ServletContext ctx) - throws ServletException { - } - } - - public static class ExtendedHandlesTypesTest extends HandlesTypesTest { - - } - - @HandlesTypes({ HasErrorParameter.class, HasSomethingElse.class }) - public class HasErrorParameterTest implements ServletContainerInitializer { - @Override - public void onStartup(Set> c, ServletContext ctx) - throws ServletException { - } - } - - public interface HasSomethingElse { - - } - - public static class DummySomethingElse implements HasSomethingElse { - } - - public static class DummyHasErrorParameter implements HasErrorParameter { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 0; - } - - } - - @Test - public void selfReferencesAreRemoved() { - HandlesTypesTest annotationTest = new HandlesTypesTest(); - assertTypes(annotationTest, Set.of(Viewport.class), Set.of()); - assertTypes(annotationTest, - Set.of(Viewport.class, AnnotationValidatorTest.class), - Set.of(AnnotationValidatorTest.class)); - assertTypes(annotationTest, - Set.of(Viewport.class, AnnotationValidatorTest.class), - Set.of(AnnotationValidatorTest.class)); - - ExtendedHandlesTypesTest extendedAnnotationTest = new ExtendedHandlesTypesTest(); - assertTypes(extendedAnnotationTest, Set.of(Viewport.class), Set.of()); - - HasErrorParameterTest interfaceTest = new HasErrorParameterTest(); - - assertTypes(interfaceTest, Set.of(DummyHasErrorParameter.class), - Set.of(DummyHasErrorParameter.class)); - assertTypes(interfaceTest, Set.of(DummyHasErrorParameter.class), - Set.of(DummyHasErrorParameter.class)); - assertTypes(interfaceTest, - Set.of(HasErrorParameter.class, DummyHasErrorParameter.class), - Set.of(DummyHasErrorParameter.class)); - assertTypes(interfaceTest, - Set.of(HasErrorParameter.class, HasSomethingElse.class, - DummyHasErrorParameter.class, DummySomethingElse.class), - Set.of(DummyHasErrorParameter.class, DummySomethingElse.class)); - } - - private void assertTypes(Object testObject, Set> input, - Set> expectedOutput) { - Assert.assertEquals(expectedOutput, AbstractAnnotationValidator - .removeHandleTypesSelfReferences(input, testObject)); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/ApplicationConfigurationTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/ApplicationConfigurationTest.java deleted file mode 100644 index 3f2e9858efd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/ApplicationConfigurationTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import java.util.function.Supplier; - -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.server.VaadinContext; - -public class ApplicationConfigurationTest { - - @Test(expected = IllegalStateException.class) - public void get_contextHasNoLookup_iseIsThrown() { - VaadinContext context = Mockito.spy(VaadinContext.class); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(null); - Mockito.doAnswer( - invocation -> invocation.getArgument(1, Supplier.class).get()) - .when(context).getAttribute(Mockito.any(), Mockito.any()); - ApplicationConfiguration.get(context); - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/ApplicationRouteRegistryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/ApplicationRouteRegistryTest.java deleted file mode 100644 index 574389da9cd..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/ApplicationRouteRegistryTest.java +++ /dev/null @@ -1,394 +0,0 @@ -package com.vaadin.flow.server.startup; - -import jakarta.servlet.ServletContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.router.RouteBaseData; -import com.vaadin.flow.router.internal.ErrorTargetEntry; -import com.vaadin.flow.server.RouteRegistry; -import com.vaadin.flow.server.VaadinServletContext; - -/** - * Tests for {@link ApplicationRouteRegistry} instance . - */ -public class ApplicationRouteRegistryTest extends RouteRegistryTestBase { - - private ApplicationRouteRegistry registry; - - @Before - public void init() { - registry = ApplicationRouteRegistry.getInstance( - new VaadinServletContext(Mockito.mock(ServletContext.class))); - } - - @Test - public void assertApplicationRegistry() { - Assert.assertEquals(ApplicationRouteRegistry.class, - getTestedRegistry().getClass()); - } - - @Test - public void updateRoutesFromMultipleThreads_allRoutesAreRegistered() - throws InterruptedException, ExecutionException { - - List> callables = new ArrayList<>(); - callables.add(() -> { - try { - getTestedRegistry().setRoute("home", MyRoute.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getTestedRegistry().setRoute("info", MyInfo.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getTestedRegistry().setRoute("palace", MyPalace.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - ExecutorService executorService = Executors.newFixedThreadPool(5); - List> futures = executorService.invokeAll(callables); - - executorService.shutdown(); - - List exceptions = new ArrayList<>(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.value != null) { - exceptions.add(result.value); - } - } - - Assert.assertEquals( - "No exceptions should have been thrown for threaded updates.", - 0, exceptions.size()); - - Assert.assertTrue("Route 'home' was not registered into the scope.", - getTestedRegistry().getNavigationTarget("home").isPresent()); - Assert.assertTrue("Route 'info' was not registered into the scope.", - getTestedRegistry().getNavigationTarget("info").isPresent()); - Assert.assertTrue("Route 'palace' was not registered into the scope.", - getTestedRegistry().getNavigationTarget("palace").isPresent()); - } - - @Test - public void updateAndRemoveFromMultipleThreads_endResultAsExpected() - throws InterruptedException, ExecutionException { - - getTestedRegistry().setRoute("home", MyRoute.class, - Collections.emptyList()); - getTestedRegistry().setRoute("info", MyInfo.class, - Collections.emptyList()); - - List> callables = new ArrayList<>(); - callables.add(() -> { - try { - getTestedRegistry().removeRoute("info"); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getTestedRegistry().setRoute("modular", MyModular.class, - Collections.emptyList()); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - callables.add(() -> { - try { - getTestedRegistry().setRoute("palace", MyPalace.class, - Collections.emptyList()); - getTestedRegistry().removeRoute("home"); - } catch (Exception e) { - return new Result(e.getMessage()); - } - return new Result(null); - }); - - ExecutorService executorService = Executors.newFixedThreadPool(5); - List> futures = executorService.invokeAll(callables); - - executorService.shutdown(); - - List exceptions = new ArrayList<>(); - - for (Future resultFuture : futures) { - Result result = resultFuture.get(); - if (result.value != null) { - exceptions.add(result.value); - } - } - - Assert.assertEquals( - "No exceptions should have been thrown for threaded updates.", - 0, exceptions.size()); - - Assert.assertFalse( - "Route 'home' was still registered even though it should have been removed.", - getTestedRegistry().getNavigationTarget("home").isPresent()); - - Assert.assertFalse( - "Route 'info' was still registered even though it should have been removed.", - getTestedRegistry().getNavigationTarget("info").isPresent()); - - Assert.assertTrue("Route 'modular' was not registered into the scope.", - getTestedRegistry().getNavigationTarget("modular").isPresent()); - Assert.assertTrue("Route 'palace' was not registered into the scope.", - getTestedRegistry().getNavigationTarget("palace").isPresent()); - } - - private static class Result { - final String value; - - Result(String value) { - this.value = value; - } - } - - @Test - public void lockingConfiguration_newConfigurationIsGottenOnlyAfterUnlock() { - CountDownLatch waitReaderThread = new CountDownLatch(1); - CountDownLatch waitUpdaterThread = new CountDownLatch(2); - - Thread readerThread = new Thread() { - @Override - public void run() { - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - getTestedRegistry().getRegisteredRoutes().isEmpty()); - - awaitCountDown(waitUpdaterThread); - - Assert.assertTrue("Registry should still remain empty", - getTestedRegistry().getRegisteredRoutes().isEmpty()); - - waitReaderThread.countDown(); - } - }; - - readerThread.start(); - - getTestedRegistry().update(() -> { - getTestedRegistry().setRoute("", MyRoute.class, - Collections.emptyList()); - - waitUpdaterThread.countDown(); - - getTestedRegistry().setRoute("path", Secondary.class, - Collections.emptyList()); - - waitUpdaterThread.countDown(); - awaitCountDown(waitReaderThread); - - }); - - Assert.assertEquals( - "After unlock registry should be updated for others to configure with new data", - 2, getTestedRegistry().getRegisteredRoutes().size()); - } - - @Test - public void routeChangeListener_correctChangesAreReturned() { - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - getTestedRegistry().addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - getTestedRegistry().setRoute("", MyRoute.class, - Collections.emptyList()); - - Assert.assertFalse("Added should contain data for one entry", - added.isEmpty()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - Assert.assertEquals(MyRoute.class, added.get(0).getNavigationTarget()); - Assert.assertEquals("", added.get(0).getUrl()); - - getTestedRegistry().setRoute("home", Secondary.class, - Collections.emptyList()); - - Assert.assertFalse("Added should contain data for one entry", - added.isEmpty()); - Assert.assertEquals("Only latest change should be available", 1, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - Assert.assertEquals(Secondary.class, - added.get(0).getNavigationTarget()); - Assert.assertEquals("home", added.get(0).getUrl()); - - getTestedRegistry().removeRoute("home"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertFalse("One route should have gotten removed", - removed.isEmpty()); - - Assert.assertEquals(Secondary.class, - removed.get(0).getNavigationTarget()); - Assert.assertEquals("The 'home' route should have been removed", "home", - removed.get(0).getUrl()); - } - - @Test - public void routeChangeListener_blockChangesAreGivenCorrectlyInEvent() { - getTestedRegistry().setRoute("", MyRoute.class, - Collections.emptyList()); - - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - getTestedRegistry().addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - getTestedRegistry().update(() -> { - getTestedRegistry().removeRoute(""); - getTestedRegistry().setRoute("path", Secondary.class, - Collections.emptyList()); - getTestedRegistry().setRoute("", MyRoute.class, - Collections.singletonList(MainLayout.class)); - }); - - Assert.assertFalse("", added.isEmpty()); - Assert.assertEquals("", 2, added.size()); - Assert.assertFalse("", removed.isEmpty()); - - for (RouteBaseData data : added) { - if (data.getUrl().equals("")) { - Assert.assertEquals("MyRoute should have been added", - MyRoute.class, data.getNavigationTarget()); - Assert.assertEquals( - "MyRoute should have been seen as a update as the parent layouts changed.", - MainLayout.class, data.getParentLayout()); - } else { - Assert.assertEquals("", Secondary.class, - data.getNavigationTarget()); - } - } - - Assert.assertEquals("MyRoute should have been both removed and added", - MyRoute.class, removed.get(0).getNavigationTarget()); - Assert.assertEquals("Removed version should not have a parent layout", - Collections.emptyList(), removed.get(0).getParentLayouts()); - } - - @Test - public void routeWithAliases_eventShowsCorrectlyAsRemoved() { - List added = new ArrayList<>(); - List removed = new ArrayList<>(); - - getTestedRegistry().addRoutesChangeListener(event -> { - added.clear(); - removed.clear(); - added.addAll(event.getAddedRoutes()); - removed.addAll(event.getRemovedRoutes()); - }); - - getTestedRegistry().update(() -> { - getTestedRegistry().setRoute("main", Secondary.class, - Collections.emptyList()); - getTestedRegistry().setRoute("Alias1", Secondary.class, - Collections.emptyList()); - getTestedRegistry().setRoute("Alias2", Secondary.class, - Collections.emptyList()); - }); - - Assert.assertEquals( - "Main route and aliases should all be seen as added.", 3, - added.size()); - Assert.assertTrue("No routes should have been removed", - removed.isEmpty()); - - getTestedRegistry().removeRoute("Alias2"); - - Assert.assertTrue("No routes should have been added", added.isEmpty()); - Assert.assertEquals( - "Removing the alias route should be seen in the event", 1, - removed.size()); - } - - @Test - public void setErrorNavigationTargets_abstractClassesAreIgnored() { - registry.setErrorNavigationTargets(new HashSet<>( - Arrays.asList(ErrorView.class, AbstractErrorView.class))); - - Optional errorNavigationTarget = registry - .getErrorNavigationTarget(new NullPointerException()); - - Assert.assertTrue("Error navigation target was not registered", - errorNavigationTarget.isPresent()); - Assert.assertEquals("Wrong errorNavigationTarget was registered", - ErrorView.class, - errorNavigationTarget.get().getNavigationTarget()); - } - - @Override - protected RouteRegistry getInitializationRegistry() { - return registry; - } - - @Override - protected RouteRegistry getTestedRegistry() { - return registry; - } - - private void awaitCountDown(CountDownLatch countDownLatch) { - try { - countDownLatch.await(); - } catch (InterruptedException e) { - Assert.fail(); - } - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/CustomElementsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/CustomElementsTest.java deleted file mode 100644 index 73765d0973d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/CustomElementsTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.startup; - -import static org.hamcrest.CoreMatchers.is; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.hamcrest.MatcherAssert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; - -/** - * @author Vaadin Ltd - * @since 1.0. - */ -public class CustomElementsTest { - private CustomElements customElements; - - @Before - public void setUp() { - customElements = new CustomElements(); - } - - @Test - public void addSingleElement() { - addElementsAndCheckResults( - Collections.singletonList(CustomElement.class), - Collections.singletonList(CustomElement.class)); - } - - @Test(expected = IllegalStateException.class) - public void addDifferentElements() { - addElementsAndCheckResults( - Arrays.asList(Tag2_Extend.class, Tag2_NotExtend.class), - Arrays.asList(Tag2_Extend.class, Tag2_NotExtend.class)); - } - - @Test - public void addExtendingElements_superclassFirst() { - addElementsAndCheckResults( - Arrays.asList(CustomElement.class, Tag1_Extend1.class, - Tag1_Extend2.class, Tag1_Extend3.class), - Collections.singletonList(CustomElement.class)); - } - - @Test - public void addExtendingElements_superclassLast() { - addElementsAndCheckResults( - Arrays.asList(Tag1_Extend1.class, Tag1_Extend2.class, - Tag1_Extend3.class, CustomElement.class), - Collections.singletonList(CustomElement.class)); - } - - @Test - public void addTwoExtendingWithDifferentTag() { - addElementsAndCheckResults( - Arrays.asList(Tag1_Extend1.class, Tag2_Extend.class), - Arrays.asList(Tag1_Extend1.class, Tag2_Extend.class)); - } - - //////////////////////////////////////////////////////////////////////////////////////// - - private void addElementsAndCheckResults( - List> elementsToAdd, - List> expectedClasses) { - elementsToAdd.forEach( - element -> customElements.addElement(getTag(element), element)); - - MatcherAssert.assertThat( - "Custom elements should contain only one class that we put into", - customElements.computeTagToElementRelation(), - is(expectedClasses.stream().collect(Collectors.toMap( - CustomElementsTest::getTag, Function.identity())))); - } - - private static String getTag(Class clazz) { - return clazz.getAnnotation(Tag.class).value(); - } - - @Tag("custom-element") - private static class CustomElement extends Component { - } - - @Tag("custom-element") - private static class Tag1_Extend1 extends CustomElement { - } - - @Tag("custom-element") - private static class Tag1_Extend2 extends CustomElement { - } - - @Tag("custom-element") - private static class Tag1_Extend3 extends CustomElement { - } - - @Tag("different-element") - private static class Tag2_Extend extends CustomElement { - } - - @Tag("different-element") - private static class Tag2_NotExtend extends CustomElement { - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/DefaultApplicationConfigurationFactoryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/DefaultApplicationConfigurationFactoryTest.java deleted file mode 100644 index 9d2fe0b0816..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/DefaultApplicationConfigurationFactoryTest.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.nio.file.Files; -import java.util.Collections; -import java.util.List; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.VaadinConfig; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.frontend.FrontendUtils; - -import static com.vaadin.flow.server.Constants.VAADIN_SERVLET_RESOURCES; -import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_USE_V14_BOOTSTRAP; -import static com.vaadin.flow.server.frontend.FrontendUtils.TOKEN_FILE; - -public class DefaultApplicationConfigurationFactoryTest { - - @Rule - public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Test - public void getTokenFileFromClassloader_tokenFileIsRead_checkWebpackGeneratedFromContext() - throws IOException { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinConfig config = Mockito.mock(VaadinConfig.class); - - ResourceProvider resourceProvider = mockResourceProvider(config, - context); - - String path = VAADIN_SERVLET_RESOURCES + TOKEN_FILE; - - String content = "{ 'foo':'bar' }"; - mockClassPathTokenFile(resourceProvider, content); - - DefaultApplicationConfigurationFactory factory = new DefaultApplicationConfigurationFactory(); - - String tokenFileContent = factory.getTokenFileFromClassloader(context); - - Mockito.verify(resourceProvider) - .getApplicationResource(FrontendUtils.WEBPACK_GENERATED); - - Mockito.verify(resourceProvider).getApplicationResources(path); - - Assert.assertEquals(content, tokenFileContent.trim()); - } - - @Test - public void create_tokenFileIsReadFromClassloader_externalStatsFileIsReadFromTokenFile_predefinedContext() - throws MalformedURLException, IOException { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinConfig config = Mockito.mock(VaadinConfig.class); - - ResourceProvider resourceProvider = mockResourceProvider(config, - context); - - String content = "{ 'externalStatsFile':true }"; - mockClassPathTokenFile(resourceProvider, content); - - DefaultApplicationConfigurationFactory factory = new DefaultApplicationConfigurationFactory(); - ApplicationConfiguration configuration = factory.create(context); - - List propertyNames = Collections - .list(configuration.getPropertyNames()); - Assert.assertTrue( - propertyNames.contains(Constants.EXTERNAL_STATS_FILE)); - Assert.assertTrue(configuration - .getBooleanProperty(Constants.EXTERNAL_STATS_FILE, false)); - Assert.assertFalse(configuration.isProductionMode()); - Assert.assertFalse(configuration.enableDevServer()); - } - - @Test - public void create_tokenFileIsSetViaContext_externalStatsFileIsReadFromTokenFile_predefinedContext() - throws MalformedURLException, IOException { - String content = "{ 'externalStatsFile':true }"; - VaadinContext context = mockTokenFileViaContextParam(content); - - DefaultApplicationConfigurationFactory factory = new DefaultApplicationConfigurationFactory(); - ApplicationConfiguration configuration = factory.create(context); - - List propertyNames = Collections - .list(configuration.getPropertyNames()); - Assert.assertTrue( - propertyNames.contains(Constants.EXTERNAL_STATS_FILE)); - Assert.assertTrue(configuration - .getBooleanProperty(Constants.EXTERNAL_STATS_FILE, false)); - Assert.assertFalse(configuration.isProductionMode()); - Assert.assertFalse(configuration.enableDevServer()); - } - - @Test - public void create_tokenFileIsSetViaContext_externalStatsUrlIsReadFromTokenFile_predefinedContext() - throws MalformedURLException, IOException { - String content = "{ 'externalStatsUrl': 'http://my.server/static/stats.json'}"; - VaadinContext context = mockTokenFileViaContextParam(content); - - DefaultApplicationConfigurationFactory factory = new DefaultApplicationConfigurationFactory(); - ApplicationConfiguration configuration = factory.create(context); - - List propertyNames = Collections - .list(configuration.getPropertyNames()); - Assert.assertTrue(propertyNames.contains(Constants.EXTERNAL_STATS_URL)); - Assert.assertTrue(configuration - .getBooleanProperty(Constants.EXTERNAL_STATS_FILE, false)); - Assert.assertEquals("http://my.server/static/stats.json", configuration - .getStringProperty(Constants.EXTERNAL_STATS_URL, null)); - Assert.assertFalse(configuration.isProductionMode()); - Assert.assertFalse(configuration.enableDevServer()); - } - - @Test - public void create_tokenFileIsReadFromClassloader_externalStatsUrlIsReadFromTokenFile_predefinedContext() - throws IOException { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinConfig config = Mockito.mock(VaadinConfig.class); - - ResourceProvider resourceProvider = mockResourceProvider(config, - context); - - mockClassPathTokenFile(resourceProvider, - "{ 'externalStatsUrl': 'http://my.server/static/stats.json'}"); - - DefaultApplicationConfigurationFactory factory = new DefaultApplicationConfigurationFactory(); - ApplicationConfiguration configuration = factory.create(context); - - List propertyNames = Collections - .list(configuration.getPropertyNames()); - Assert.assertTrue(propertyNames.contains(Constants.EXTERNAL_STATS_URL)); - Assert.assertTrue(configuration - .getBooleanProperty(Constants.EXTERNAL_STATS_FILE, false)); - Assert.assertEquals("http://my.server/static/stats.json", configuration - .getStringProperty(Constants.EXTERNAL_STATS_URL, null)); - Assert.assertFalse(configuration.isProductionMode()); - Assert.assertFalse(configuration.enableDevServer()); - } - - @Test - public void create_propertiesAreReadFromContext() throws IOException { - VaadinContext context = Mockito.mock(VaadinContext.class); - VaadinConfig config = Mockito.mock(VaadinConfig.class); - ResourceProvider resourceProvider = mockResourceProvider(config, - context); - - Mockito.when(context.getContextParameterNames()).thenReturn( - Collections.enumeration(Collections.singleton("foo"))); - Mockito.when(context.getContextParameter("foo")).thenReturn("bar"); - - mockClassPathTokenFile(resourceProvider, "{}"); - - DefaultApplicationConfigurationFactory factory = new DefaultApplicationConfigurationFactory(); - ApplicationConfiguration configuration = factory.create(context); - - List propertyNames = Collections - .list(configuration.getPropertyNames()); - Assert.assertEquals(1, propertyNames.size()); - Assert.assertEquals("foo", propertyNames.get(0)); - Assert.assertEquals("bar", - configuration.getStringProperty("foo", null)); - } - - private void mockClassPathTokenFile(ResourceProvider resourceProvider, - String content) throws IOException, MalformedURLException { - String path = VAADIN_SERVLET_RESOURCES + TOKEN_FILE; - - File tmpFile = temporaryFolder.newFile(); - Files.write(tmpFile.toPath(), Collections.singletonList(content)); - - URLStreamHandler handler = new URLStreamHandler() { - - @Override - protected URLConnection openConnection(URL u) throws IOException { - return tmpFile.toURI().toURL().openConnection(); - } - }; - URL url = new URL("file", "", -1, "foo.jar!/" + path, handler); - - Mockito.when(resourceProvider.getApplicationResources(path)) - .thenReturn(Collections.singletonList(url)); - } - - private ResourceProvider mockResourceProvider(VaadinConfig config, - VaadinContext context) { - Mockito.when(config.getVaadinContext()).thenReturn(context); - - Mockito.when(context.getContextParameterNames()) - .thenReturn(Collections.emptyEnumeration()); - Mockito.when(config.getConfigParameterNames()) - .thenReturn(Collections.emptyEnumeration()); - - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - - Mockito.when(context.getAttribute(ApplicationConfiguration.class)) - .thenReturn(appConfig); - Mockito.when(context.getAttribute( - Mockito.eq(ApplicationConfiguration.class), Mockito.any())) - .thenReturn(appConfig); - - Lookup lookup = Mockito.mock(Lookup.class); - ResourceProvider resourceProvider = Mockito - .mock(ResourceProvider.class); - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(resourceProvider); - Mockito.when(context.getAttribute(Lookup.class)).thenReturn(lookup); - - return resourceProvider; - } - - private VaadinContext mockTokenFileViaContextParam(String content) - throws IOException { - VaadinContext context = Mockito.mock(VaadinContext.class); - Mockito.when(context.getContextParameterNames()) - .thenReturn(Collections.enumeration( - Collections.singleton(FrontendUtils.PARAM_TOKEN_FILE))); - - File tmpFile = temporaryFolder.newFile(); - Files.write(tmpFile.toPath(), Collections.singletonList(content)); - - Mockito.when( - context.getContextParameter(FrontendUtils.PARAM_TOKEN_FILE)) - .thenReturn(tmpFile.getPath()); - return context; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/LookupServletContainerInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/LookupServletContainerInitializerTest.java deleted file mode 100644 index 16508335f7e..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/LookupServletContainerInitializerTest.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.template.internal.DeprecatedPolymerPublishedEventHandler; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.LookupInitializer; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.function.VaadinApplicationInitializationBootstrap; -import com.vaadin.flow.router.RoutePathProvider; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.startup.testdata.TestResourceProvider; - -import elemental.json.JsonObject; -import elemental.json.JsonValue; - -public class LookupServletContainerInitializerTest { - - private LookupServletContainerInitializer initializer = new LookupServletContainerInitializer(); - - public static class TestPolymerPublishedEventHandler - implements DeprecatedPolymerPublishedEventHandler { - - @Override - public boolean isTemplateModelValue(Component instance, - JsonValue argValue, Class convertedType) { - return false; - } - - @Override - public Object getTemplateItem(Component template, JsonObject argValue, - Type convertedType) { - return null; - } - - } - - public static class TestApplicationConfigurationFactory - implements ApplicationConfigurationFactory { - @Override - public ApplicationConfiguration create(VaadinContext context) { - return null; - } - } - - public static class TestRoutePathProvider implements RoutePathProvider { - - @Override - public String getRoutePath(Class navigationTarget) { - return null; - } - - } - - private static class TestLookup implements Lookup { - - private Map, Collection>> services; - - @Override - public T lookup(Class serviceClass) { - return null; - } - - @Override - public Collection lookupAll(Class serviceClass) { - return null; - } - - } - - public static class TestLookupInitializer extends LookupInitializer { - - @Override - public void initialize(VaadinContext context, - Map, Collection>> services, - VaadinApplicationInitializationBootstrap bootstrap) - throws ServletException { - TestLookup lookup = new TestLookup(); - lookup.services = services; - bootstrap.bootstrap(lookup); - } - } - - @Test - public void processLookupServletContainerInitializer_resourceProviderIsProvidedAsScannedClass_lookupReturnsTheProviderInstance() - throws ServletException { - Lookup lookup = mockLookup(TestResourceProvider.class); - - ResourceProvider provider = lookup.lookup(ResourceProvider.class); - Assert.assertNotNull(provider); - Assert.assertEquals(TestResourceProvider.class, provider.getClass()); - - Collection allProviders = lookup - .lookupAll(ResourceProvider.class); - Assert.assertEquals(1, allProviders.size()); - - Assert.assertEquals(TestResourceProvider.class, - allProviders.iterator().next().getClass()); - } - - @Test - public void processLookupServletContainerInitializer_polymerPublishedEventHandlerIsProvidedAsScannedClass_lookupReturnsTheProviderInstance() - throws ServletException { - Lookup lookup = mockLookup(TestPolymerPublishedEventHandler.class); - - DeprecatedPolymerPublishedEventHandler handler = lookup - .lookup(DeprecatedPolymerPublishedEventHandler.class); - Assert.assertNotNull(handler); - Assert.assertEquals(TestPolymerPublishedEventHandler.class, - handler.getClass()); - - Collection allHandlers = lookup - .lookupAll(DeprecatedPolymerPublishedEventHandler.class); - Assert.assertEquals(1, allHandlers.size()); - - Assert.assertEquals(TestPolymerPublishedEventHandler.class, - allHandlers.iterator().next().getClass()); - } - - @Test - public void processLookupServletContainerInitializer_routePathProviderIsProvidedAsScannedClass_lookupReturnsTheProviderInstance() - throws ServletException { - Lookup lookup = mockLookup(TestRoutePathProvider.class); - - RoutePathProvider handler = lookup.lookup(RoutePathProvider.class); - Assert.assertNotNull(handler); - Assert.assertEquals(TestRoutePathProvider.class, handler.getClass()); - - Collection allHandlers = lookup - .lookupAll(RoutePathProvider.class); - Assert.assertEquals(1, allHandlers.size()); - - Assert.assertEquals(TestRoutePathProvider.class, - allHandlers.iterator().next().getClass()); - } - - @Test - public void processLookupServletContainerInitializer_contextHasDeferredInitializers_runInitializersAndClearAttribute() - throws ServletException { - ServletContext context = Mockito.mock(ServletContext.class); - DeferredServletContextInitializers deferredInitializers = Mockito - .mock(DeferredServletContextInitializers.class); - Mockito.when(context.getAttribute( - DeferredServletContextInitializers.class.getName())) - .thenReturn(deferredInitializers); - mockLookup(context); - - Mockito.verify(deferredInitializers).runInitializers(context); - Mockito.verify(context).removeAttribute( - DeferredServletContextInitializers.class.getName()); - } - - @Test - public void processApplicationConfigurationFactory_factoryIsProvided_providedFactoryIsCreated() - throws ServletException { - Lookup lookup = mockLookup(DefaultApplicationConfigurationFactory.class, - TestApplicationConfigurationFactory.class); - - ApplicationConfigurationFactory config = lookup - .lookup(ApplicationConfigurationFactory.class); - Assert.assertNotNull(config); - Assert.assertTrue( - config instanceof TestApplicationConfigurationFactory); - } - - @Test - public void process_customLookupInitializerIsProvided_servicesHasCustomImpls_customInitializerIsCalledWithProvidedImpls() - throws ServletException { - Lookup lookup = mockLookup(TestPolymerPublishedEventHandler.class, - TestResourceProvider.class, - TestApplicationConfigurationFactory.class, - TestLookupInitializer.class); - Assert.assertTrue(lookup instanceof TestLookup); - - TestLookup customLookup = (TestLookup) lookup; - Map, Collection>> services = customLookup.services; - Assert.assertFalse(services.containsKey(LookupInitializer.class)); - Assert.assertEquals(TestPolymerPublishedEventHandler.class, - services.get(DeprecatedPolymerPublishedEventHandler.class) - .iterator().next()); - Assert.assertEquals(TestResourceProvider.class, - services.get(ResourceProvider.class).iterator().next()); - Assert.assertEquals(TestApplicationConfigurationFactory.class, services - .get(ApplicationConfigurationFactory.class).iterator().next()); - } - - @Test - public void getServiceTypes_getServiceTypesIsInvoked_initializerIsInvokdedWithProvidedServices() - throws ServletException { - initializer = new LookupServletContainerInitializer() { - @Override - protected Collection> getServiceTypes() { - return Arrays.asList(List.class); - } - }; - - Lookup lookup = mockLookup(TestLookupInitializer.class, - ArrayList.class); - - Assert.assertTrue(lookup instanceof TestLookup); - - TestLookup customLookup = (TestLookup) lookup; - Map, Collection>> services = customLookup.services; - Assert.assertFalse(services.containsKey(LookupInitializer.class)); - Assert.assertTrue(services.containsKey(List.class)); - - Collection> collection = services.get(List.class); - Assert.assertEquals(1, collection.size()); - Assert.assertEquals(ArrayList.class, collection.iterator().next()); - } - - @Test(expected = ServletException.class) - public void process_classSetIsNull_throws() throws ServletException { - initializer.process(null, Mockito.mock(ServletContext.class)); - } - - private Lookup mockLookup(ServletContext context, Class... classes) - throws ServletException { - ArgumentCaptor lookupCapture = ArgumentCaptor - .forClass(Lookup.class); - - Stream> stream = Stream - .concat(Stream.of(LookupInitializer.class), Stream.of(classes)); - initializer.process(stream.collect(Collectors.toSet()), context); - - Mockito.verify(context).setAttribute(Mockito.eq(Lookup.class.getName()), - lookupCapture.capture()); - - return lookupCapture.getValue(); - } - - private Lookup mockLookup(Class... classes) throws ServletException { - return mockLookup(Mockito.mock(ServletContext.class), classes); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/RouteRegistryInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/RouteRegistryInitializerTest.java deleted file mode 100644 index 7b2d0130b34..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/RouteRegistryInitializerTest.java +++ /dev/null @@ -1,1630 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.page.BodySize; -import com.vaadin.flow.component.page.Inline; -import com.vaadin.flow.component.page.Viewport; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.OneTimeInitializerPredicate; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.BeforeEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasDynamicTitle; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.HasUrlParameter; -import com.vaadin.flow.router.NotFoundException; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.router.ParentLayout; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteAlias; -import com.vaadin.flow.router.RouteAliasData; -import com.vaadin.flow.router.RouteConfiguration; -import com.vaadin.flow.router.RouteData; -import com.vaadin.flow.router.RouteParameterRegex; -import com.vaadin.flow.router.RoutePathProvider; -import com.vaadin.flow.router.RoutePrefix; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.router.RouterTest.FileNotFound; -import com.vaadin.flow.router.RoutesChangedEvent; -import com.vaadin.flow.router.TestRouteRegistry; -import com.vaadin.flow.router.internal.ErrorTargetEntry; -import com.vaadin.flow.router.internal.HasUrlParameterFormat; -import com.vaadin.flow.router.internal.PathUtil; -import com.vaadin.flow.server.InitialPageSettings; -import com.vaadin.flow.server.InvalidRouteConfigurationException; -import com.vaadin.flow.server.InvalidRouteLayoutConfigurationException; -import com.vaadin.flow.server.MockVaadinContext; -import com.vaadin.flow.server.PageConfigurator; -import com.vaadin.flow.server.VaadinServletContext; - -/** - * Unit tests for RouteRegistryInitializer and RouteRegistry. - */ -public class RouteRegistryInitializerTest { - - private RouteRegistryInitializer routeRegistryInitializer; - private ApplicationRouteRegistry registry; - private ServletContext servletContext; - private VaadinServletContext vaadinContext; - private Lookup lookup; - private RoutePathProvider pathProvider; - - @Before - public void init() { - pathProvider = Mockito.mock(RoutePathProvider.class); - routeRegistryInitializer = new RouteRegistryInitializer(); - registry = new TestRouteRegistry(); - servletContext = Mockito.mock(ServletContext.class); - lookup = Mockito.mock(Lookup.class); - Mockito.when(servletContext.getAttribute(Lookup.class.getName())) - .thenReturn(lookup); - vaadinContext = new VaadinServletContext(servletContext); - registry = ApplicationRouteRegistry.getInstance(vaadinContext); - - Mockito.when(vaadinContext.getAttribute( - ApplicationRouteRegistry.ApplicationRouteRegistryWrapper.class)) - .thenReturn( - new ApplicationRouteRegistry.ApplicationRouteRegistryWrapper( - registry)); - - Mockito.when(lookup.lookup(RoutePathProvider.class)) - .thenReturn(pathProvider); - - Mockito.doAnswer(invocation -> { - Class clazz = invocation.getArgument(0, Class.class); - Annotation route = clazz.getAnnotation(Route.class); - return ((Route) route).value(); - }).when(pathProvider).getRoutePath(Mockito.any()); - } - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Test - public void process() throws ServletException { - routeRegistryInitializer.process( - Stream.of(NavigationTarget.class, NavigationTargetFoo.class, - NavigationTargetBar.class).collect(Collectors.toSet()), - servletContext); - - Assert.assertEquals("Route '' registered to NavigationTarget.class", - NavigationTarget.class, registry.getNavigationTarget("").get()); - Assert.assertEquals( - "Route 'foo' registered to NavigationTargetFoo.class", - NavigationTargetFoo.class, - registry.getNavigationTarget("foo").get()); - Assert.assertEquals( - "Route 'bar' registered to NavigationTargetBar.class", - NavigationTargetBar.class, - registry.getNavigationTarget("bar").get()); - } - - @Test - public void process_no_exception_with_null_arguments() { - try { - routeRegistryInitializer.process(null, servletContext); - } catch (Exception e) { - Assert.fail( - "RouteRegistryInitializer.process should not throw with null arguments"); - } - } - - @Test(expected = ServletException.class) - public void process_duplicate_routes_throws() throws ServletException { - routeRegistryInitializer.process( - Stream.of(NavigationTargetFoo.class, NavigationTargetFoo2.class) - .collect(Collectors.toSet()), - servletContext); - } - - @Test(expected = ServletException.class) - public void process_duplicate_routesViaAlias_throws() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(NavigationTargetBar.class, NavigationTargetBar2.class) - .collect(Collectors.toSet()), - servletContext); - } - - @Test - public void routeRegistry_fails_for_multiple_registration_of_same_route() { - expectedEx.expect(InvalidRouteConfigurationException.class); - expectedEx.expectMessage( - "Navigation targets must have unique routes, found navigation targets " - + "'com.vaadin.flow.server.startup.RouteRegistryInitializerTest$NavigationTargetFoo' and " - + "'com.vaadin.flow.server.startup.RouteRegistryInitializerTest$NavigationTargetFoo2' with the same route."); - - RouteConfiguration.forRegistry(registry) - .setAnnotatedRoute(NavigationTargetFoo.class); - - Assert.assertTrue("RouteRegistry should be initialized", - registry.hasNavigationTargets()); - - // Test should fail on this as there already exists a route for this - // route - RouteConfiguration.forRegistry(registry) - .setAnnotatedRoute(NavigationTargetFoo2.class); - } - - @Test - public void routeRegistry_registers_correctly_route_with_parentLayout() - throws ServletException { - routeRegistryInitializer.process(Stream - .of(NavigationTarget.class, NavigationTargetFoo.class, - MiddleParentWithRoute.class) - .collect(Collectors.toSet()), servletContext); - - Optional> navigationTarget = registry - .getNavigationTarget("middle_parent"); - - Assert.assertTrue("Couldn't find navigation target for `middle_parent`", - navigationTarget.isPresent()); - } - - @Test(expected = InvalidRouteLayoutConfigurationException.class) - public void routeRegistry_fails_on_aloneRouteAlias() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(NavigationTarget.class, NavigationTargetFoo.class, - RouteAliasAlone.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void routeRegistry_stores_whole_path_with_parent_route_prefix() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(ExtendingPrefix.class).collect(Collectors.toSet()), - servletContext); - - Optional> navigationTarget = registry - .getNavigationTarget("parent/prefix"); - - Assert.assertTrue("Couldn't find navigation target for `parent/prefix`", - navigationTarget.isPresent()); - Assert.assertEquals( - "Route 'parent/prefix' was not registered to ExtendingPrefix.class", - ExtendingPrefix.class, navigationTarget.get()); - } - - @Test - public void routeRegistry_route_with_absolute_ignores_parent_route_prefix() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(AbsoluteRoute.class).collect(Collectors.toSet()), - servletContext); - - Optional> navigationTarget = registry - .getNavigationTarget("absolute"); - - Assert.assertTrue("Could not find navigation target for `absolute`", - navigationTarget.isPresent()); - Assert.assertEquals("Route 'absolute' was not registered correctly", - AbsoluteRoute.class, navigationTarget.get()); - } - - @Test - public void routeRegistry_route_with_absolute_parent_prefix_ignores_remaining_parent_route_prefixes() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(MultiLevelRoute.class).collect(Collectors.toSet()), - servletContext); - - assertRouteTarget(MultiLevelRoute.class, "absolute/levels", - "Route 'absolute' was not registered correctly"); - } - - @Test - public void routeRegistry_routeWithAlias_parentRoutePrefix() - throws ServletException { - routeRegistryInitializer.process(Stream.of(MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - assertRouteTarget(MultiLevelRouteAlias.class, "absolute/levels", - "Route 'absolute' was not registered correctly"); - - Optional url = registry - .getTargetUrl(MultiLevelRouteAlias.class); - - Assert.assertTrue(url.isPresent()); - - Assert.assertEquals("absolute/levels", url.get()); - - assertRouteTarget(MultiLevelRouteAlias.class, "parent/alias1", - "RouteAlias 'alias1' was not registered correctly"); - } - - @Test - public void routeRegistry_routeWithAlias_parent_prefix_ignores_remaining_parent_route_prefixes() - throws ServletException { - routeRegistryInitializer.process(Stream.of(MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - assertRouteTarget(MultiLevelRouteAlias.class, "absolute/alias2", - "RouteAlias 'alias2' was not registered correctly"); - } - - @Test - public void routeRegistry_routeWithAlias_absoluteRoute() - throws ServletException { - routeRegistryInitializer.process(Stream.of(MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - assertRouteTarget(MultiLevelRouteAlias.class, "alias3", - "RouteAlias 'alias3' was not registered correctly"); - } - - @Test - public void routeRegistry_routeWithAlias_noParent() - throws ServletException { - routeRegistryInitializer.process(Stream.of(MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - assertRouteTarget(MultiLevelRouteAlias.class, "alias4", - "RouteAlias 'alias4' was not registered correctly"); - } - - @Test - public void routeRegistry_routeWithAlias_twoParentLevels() - throws ServletException { - routeRegistryInitializer.process(Stream.of(MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - assertRouteTarget(MultiLevelRouteAlias.class, "parent/middle/alias5", - "RouteAlias 'alias5' was not registered correctly"); - } - - @Test - public void routeRegistry_route_returns_registered_string_for_get_url() - throws ServletException { - routeRegistryInitializer.process(Stream - .of(NavigationTarget.class, NavigationTargetFoo.class, - AbsoluteRoute.class, ExtendingPrefix.class) - .collect(Collectors.toSet()), servletContext); - - Assert.assertEquals("", - registry.getTargetUrl(NavigationTarget.class).get()); - Assert.assertEquals("foo", - registry.getTargetUrl(NavigationTargetFoo.class).get()); - Assert.assertEquals("absolute", - registry.getTargetUrl(AbsoluteRoute.class).get()); - Assert.assertEquals("parent/prefix", - registry.getTargetUrl(ExtendingPrefix.class).get()); - } - - @Test - public void routeRegistry_routes_with_parameters_return_parameter_type_for_target_url() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(ParameterRoute.class, StringParameterRoute.class) - .collect(Collectors.toSet()), - servletContext); - - Assert.assertEquals( - String.format("parameter/:%s(%s)", - HasUrlParameterFormat.PARAMETER_NAME, - RouteParameterRegex.INTEGER), - registry.getTemplate(ParameterRoute.class).get()); - Assert.assertEquals( - String.format("string/:%s", - HasUrlParameterFormat.PARAMETER_NAME), - registry.getTemplate(StringParameterRoute.class).get()); - } - - @Test - public void routeRegistry_route_returns_string_not_ending_in_dash() - throws ServletException { - routeRegistryInitializer.process(Stream - .of(NavigationRootWithParent.class).collect(Collectors.toSet()), - servletContext); - - Assert.assertEquals( - "The root target for a parent layout should not end with '/'", - "parent", - registry.getTargetUrl(NavigationRootWithParent.class).get()); - } - - @Test - public void registration_fails_for_navigation_target_with_duplicate_title() - throws ServletException { - expectedEx.expect(DuplicateNavigationTitleException.class); - expectedEx.expectMessage(String.format( - "'%s' has a PageTitle annotation, but also implements HasDynamicTitle.", - FaultyNavigationTargetWithTitle.class.getName())); - - routeRegistryInitializer.process( - Collections.singleton(FaultyNavigationTargetWithTitle.class), - servletContext); - } - - @Test - public void registration_fails_for_navigation_target_with_inherited_dynamic_title() - throws ServletException { - expectedEx.expect(DuplicateNavigationTitleException.class); - expectedEx.expectMessage(String.format( - "'%s' has a PageTitle annotation, but also implements HasDynamicTitle.", - FaultyChildWithDuplicateTitle.class.getName())); - - routeRegistryInitializer.process( - Collections.singleton(FaultyChildWithDuplicateTitle.class), - servletContext); - } - - @Test - public void registration_succeeds_for_navigation_target_with_inherited_title_annotation() - throws ServletException { - routeRegistryInitializer.process( - Collections.singleton(ChildWithDynamicTitle.class), - servletContext); - - Assert.assertEquals("bar", - registry.getTargetUrl(ChildWithDynamicTitle.class).get()); - } - - @Route("") - private static class NavigationTarget extends Component { - } - - @Route("foo") - private static class NavigationTargetFoo extends Component { - } - - @Route("foo") - private static class NavigationTargetFoo2 extends Component { - } - - @Route("bar") - private static class NavigationTargetBar extends Component { - } - - @Route("bar2") - @RouteAlias("bar") - private static class NavigationTargetBar2 extends Component { - } - - private static class RouteParentLayout extends Component - implements RouterLayout { - } - - @Route(value = "", layout = ParentWithRoutePrefix.class) - private static class NavigationRootWithParent extends Component { - } - - @ParentLayout(RouteParentLayout.class) - @Route(value = "middle_parent") - private static class MiddleParentWithRoute extends Component - implements RouterLayout { - } - - @RouteAlias(value = "wrong") - private static class RouteAliasAlone extends Component { - } - - @RoutePrefix("parent") - private static class ParentWithRoutePrefix extends Component - implements RouterLayout { - } - - @Route(value = "prefix", layout = ParentWithRoutePrefix.class) - private static class ExtendingPrefix extends Component { - } - - @Route(value = "absolute", layout = ParentWithRoutePrefix.class, absolute = true) - private static class AbsoluteRoute extends Component { - } - - @RoutePrefix(value = "absolute", absolute = true) - @ParentLayout(ParentWithRoutePrefix.class) - private static class AbsoluteMiddleParent extends Component - implements RouterLayout { - } - - @RoutePrefix(value = "middle") - @ParentLayout(ParentWithRoutePrefix.class) - private static class MiddleParent extends Component - implements RouterLayout { - } - - @Route(value = "levels", layout = AbsoluteMiddleParent.class) - private static class MultiLevelRoute extends Component { - } - - @Route(value = "levels", layout = AbsoluteMiddleParent.class) - @RouteAlias(value = "alias1", layout = ParentWithRoutePrefix.class) - @RouteAlias(value = "alias2", layout = AbsoluteMiddleParent.class) - @RouteAlias(value = "alias3", absolute = true, layout = ParentWithRoutePrefix.class) - @RouteAlias(value = "alias4") - @RouteAlias(value = "alias5", layout = MiddleParent.class) - private static class MultiLevelRouteAlias extends Component { - } - - @Route("parameter") - private static class ParameterRoute extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, Integer parameter) { - - } - } - - @Route("string") - private static class StringParameterRoute extends Component - implements HasUrlParameter { - - @Override - public void setParameter(BeforeEvent event, String parameter) { - - } - } - - @Route("foo") - @PageTitle("Custom Title") - private static class FaultyNavigationTargetWithTitle extends Component - implements HasDynamicTitle { - - @Override - public String getPageTitle() { - return ""; - } - } - - @Route("foo") - private static class ParentWithDynamicTitle extends Component - implements HasDynamicTitle { - - @Override - public String getPageTitle() { - return "Parent View"; - } - } - - @Route("bar") - @PageTitle("Child View") - private static class FaultyChildWithDuplicateTitle - extends ParentWithDynamicTitle { - } - - @Route("foo") - @PageTitle("Parent View") - private static class ParentWithTitleAnnotation extends Component - implements HasDynamicTitle { - - @Override - public String getPageTitle() { - return ""; - } - } - - @Route("bar") - private static class ChildWithDynamicTitle - extends ParentWithTitleAnnotation { - - @Override - public String getPageTitle() { - return "Child View"; - } - } - - private void assertRouteTarget(Class routeClass, String path, - String errorMessage) { - Optional> navigationTarget = registry - .getNavigationTarget(path); - - Assert.assertTrue("Could not find navigation target for `" + path + "`", - navigationTarget.isPresent()); - Assert.assertEquals(errorMessage, routeClass, navigationTarget.get()); - } - - /* @Viewport tests */ - - @Route("single") - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class SingleNavigationTarget extends Component { - } - - @Tag(Tag.DIV) - public static class Parent extends Component implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(Parent.class) - @Viewport("width=device-width") - public static class MiddleParentLayout extends Component - implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(MiddleParentLayout.class) - @Viewport("width=device-width") - public static class MultiMiddleParentLayout extends Component - implements RouterLayout { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - public static class RootWithParent extends Component { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class RootViewportWithParent extends Component { - } - - @Route(value = "", layout = MiddleParentLayout.class) - @Tag(Tag.DIV) - public static class RootWithParents extends Component { - } - - @Route(value = "", layout = MultiMiddleParentLayout.class) - @Tag(Tag.DIV) - public static class MultiViewport extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = Parent.class) - @Tag(Tag.DIV) - @Viewport("width=device-width") - public static class FailingAliasView extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = Parent.class) - @Tag(Tag.DIV) - public static class AliasView extends Component { - } - - @Test - public void process_wrong_position_view_layout_throws() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "Viewport annotation should be on the top most route layout '%s'. Offending class: '%s'", - Parent.class.getName(), MiddleParentLayout.class.getName())); - - routeRegistryInitializer.process( - Stream.of(RootWithParents.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_check_only_one_viewport_in_route_chain() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage( - "Only one Viewport annotation is supported for navigation chain and should be on the top most level. Offending classes in chain: " - + MultiMiddleParentLayout.class.getName() + ", " - + MiddleParentLayout.class.getName()); - - routeRegistryInitializer.process( - Stream.of(MultiViewport.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_route_can_not_contain_viewport_if_has_parent() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "Viewport annotation needs to be on the top parent layout '%s' not on '%s'", - Parent.class.getName(), - RootViewportWithParent.class.getName())); - - routeRegistryInitializer.process(Stream.of(RootViewportWithParent.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_one_viewport_in_chain_and_one_for_route_passes() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(SingleNavigationTarget.class, RootWithParent.class) - .collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_check_also_faulty_alias_route() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "Viewport annotation needs to be on the top parent layout '%s' not on '%s'", - Parent.class.getName(), FailingAliasView.class.getName())); - - routeRegistryInitializer.process( - Stream.of(FailingAliasView.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_valid_alias_does_not_throw() throws ServletException { - routeRegistryInitializer.process( - Stream.of(AliasView.class).collect(Collectors.toSet()), - servletContext); - } - - /* BodySize tests */ - - @Route("single") - @Tag(Tag.DIV) - @BodySize(width = "100vw", height = "100vh") - public static class BodySingleNavigationTarget extends Component { - } - - @Tag(Tag.DIV) - public static class BodyParent extends Component implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(BodyParent.class) - @BodySize(width = "100vw", height = "100vh") - public static class BodyMiddleParentLayout extends Component - implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(BodyMiddleParentLayout.class) - @BodySize(width = "100vw", height = "100vh") - public static class BodyMultiMiddleParentLayout extends Component - implements RouterLayout { - } - - @Route(value = "", layout = BodyParent.class) - @Tag(Tag.DIV) - public static class BodyRootWithParent extends Component { - } - - @Route(value = "", layout = BodyParent.class) - @Tag(Tag.DIV) - @BodySize(width = "100vw", height = "100vh") - public static class BodyRootViewportWithParent extends Component { - } - - @Route(value = "", layout = BodyMiddleParentLayout.class) - @Tag(Tag.DIV) - public static class BodyRootWithParents extends Component { - } - - @Route(value = "", layout = BodyMultiMiddleParentLayout.class) - @Tag(Tag.DIV) - public static class BodyMultiViewport extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = BodyParent.class) - @Tag(Tag.DIV) - @BodySize(width = "100vw", height = "100vh") - public static class BodyFailingAliasView extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = BodyParent.class) - @Tag(Tag.DIV) - public static class BodyAliasView extends Component { - } - - @Test - public void process_wrong_position_body_size_view_layout_throws() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "BodySize annotation should be on the top most route layout '%s'. Offending class: '%s'", - BodyParent.class.getName(), - BodyMiddleParentLayout.class.getName())); - - routeRegistryInitializer.process(Stream.of(BodyRootWithParents.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_check_only_one_body_size_in_route_chain() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage( - "Only one BodySize annotation is supported for navigation chain and should be on the top most level. Offending classes in chain: " - + BodyMultiMiddleParentLayout.class.getName() + ", " - + BodyMiddleParentLayout.class.getName()); - - routeRegistryInitializer.process( - Stream.of(BodyMultiViewport.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_route_can_not_contain_body_size_if_has_parent() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "BodySize annotation needs to be on the top parent layout '%s' not on '%s'", - BodyParent.class.getName(), - BodyRootViewportWithParent.class.getName())); - - routeRegistryInitializer - .process(Stream.of(BodyRootViewportWithParent.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_one_body_size_in_chain_and_one_for_route_passes() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(BodySingleNavigationTarget.class, - BodyRootWithParent.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_check_also_faulty_body_size_alias_route() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "BodySize annotation needs to be on the top parent layout '%s' not on '%s'", - BodyParent.class.getName(), - BodyFailingAliasView.class.getName())); - - routeRegistryInitializer.process(Stream.of(BodyFailingAliasView.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_valid_body_size_alias_does_not_throw() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(BodyAliasView.class).collect(Collectors.toSet()), - servletContext); - } - - /* PageConfigurator tests */ - - @Route("single") - @Tag(Tag.DIV) - public static class SingleConfigurator extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @Tag(Tag.DIV) - public static class ParentConfigurator extends Component - implements RouterLayout, PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @Tag(Tag.DIV) - @ParentLayout(Parent.class) - public static class MiddleParentConfigurator extends Component - implements RouterLayout, PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @Route(value = "", layout = MiddleParentConfigurator.class) - @Tag(Tag.DIV) - public static class RootWithMultipleParentConfigurator extends Component { - } - - @Tag(Tag.DIV) - @ParentLayout(MiddleParentConfigurator.class) - public static class MultiMiddleParentConfigurator extends Component - implements RouterLayout, PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @Route(value = "", layout = MultiMiddleParentConfigurator.class) - @Tag(Tag.DIV) - public static class MultiConfigurator extends Component { - } - - @Route(value = "", layout = ParentConfigurator.class) - @Tag(Tag.DIV) - public static class RootWithParentConfigurator extends Component { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - public static class RootConfiguratorWithParent extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @Route("") - @RouteAlias(value = "alias", layout = Parent.class) - @Tag(Tag.DIV) - public static class FailingAliasConfigurator extends Component - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @Test - public void process_valid_page_configurator_does_not_throw() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(SingleConfigurator.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_wrong_position_page_configurator_throws() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "PageConfigurator implementation should be the top most route layout '%s'. Offending class: '%s'", - Parent.class.getName(), - MiddleParentConfigurator.class.getName())); - - routeRegistryInitializer - .process(Stream.of(RootWithMultipleParentConfigurator.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_check_only_one_page_configurator_in_route_chain() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage( - "Only one PageConfigurator implementation is supported for navigation chain and should be on the top most level. Offending classes in chain: " - + MultiMiddleParentConfigurator.class.getName() + ", " - + MiddleParentConfigurator.class.getName()); - - routeRegistryInitializer.process( - Stream.of(MultiConfigurator.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_route_can_not_contain_page_configurator_if_has_parent() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "PageConfigurator needs to be the top parent layout '%s' not '%s'", - Parent.class.getName(), - RootConfiguratorWithParent.class.getName())); - - routeRegistryInitializer - .process(Stream.of(RootConfiguratorWithParent.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_one_page_configurator_in_chain_and_one_for_route_passes() - throws ServletException { - routeRegistryInitializer.process(Stream - .of(SingleConfigurator.class, RootWithParentConfigurator.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_check_page_configurator_for_faulty_alias_route() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "PageConfigurator needs to be the top parent layout '%s' not '%s'", - Parent.class.getName(), - FailingAliasConfigurator.class.getName())); - - routeRegistryInitializer.process(Stream - .of(FailingAliasConfigurator.class).collect(Collectors.toSet()), - servletContext); - } - - /* Inline tests */ - - @Route("single") - @Tag(Tag.DIV) - @Inline(value = "inline.js", position = Inline.Position.PREPEND) - @Inline("inline.css") - public static class InlineSingleNavigationTarget extends Component { - } - - @Tag(Tag.DIV) - public static class InlineParent extends Component implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(InlineParent.class) - @Inline("inline.js") - public static class InlineMiddleParentLayout extends Component - implements RouterLayout { - } - - @Tag(Tag.DIV) - @ParentLayout(InlineMiddleParentLayout.class) - @Inline("inline.js") - public static class InlineMultiMiddleParentLayout extends Component - implements RouterLayout { - } - - @Route(value = "", layout = InlineParent.class) - @Tag(Tag.DIV) - public static class InlineRootWithParent extends Component { - } - - @Route(value = "", layout = InlineParent.class) - @Tag(Tag.DIV) - @Inline("inline.js") - public static class InlineRootViewportWithParent extends Component { - } - - @Route(value = "", layout = InlineMiddleParentLayout.class) - @Tag(Tag.DIV) - public static class InlineRootWithParents extends Component { - } - - @Route(value = "", layout = InlineMultiMiddleParentLayout.class) - @Tag(Tag.DIV) - public static class InlineMultiViewport extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = InlineParent.class) - @Tag(Tag.DIV) - @Inline("inline.js") - public static class InlineFailingAliasView extends Component { - } - - @Route("") - @RouteAlias(value = "alias", layout = InlineParent.class) - @Tag(Tag.DIV) - public static class InlineAliasView extends Component { - } - - @Test - public void process_wrong_position_inline_view_layout_throws() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "Inline annotation should be on the top most route layout '%s'. Offending class: '%s'", - InlineParent.class.getName(), - InlineMiddleParentLayout.class.getName())); - - routeRegistryInitializer.process(Stream.of(InlineRootWithParents.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_check_only_one_inline_in_route_chain() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage( - "Only one Inline annotation is supported for navigation chain and should be on the top most level. Offending classes in chain: " - + InlineMultiMiddleParentLayout.class.getName() + ", " - + InlineMiddleParentLayout.class.getName()); - - routeRegistryInitializer.process(Stream.of(InlineMultiViewport.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_route_can_not_contain_inline_if_has_parent() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "Inline annotation needs to be on the top parent layout '%s' not on '%s'", - InlineParent.class.getName(), - InlineRootViewportWithParent.class.getName())); - - routeRegistryInitializer - .process(Stream.of(InlineRootViewportWithParent.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_one_inline_in_chain_and_one_for_route_passes() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(InlineSingleNavigationTarget.class, - InlineRootWithParent.class).collect(Collectors.toSet()), - servletContext); - } - - @Test - public void process_check_also_faulty_inline_alias_route() - throws ServletException { - expectedEx.expect(InvalidRouteLayoutConfigurationException.class); - expectedEx.expectMessage(String.format( - "Inline annotation needs to be on the top parent layout '%s' not on '%s'", - InlineParent.class.getName(), - InlineFailingAliasView.class.getName())); - - routeRegistryInitializer.process(Stream.of(InlineFailingAliasView.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_valid_inline_alias_does_not_throw() - throws ServletException { - routeRegistryInitializer.process( - Stream.of(InlineAliasView.class).collect(Collectors.toSet()), - servletContext); - } - - /* RouteData tests */ - - @Test - public void routeData_returns_all_registered_routes() - throws ServletException { - Set> routes = Stream.of(NavigationTarget.class, - NavigationTargetFoo.class, NavigationTargetBar.class) - .collect(Collectors.toSet()); - routeRegistryInitializer.process(routes, servletContext); - List registeredRoutes = registry.getRegisteredRoutes(); - - Assert.assertEquals("Not all registered routes were returned", 3, - registeredRoutes.size()); - - Set> collectedRoutes = registeredRoutes.stream() - .map(RouteData::getNavigationTarget) - .collect(Collectors.toSet()); - - Assert.assertTrue("Not all targets were correct", - routes.containsAll(collectedRoutes)); - } - - @Test - public void routeData_gets_correct_urls_for_targets() - throws ServletException { - routeRegistryInitializer.process(Stream.of(NavigationTarget.class, - NavigationRootWithParent.class, AbsoluteRoute.class, - ExtendingPrefix.class, StringParameterRoute.class, - ParameterRoute.class, MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - List registeredRoutes = registry.getRegisteredRoutes(); - - Assert.assertEquals("Not all registered routes were returned", 7, - registeredRoutes.size()); - - // RouteData should be sorted by template - Assert.assertEquals("Sort order was not the one expected", "", - registeredRoutes.get(0).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", "absolute", - registeredRoutes.get(1).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", - "absolute/levels", registeredRoutes.get(2).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", - HasUrlParameterFormat.getTemplate("parameter", - ParameterRoute.class), - registeredRoutes.get(3).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", "parent", - registeredRoutes.get(4).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", - "parent/prefix", registeredRoutes.get(5).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", - HasUrlParameterFormat.getTemplate("string", - StringParameterRoute.class), - registeredRoutes.get(6).getTemplate()); - } - - @Test - public void routeData_gets_correct_parents_for_targets() - throws ServletException { - routeRegistryInitializer.process(Stream.of(NavigationTarget.class, - NavigationRootWithParent.class, AbsoluteRoute.class, - ExtendingPrefix.class, StringParameterRoute.class, - ParameterRoute.class, MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - List registeredRoutes = registry.getRegisteredRoutes(); - - Assert.assertEquals("Not all registered routes were returned", 7, - registeredRoutes.size()); - - Assert.assertEquals("Parent is wrongly set to data", - Collections.emptyList(), - registeredRoutes.get(0).getParentLayouts()); - Assert.assertEquals("Parent is wrongly set to data", - ParentWithRoutePrefix.class, - registeredRoutes.get(1).getParentLayout()); - Assert.assertEquals("Parent is wrongly set to data", - AbsoluteMiddleParent.class, - registeredRoutes.get(2).getParentLayout()); - Assert.assertEquals("Parent is wrongly set to data", - Collections.emptyList(), - registeredRoutes.get(3).getParentLayouts()); - Assert.assertEquals("Parent is wrongly set to data", - ParentWithRoutePrefix.class, - registeredRoutes.get(4).getParentLayout()); - Assert.assertEquals("Parent is wrongly set to data", - ParentWithRoutePrefix.class, - registeredRoutes.get(5).getParentLayout()); - Assert.assertEquals("Parent is wrongly set to data", - Collections.emptyList(), - registeredRoutes.get(6).getParentLayouts()); - - } - - @Test - public void routeData_gets_correct_parameters_for_targets() - throws ServletException { - routeRegistryInitializer.process(Stream.of(NavigationTarget.class, - NavigationRootWithParent.class, AbsoluteRoute.class, - ExtendingPrefix.class, StringParameterRoute.class, - ParameterRoute.class, MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - List registeredRoutes = registry.getRegisteredRoutes(); - - Assert.assertEquals("Not all registered routes were returned", 7, - registeredRoutes.size()); - - Assert.assertEquals("Unexpected parameters encountered", 0, - registeredRoutes.get(0).getRouteParameters().size()); - Assert.assertEquals("Unexpected parameters encountered", 0, - registeredRoutes.get(1).getRouteParameters().size()); - Assert.assertEquals("Unexpected parameters encountered", 0, - registeredRoutes.get(2).getRouteParameters().size()); - Assert.assertEquals("Missing parameters", 1, - registeredRoutes.get(3).getRouteParameters().size()); - - Assert.assertEquals("Unexpected parameters encountered", 0, - registeredRoutes.get(4).getRouteParameters().size()); - Assert.assertEquals("Unexpected parameters encountered", 0, - registeredRoutes.get(5).getRouteParameters().size()); - Assert.assertEquals("Missing parameters", 1, - registeredRoutes.get(6).getRouteParameters().size()); - - Assert.assertEquals("Unexpected parameter type encountered", - ":" + HasUrlParameterFormat.PARAMETER_NAME + "(" - + RouteParameterRegex.INTEGER + ")", - registeredRoutes.get(3).getRouteParameters() - .get(HasUrlParameterFormat.PARAMETER_NAME) - .getTemplate()); - Assert.assertEquals("Unexpected parameter type encountered", - ":" + HasUrlParameterFormat.PARAMETER_NAME, - registeredRoutes.get(6).getRouteParameters() - .get(HasUrlParameterFormat.PARAMETER_NAME) - .getTemplate()); - } - - @Test - public void routeData_for_alias_data_is_correct() throws ServletException { - routeRegistryInitializer.process(Stream.of(MultiLevelRouteAlias.class) - .collect(Collectors.toSet()), servletContext); - - List registeredRoutes = registry.getRegisteredRoutes(); - - Assert.assertEquals("Not all registered routes were returned", 1, - registeredRoutes.size()); - - RouteData routeData = registeredRoutes.get(0); - Assert.assertEquals("Not all registered routes were returned", 5, - routeData.getRouteAliases().size()); - - List routeAliases = routeData.getRouteAliases(); - - Assert.assertEquals("Sort order was not the one expected", - "absolute/alias2", routeAliases.get(0).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", "alias3", - routeAliases.get(1).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", "alias4", - routeAliases.get(2).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", - "parent/alias1", routeAliases.get(3).getTemplate()); - Assert.assertEquals("Sort order was not the one expected", - "parent/middle/alias5", routeAliases.get(4).getTemplate()); - - Assert.assertEquals("Sort order was not the one expected", - AbsoluteMiddleParent.class, - routeAliases.get(0).getParentLayout()); - Assert.assertEquals("Sort order was not the one expected", - ParentWithRoutePrefix.class, - routeAliases.get(1).getParentLayout()); - Assert.assertEquals("Sort order was not the one expected", - Collections.emptyList(), - routeAliases.get(2).getParentLayouts()); - Assert.assertEquals("Sort order was not the one expected", - ParentWithRoutePrefix.class, - routeAliases.get(3).getParentLayout()); - Assert.assertEquals("Sort order was not the one expected", - MiddleParent.class, routeAliases.get(4).getParentLayout()); - } - - @Route("ignored") - public static class IgnoredView extends Component { - } - - public static class TestRouteFilter implements NavigationTargetFilter { - @Override - public boolean testNavigationTarget( - Class navigationTarget) { - return !navigationTarget.getSimpleName().startsWith("Ignored"); - } - - @Override - public boolean testErrorNavigationTarget( - Class errorNavigationTarget) { - return !errorNavigationTarget.getSimpleName().startsWith("Ignored"); - } - } - - // An additional filter to test that it's not enough to have only one - // passing filter - public static class AlwaysTrueRouterFilter - implements NavigationTargetFilter { - @Override - public boolean testNavigationTarget( - Class navigationTarget) { - return true; - } - - @Override - public boolean testErrorNavigationTarget( - Class errorNavigationTarget) { - return true; - } - } - - @Test - public void routeFilter_ignoresRoutes() - throws InvalidRouteConfigurationException, ServletException { - routeRegistryInitializer - .process(Stream.of(IgnoredView.class, NavigationTarget.class) - .collect(Collectors.toSet()), servletContext); - - List registeredTargets = registry.getRegisteredRoutes().stream() - .map(RouteData::getNavigationTarget) - .collect(Collectors.toList()); - Assert.assertEquals(Arrays.asList(NavigationTarget.class), - registeredTargets); - } - - public static class IgnoredErrorView extends Component - implements HasErrorParameter { - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 0; - } - } - - @Test - public void routeFilter_ignoresErrorTargets() - throws InvalidRouteConfigurationException { - registry.setErrorNavigationTargets( - Stream.of(IgnoredErrorView.class, FileNotFound.class) - .collect(Collectors.toSet())); - - Assert.assertTrue(registry - .getErrorNavigationTarget(new NotFoundException()).isPresent()); - - ErrorTargetEntry errorTargetEntry = registry - .getErrorNavigationTarget(new Exception()).get(); - - Assert.assertNotEquals(IgnoredErrorView.class, - errorTargetEntry.getNavigationTarget()); - } - - @Test - public void registerClassesWithSameRoute_abstractClass_subclass_subclassIsRegistered() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(AbstractRouteTarget.class); - classes.add(BaseRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - - Assert.assertEquals(BaseRouteTarget.class, - registry.getNavigationTarget("foo").get()); - } - - @Test - public void registerClassesWithSameRoute_class_abstractSuperClass_subclassIsRegistered() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(BaseRouteTarget.class); - classes.add(AbstractRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - - Assert.assertEquals(BaseRouteTarget.class, - registry.getNavigationTarget("foo").get()); - } - - @Test - public void registerClassesWithSameRoute_class_subclass_subclassIsRegistered() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(BaseRouteTarget.class); - classes.add(SuperRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - - Assert.assertEquals(SuperRouteTarget.class, - registry.getNavigationTarget("foo").get()); - } - - @Test - public void registerClassesWithSameRoute_class_superClass_subclassIsRegistered() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(SuperRouteTarget.class); - classes.add(BaseRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - - Assert.assertEquals(SuperRouteTarget.class, - registry.getNavigationTarget("foo").get()); - } - - @Test(expected = ServletException.class) - public void registerClassesWithSameRoute_absatrctClass_unrelatedClass_throws() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(AbstractRouteTarget.class); - classes.add(OtherRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - } - - @Test(expected = ServletException.class) - public void registerClassesWithSameRoute_unrelatedClass_abstractClass_throws() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(OtherRouteTarget.class); - classes.add(AbstractRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - } - - @Test(expected = ServletException.class) - public void registerClassesWithSameRoute_class_unrelatedClass_throws() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(BaseRouteTarget.class); - classes.add(OtherRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - } - - @Test(expected = ServletException.class) - public void registerClassesWithSameRoute_unrelatedClass_class_throws() - throws ServletException { - LinkedHashSet> classes = new LinkedHashSet<>(); - classes.add(OtherRouteTarget.class); - classes.add(BaseRouteTarget.class); - routeRegistryInitializer.process(classes, servletContext); - } - - @Test - public void initialize_predicateReturnsTrue_noPrevopusStaticRoutes_cleanIsNotCalled_removeMethodIsNotCalled() - throws VaadinInitializerException { - Mockito.when(lookup.lookup(OneTimeInitializerPredicate.class)) - .thenReturn(() -> true); - TestApplicationRouteRegistry registry = new TestApplicationRouteRegistry(); - Mockito.when(servletContext - .getAttribute(registry.wrapper.getClass().getName())) - .thenReturn(registry.wrapper); - - routeRegistryInitializer.initialize( - Collections.singleton(BaseRouteTarget.class), vaadinContext); - Assert.assertFalse(registry.cleanCalled); - Assert.assertFalse(registry.removeCalled); - } - - @Test - public void initialize_predicateReturnsTrue_sameRouteIsReadded_eventHasNoReaddedRoute() - throws VaadinInitializerException { - Mockito.when(lookup.lookup(OneTimeInitializerPredicate.class)) - .thenReturn(() -> true); - - routeRegistryInitializer.initialize( - new HashSet<>(Arrays.asList(OldRouteTarget.class)), - vaadinContext); - - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(vaadinContext); - Assert.assertEquals(1, registry.getRegisteredRoutes().size()); - - AtomicReference event = new AtomicReference<>(); - registry.addRoutesChangeListener(event::set); - - routeRegistryInitializer.initialize(new HashSet<>( - Arrays.asList(OldRouteTarget.class, BaseRouteTarget.class)), - vaadinContext); - Assert.assertEquals(2, registry.getRegisteredRoutes().size()); - - Assert.assertTrue(event.get().getRemovedRoutes().isEmpty()); - Assert.assertEquals(1, event.get().getAddedRoutes().size()); - } - - @Test - public void initialize_noPredicate_noPrevopusStaticRoutes_cleanIsNotCalled_removeMethodIsNotCalled() - throws VaadinInitializerException { - TestApplicationRouteRegistry registry = new TestApplicationRouteRegistry(); - Mockito.when(servletContext - .getAttribute(registry.wrapper.getClass().getName())) - .thenReturn(registry.wrapper); - - routeRegistryInitializer.initialize( - Collections.singleton(BaseRouteTarget.class), vaadinContext); - Assert.assertFalse(registry.cleanCalled); - Assert.assertFalse(registry.removeCalled); - } - - @Test - public void initialize_noPredicate_hasPrevopusStaticRoutes_previousRoutesAreRemoved() - throws VaadinInitializerException { - ApplicationRouteRegistry registry = firstInitRouteRegistry(); - - // second time initialization - - routeRegistryInitializer.initialize( - Collections.singleton(BaseRouteTarget.class), vaadinContext); - Assert.assertEquals(1, registry.getRegisteredRoutes().size()); - Assert.assertTrue( - registry.getTemplate(BaseRouteTarget.class).isPresent()); - } - - @Test - public void initialize_noPredicate_hasPrevopusStaticRoutes_addRouteManually_previousRoutesAreRemoved_addedRouteIsPreserved() - throws VaadinInitializerException { - ApplicationRouteRegistry registry = firstInitRouteRegistry(); - - // now add a route via registry API without registry initializer - - registry.setRoute("manual-route", Component.class, - Collections.emptyList()); - - // second time initialization - - routeRegistryInitializer.initialize( - Collections.singleton(BaseRouteTarget.class), vaadinContext); - // two routes: manually added and set during init phase - - Assert.assertTrue( - registry.getTemplate(BaseRouteTarget.class).isPresent()); - Assert.assertTrue(registry.getNavigationTarget( - PathUtil.getPath("manual-route", Collections.emptyList())) - .isPresent()); - } - - private ApplicationRouteRegistry firstInitRouteRegistry() - throws VaadinInitializerException { - vaadinContext = new VaadinServletContext(servletContext) { - - private Map, Object> map = new HashMap<>(); - - @Override - public T getAttribute(Class type) { - if (Lookup.class.equals(type)) { - return type.cast(lookup); - } else { - return type.cast(map.get(type)); - } - } - - @Override - public void setAttribute(Class clazz, T value) { - map.put(clazz, value); - } - }; - // first time initialization - routeRegistryInitializer.initialize( - Collections.singleton(OldRouteTarget.class), vaadinContext); - - ApplicationRouteRegistry registry = ApplicationRouteRegistry - .getInstance(vaadinContext); - List routes = registry.getRegisteredRoutes(); - // self check - - Assert.assertEquals(1, routes.size()); - RouteData data = routes.get(0); - Assert.assertEquals("foo-bar", data.getTemplate()); - List aliases = data.getRouteAliases(); - Assert.assertEquals(1, aliases.size()); - RouteAliasData alias = aliases.get(0); - Assert.assertEquals("baz", alias.getTemplate()); - return registry; - } - - private static class TestApplicationRouteRegistry - extends ApplicationRouteRegistry { - - ApplicationRouteRegistryWrapper wrapper = new ApplicationRouteRegistryWrapper( - this); - - boolean cleanCalled; - - boolean removeCalled; - - TestApplicationRouteRegistry() { - super(new MockVaadinContext()); - } - - @Override - public void clean() { - cleanCalled = true; - } - - @Override - public void removeRoute(Class navigationTarget) { - removeCalled = true; - } - - @Override - public void removeRoute(String path) { - removeCalled = true; - } - - @Override - public void removeRoute(String path, - Class navigationTarget) { - removeCalled = true; - } - } - - @Tag(Tag.DIV) - @Route("foo") - private abstract static class AbstractRouteTarget extends Component { - - } - - @Tag(Tag.DIV) - @Route("foo") - private static class BaseRouteTarget extends AbstractRouteTarget { - - } - - @Tag(Tag.DIV) - @Route("foo") - private static class SuperRouteTarget extends BaseRouteTarget { - - } - - @Tag(Tag.DIV) - @Route("foo") - private static class OtherRouteTarget extends Component { - - } - - @Tag(Tag.DIV) - @Route("foo-bar") - @RouteAlias("baz") - private static class OldRouteTarget extends AbstractRouteTarget { - - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/RouteRegistryTestBase.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/RouteRegistryTestBase.java deleted file mode 100644 index f16faf02b9d..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/RouteRegistryTestBase.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.router.BeforeEnterEvent; -import com.vaadin.flow.router.ErrorParameter; -import com.vaadin.flow.router.HasErrorParameter; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouteAlias; -import com.vaadin.flow.router.RouteData; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.RouteRegistry; - -@NotThreadSafe -public abstract class RouteRegistryTestBase { - - @Test - public void initializedRoutes_routesCanBeAdded() { - getInitializationRegistry().clean(); - - getInitializationRegistry().setRoute("home", MyRoute.class, - Collections.emptyList()); - getInitializationRegistry().setRoute("info", MyInfo.class, - Collections.emptyList()); - - Assert.assertEquals( - "Initial registration of routes should have succeeded.", 2, - getTestedRegistry().getRegisteredRoutes().size()); - - getTestedRegistry().setRoute("palace", MyPalace.class, - Collections.emptyList()); - getTestedRegistry().setRoute("modular", MyModular.class, - Collections.emptyList()); - - Assert.assertEquals("All new routes should have been registered", 4, - getTestedRegistry().getRegisteredRoutes().size()); - - getTestedRegistry().setRoute("withAliases", MyRouteWithAliases.class, - Collections.emptyList()); - getTestedRegistry().setRoute("version", MyRouteWithAliases.class, - Collections.emptyList()); - getTestedRegistry().setRoute("person", MyRouteWithAliases.class, - Collections.emptyList()); - - Assert.assertEquals("The new route should have registered", 5, - getTestedRegistry().getRegisteredRoutes().size()); - } - - @Test - public void registeringRouteWithAlias_RouteDataIsPopulatedCorrectly() { - getInitializationRegistry().clean(); - - getInitializationRegistry().setRoute("home", MyRoute.class, - Collections.emptyList()); - getInitializationRegistry().setRoute("info", MyInfo.class, - Collections.emptyList()); - - getInitializationRegistry().setRoute("withAliases", - MyRouteWithAliases.class, Collections.emptyList()); - getInitializationRegistry().setRoute("version", - MyRouteWithAliases.class, Collections.emptyList()); - getInitializationRegistry().setRoute("person", MyRouteWithAliases.class, - Collections.emptyList()); - - Optional first = getTestedRegistry() - .getRegisteredRoutes().stream().filter(route -> route - .getNavigationTarget().equals(MyRouteWithAliases.class)) - .findFirst(); - Assert.assertTrue("Didn't get RouteData for MyRouteWithAliases.", - first.isPresent()); - - Assert.assertEquals("Expected two route aliases to be registered", 2, - first.get().getRouteAliases().size()); - } - - @Test - public void registeredRouteWithAlias_removingClassRemovesAliases() { - getInitializationRegistry().clean(); - - getInitializationRegistry().setRoute("withAliases", - MyRouteWithAliases.class, Collections.emptyList()); - getInitializationRegistry().setRoute("version", - MyRouteWithAliases.class, Collections.emptyList()); - getInitializationRegistry().setRoute("person", MyRouteWithAliases.class, - Collections.emptyList()); - - Assert.assertTrue( - "Registry didn't contain routes even though 3 should have been registered", - !getTestedRegistry().getRegisteredRoutes().isEmpty()); - - Assert.assertTrue("Path for main route 'withAliases' returned empty", - getTestedRegistry().getNavigationTarget("withAliases") - .isPresent()); - Assert.assertTrue("RouteAlias 'version' returned empty.", - getTestedRegistry().getNavigationTarget("version").isPresent()); - Assert.assertTrue("RouteAlias 'person' returned empty.", - getTestedRegistry().getNavigationTarget("person").isPresent()); - - getTestedRegistry().removeRoute(MyRouteWithAliases.class); - - Assert.assertFalse( - "Registry should be empty after removing the only registered Class.", - !getTestedRegistry().getRegisteredRoutes().isEmpty()); - } - - @Test - public void registeredRouteWithAlias_removingPathLeavesAliases() { - getInitializationRegistry().clean(); - - getInitializationRegistry().setRoute("withAliases", - MyRouteWithAliases.class, Collections.emptyList()); - getInitializationRegistry().setRoute("version", - MyRouteWithAliases.class, Collections.emptyList()); - getInitializationRegistry().setRoute("person", MyRouteWithAliases.class, - Collections.emptyList()); - - Assert.assertTrue( - "Registry didn't contain routes even though 3 should have been registered", - !getTestedRegistry().getRegisteredRoutes().isEmpty()); - - Assert.assertTrue("Path for main route 'withAliases' returned empty", - getTestedRegistry().getNavigationTarget("withAliases") - .isPresent()); - Assert.assertTrue("RouteAlias 'version' returned empty.", - getTestedRegistry().getNavigationTarget("version").isPresent()); - Assert.assertTrue("RouteAlias 'person' returned empty.", - getTestedRegistry().getNavigationTarget("person").isPresent()); - - getTestedRegistry().removeRoute("withAliases"); - - Assert.assertTrue("Registry should contain alias routes", - !getTestedRegistry().getRegisteredRoutes().isEmpty()); - - Assert.assertEquals( - "One RouteAlias should be the main url so only 1 route alias should be marked as an alias", - 1, getTestedRegistry().getRegisteredRoutes().get(0) - .getRouteAliases().size()); - } - - @Test - public void routesWithParentLayouts_parentLayoutReturnsAsExpected() { - getInitializationRegistry().clean(); - - getInitializationRegistry().setRoute("MyRoute", - MyRouteWithAliases.class, - Collections.singletonList(MainLayout.class)); - getInitializationRegistry().setRoute("info", MyRouteWithAliases.class, - Collections.emptyList()); - getInitializationRegistry().setRoute("version", - MyRouteWithAliases.class, - Arrays.asList(MiddleLayout.class, MainLayout.class)); - - Assert.assertFalse("'MyRoute' should have a single parent", - getTestedRegistry() - .getRouteLayouts("MyRoute", MyRouteWithAliases.class) - .isEmpty()); - Assert.assertTrue("'info' should have no parents.", getTestedRegistry() - .getRouteLayouts("info", MyRouteWithAliases.class).isEmpty()); - Assert.assertEquals("'version' should return two parents", 2, - getTestedRegistry() - .getRouteLayouts("version", MyRouteWithAliases.class) - .size()); - } - - @Test - public void registeredParentLayouts_changingListDoesntChangeRegistration() { - getInitializationRegistry().clean(); - - List> parentChain = new ArrayList<>( - Arrays.asList(MiddleLayout.class, MainLayout.class)); - - getInitializationRegistry().setRoute("version", MyRoute.class, - parentChain); - - parentChain.remove(MainLayout.class); - - Assert.assertEquals( - "'version' should return two parents even when original list is changed", - 2, getTestedRegistry().getRouteLayouts("version", MyRoute.class) - .size()); - } - - @Test - public void registeredParentLayouts_returnedListInSameOrder() { - getInitializationRegistry().clean(); - - List> parentChain = new ArrayList<>( - Arrays.asList(MiddleLayout.class, MainLayout.class)); - - getInitializationRegistry().setRoute("version", MyRoute.class, - parentChain); - - Assert.assertArrayEquals( - "Registry should return parent layouts in the same order as set.", - parentChain.toArray(), getTestedRegistry() - .getRouteLayouts("version", MyRoute.class).toArray()); - } - - /** - * Returns registry which is used to initialize the registry with data. - * - * @return initialization registry - */ - protected abstract RouteRegistry getInitializationRegistry(); - - /** - * Returns registry which is tested. - *

    - * This may be the same registry which is returned by - * {@link #getInitializationRegistry()} but doesn't have to be. - * - * @return the tested registry - */ - protected abstract RouteRegistry getTestedRegistry(); - - @Tag("div") - @Route("home") - protected static class MyRoute extends Component { - } - - @Tag("div") - @Route("info") - protected static class MyInfo extends Component { - } - - @Tag("div") - @Route("palace") - protected static class MyPalace extends Component { - } - - @Tag("div") - protected static class Secondary extends Component { - } - - @Tag("div") - @Route("modular") - protected static class MyModular extends Component { - } - - @Tag("div") - @Route("withAliases") - @RouteAlias("version") - @RouteAlias("person") - protected static class MyRouteWithAliases extends Component { - } - - @Tag("div") - protected static class MainLayout extends Component - implements RouterLayout { - } - - @Tag("div") - protected static class MiddleLayout extends Component - implements RouterLayout { - } - - @Tag("div") - public static abstract class AbstractErrorView - extends Component implements HasErrorParameter { - } - - @Tag("div") - public static class ErrorView - extends AbstractErrorView { - - @Override - public int setErrorParameter(BeforeEnterEvent event, - ErrorParameter parameter) { - return 0; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/ServletContainerInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/ServletContainerInitializerTest.java deleted file mode 100644 index 7a5290c6f23..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/ServletContainerInitializerTest.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup; - -import jakarta.servlet.ServletContainerInitializer; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.testutil.ClassFinder; - -/** - * Checks that any class which implements {@link ServletContainerInitializer} - * implements {@link FixedServletContainerInitializer} instead and doesn't - * override - * {@link ServletContainerInitializer#onStartup(java.util.Set, jakarta.servlet.ServletContext)} - */ -public class ServletContainerInitializerTest extends ClassFinder { - - @Test - public void servletContextHasNoLookup_deferredServletContextInitializersAttributeIsSet_processIsNotExecuted() - throws ServletException { - AtomicBoolean processIsExecuted = new AtomicBoolean(); - ClassLoaderAwareServletContainerInitializer initializer = new ClassLoaderAwareServletContainerInitializer() { - - @Override - public void process(Set> set, ServletContext ctx) - throws ServletException { - processIsExecuted.set(true); - } - - }; - ServletContext context = Mockito.mock(ServletContext.class); - initializer.onStartup(Collections.emptySet(), context); - - Mockito.verify(context).setAttribute( - Mockito.eq(DeferredServletContextInitializers.class.getName()), - Mockito.any()); - - Assert.assertFalse(processIsExecuted.get()); - } - - @Test - public void servletContextHasLookup_deferredServletContextInitializersAttributeIsNotSet_processIsExecuted() - throws ServletException { - AtomicBoolean processIsExecuted = new AtomicBoolean(); - ClassLoaderAwareServletContainerInitializer initializer = new ClassLoaderAwareServletContainerInitializer() { - - @Override - public void process(Set> set, ServletContext ctx) - throws ServletException { - processIsExecuted.set(true); - } - - }; - ServletContext context = Mockito.mock(ServletContext.class); - Mockito.when(context.getAttribute(Lookup.class.getName())) - .thenReturn(Mockito.mock(Lookup.class)); - - Mockito.when(context.getClassLoader()) - .thenReturn(initializer.getClass().getClassLoader()); - initializer.onStartup(Collections.emptySet(), context); - - Mockito.verify(context, Mockito.times(0)).setAttribute( - Mockito.eq(DeferredServletContextInitializers.class.getName()), - Mockito.any()); - - Assert.assertTrue(processIsExecuted.get()); - } - - @Test - public void anyServletContainerInitializerSubclassImplementsFixedServletContainerInitializer() - throws IOException { - List rawClasspathEntries = getRawClasspathEntries(); - - List excludes = getExcludedPatterns().map(Pattern::compile) - .collect(Collectors.toList()); - - List classes = new ArrayList<>(); - for (String location : rawClasspathEntries) { - if (!isTestClassPath(location)) { - classes.addAll(findServerClasses(location, excludes)); - } - } - - List brokenInitializers = new ArrayList<>(); - for (String className : classes) { - if (className - .equals(ClassLoaderAwareServletContainerInitializer.class - .getName())) { - continue; - } - try { - Class clazz = Class.forName(className); - // skip annotations and synthetic classes - if (clazz.isAnnotation() || clazz.isSynthetic()) { - continue; - } - - if (ServletContainerInitializer.class.isAssignableFrom(clazz) - && isBadSubType(clazz)) { - brokenInitializers.add(className); - } - } catch (ClassNotFoundException ignore) { - // ignore - } - } - Assert.assertTrue( - brokenInitializers + " classes are subtypes of " - + ServletContainerInitializer.class - + " but either are not subtypes of " - + ClassLoaderAwareServletContainerInitializer.class - + " or override " - + ClassLoaderAwareServletContainerInitializer.class - .getName() - + ".onStartup method", - brokenInitializers.isEmpty()); - - } - - private Stream getExcludedPatterns() { - return Stream.of("com\\.vaadin\\.flow\\..*osgi\\..*", - "com\\.vaadin\\.flow\\.server\\.startup\\.LookupInitializer\\$OsgiLookupImpl"); - } - - private boolean isBadSubType(Class clazz) { - if (!ClassLoaderAwareServletContainerInitializer.class - .isAssignableFrom(clazz)) { - return true; - } - Method onStartUpMethod = Stream - .of(ServletContainerInitializer.class.getDeclaredMethods()) - .filter(method -> !method.isSynthetic()).findFirst().get(); - return Stream.of(clazz.getDeclaredMethods()) - .anyMatch(method -> sameSignature(method, onStartUpMethod)); - } - - private boolean sameSignature(Method method1, Method method2) { - return method1.getName().equals(method2.getName()) - && method1.getReturnType().equals(method2.getReturnType()) - && Arrays.asList(method1.getParameterTypes()) - .equals(Arrays.asList(method2.getParameterTypes())); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/ServletDeployerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/ServletDeployerTest.java deleted file mode 100644 index 69146578224..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/ServletDeployerTest.java +++ /dev/null @@ -1,307 +0,0 @@ -package com.vaadin.flow.server.startup; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jakarta.servlet.Registration; -import jakarta.servlet.Servlet; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletContextEvent; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.di.ResourceProvider; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.server.InitParameters; -import com.vaadin.flow.server.frontend.FallbackChunk; -import com.vaadin.flow.server.frontend.FrontendUtils; - -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; - -public class ServletDeployerTest { - private final ServletDeployer deployer = new ServletDeployer(); - - private List servletNames; - private List servletMappings; - private List servletLoadOnStartup; - - private boolean disableAutomaticServletRegistration = false; - - @Rule - public TemporaryFolder tempFolder = new TemporaryFolder(); - - private static class TestServlet implements Servlet { - @Override - public void init(ServletConfig config) { - } - - @Override - public ServletConfig getServletConfig() { - return null; - } - - @Override - public void service(ServletRequest req, ServletResponse res) { - } - - @Override - public String getServletInfo() { - return null; - } - - @Override - public void destroy() { - } - } - - @Route - private static class ComponentWithRoute extends Component { - } - - @Before - public void clearCaptures() { - servletNames = new ArrayList<>(); - servletMappings = new ArrayList<>(); - servletLoadOnStartup = new ArrayList<>(); - } - - @Test - public void automaticallyRegisterTwoServletsWhenNoServletsPresent() - throws Exception { - deployer.contextInitialized(getContextEvent()); - - assertMappingsCount(1, 1); - assertMappingIsRegistered(ServletDeployer.class.getName(), "/*"); - assertLoadOnStartupSet(); - } - - @Test - public void doNotRegisterAnythingIfRegistrationIsDisabled() - throws Exception { - disableAutomaticServletRegistration = true; - deployer.contextInitialized(getContextEvent( - getServletRegistration("testServlet", TestServlet.class, - singletonList("/test/*"), Collections.emptyMap()))); - - assertMappingsCount(0, 0); - } - - @Test - public void registeredNonVaadinServlets_vaadinServletsAreRegistered() - throws Exception { - deployer.contextInitialized(getContextEvent( - getServletRegistration("testServlet", TestServlet.class, - singletonList("/test/*"), Collections.emptyMap()))); - - assertMappingsCount(1, 1); - assertLoadOnStartupSet(); - } - - @Test - public void frontendServletIsNotRegisteredWhenProductionModeIsActive() - throws Exception { - deployer.contextInitialized(getContextEvent(getServletRegistration( - "testServlet", TestServlet.class, singletonList("/test/*"), - singletonMap(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE, - "true")))); - - assertMappingsCount(1, 1); - assertMappingIsRegistered(ServletDeployer.class.getName(), "/*"); - assertLoadOnStartupSet(); - } - - @Test - public void frontendServletIsNotRegistered_whenMainServletIsRegistered() - throws Exception { - deployer.contextInitialized(getContextEvent()); - - assertMappingsCount(1, 1); - assertMappingIsRegistered(ServletDeployer.class.getName(), "/*"); - assertLoadOnStartupSet(); - } - - @Test - public void servletIsNotRegisteredWhenAnotherHasTheSamePathMapping_mainServlet() - throws Exception { - deployer.contextInitialized(getContextEvent( - getServletRegistration("test", TestServlet.class, - singletonList("/*"), Collections.emptyMap()))); - - assertMappingsCount(0, 0); - } - - @Test - public void servletIsNotRegisteredWhenAnotherHasTheSamePathMapping_frontendServlet() - throws Exception { - deployer.contextInitialized(getContextEvent( - getServletRegistration("test", TestServlet.class, - singletonList("/frontend/*"), Collections.emptyMap()))); - - assertMappingsCount(1, 1); - assertMappingIsRegistered(ServletDeployer.class.getName(), "/*"); - assertLoadOnStartupSet(); - } - - private void assertMappingsCount(int numServlets, int numMappings) { - assertEquals(String.format( - "Expected to have exactly '%d' servlets, but got '%d': '%s'", - numServlets, servletNames.size(), servletNames), - servletNames.size(), numServlets); - assertEquals(String.format( - "Expected to have exactly '%d' mappings, but got '%d': '%s'", - numMappings, servletMappings.size(), servletMappings), - servletMappings.size(), numMappings); - } - - private void assertMappingIsRegistered(String servletName, - String mappedPath) { - int servletNameIndex = servletNames.indexOf(servletName); - int pathIndex = servletMappings.indexOf(mappedPath); - assertTrue(String.format( - "Did not find servlet name '%s' among added servlet names: '%s'", - servletName, servletNames), servletNameIndex >= 0); - assertTrue(String.format( - "Did not find mapped path '%s' among added paths: '%s'", - mappedPath, servletMappings), pathIndex >= 0); - assertEquals( - "Expected servlet name '%s' and mapped path '%s' to be added for the same servlet in the same time", - pathIndex, servletNameIndex); - } - - private void assertLoadOnStartupSet() { - assertEquals("Servlet loadOnStartup should be invoked only once", 1, - servletLoadOnStartup.size()); - assertEquals( - String.format( - "Expected servlet loadOnStartup to be '%d' but was '%d", - 1, servletLoadOnStartup.get(0)), - (Integer) 1, servletLoadOnStartup.get(0)); - } - - private void assertLoadOnStartupNotSet() { - assertTrue("Servlet loadOnStartup should not have been invoked ", - servletLoadOnStartup.isEmpty()); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - private ServletContextEvent getContextEvent( - ServletRegistration... servletRegistrations) throws Exception { - ServletRegistration.Dynamic dynamicMock = Mockito - .mock(ServletRegistration.Dynamic.class); - - Mockito.when(dynamicMock.addMapping(Mockito.anyString())) - .thenAnswer(answer -> { - String mappings = answer.getArgument(0); - this.servletMappings.addAll(Arrays.asList(mappings)); - return Collections.emptySet(); - }); - Mockito.doAnswer(i -> this.servletLoadOnStartup.add(i.getArgument(0))) - .when(dynamicMock).setLoadOnStartup(ArgumentMatchers.anyInt()); - - ServletContext contextMock = Mockito.mock(ServletContext.class); - - Lookup lookup = Mockito.mock(Lookup.class); - Mockito.when(contextMock.getAttribute(Lookup.class.getName())) - .thenReturn(lookup); - - ResourceProvider resourceProvider = Mockito - .mock(ResourceProvider.class); - - Mockito.when(resourceProvider.getApplicationResources(Mockito.any())) - .thenReturn(Collections.emptyList()); - - Mockito.when(lookup.lookup(ResourceProvider.class)) - .thenReturn(resourceProvider); - - ApplicationConfiguration appConfig = Mockito - .mock(ApplicationConfiguration.class); - - Mockito.when(appConfig.getPropertyNames()) - .thenReturn(Collections.emptyEnumeration()); - Mockito.when(appConfig.isProductionMode()).thenReturn(false); - FallbackChunk chunk = Mockito.mock(FallbackChunk.class); - Mockito.when(appConfig.getFallbackChunk()).thenReturn(chunk); - - Mockito.when(appConfig.disableAutomaticServletRegistration()) - .thenReturn(disableAutomaticServletRegistration); - - Mockito.when(contextMock - .getAttribute(ApplicationConfiguration.class.getName())) - .thenReturn(appConfig); - - Mockito.when(contextMock.getContextPath()).thenReturn(""); - Mockito.when(contextMock.getClassLoader()) - .thenReturn(this.getClass().getClassLoader()); - - Mockito.when(contextMock.addServlet(Mockito.anyString(), - Mockito.any(Class.class))).thenAnswer(answer -> { - String servletName = answer.getArgument(0); - servletNames.add(servletName); - return dynamicMock; - }); - - // seems to be a compiler bug, since fails to compile with the - // actual - // types specified (or being inlined) but works with raw type - @SuppressWarnings({ "rawtypes", "serial" }) - Map hack = Stream.of(servletRegistrations).collect( - Collectors.toMap(Registration::getName, Function.identity())); - Mockito.when(contextMock.getServletRegistrations()).thenReturn(hack); - - File token = tempFolder.newFile(); - FileUtils.write(token, "{}", StandardCharsets.UTF_8); - - Mockito.when(contextMock.getInitParameterNames()) - .thenReturn(Collections.enumeration(Collections - .singletonList(FrontendUtils.PARAM_TOKEN_FILE))); - Mockito.when( - contextMock.getInitParameter(FrontendUtils.PARAM_TOKEN_FILE)) - .thenReturn(token.getPath()); - - return new ServletContextEvent(contextMock); - } - - private ServletRegistration getServletRegistration(String servletName, - Class servletClass, Collection pathMappings, - Map initParameters) { - ServletRegistration registrationMock = Mockito - .mock(ServletRegistration.class); - Mockito.when(registrationMock.getClassName()) - .thenReturn(servletClass.getName()); - Mockito.when(registrationMock.getMappings()).thenReturn(pathMappings); - Mockito.when(registrationMock.getName()).thenReturn(servletName); - Mockito.when(registrationMock.getInitParameters()) - .thenReturn(initParameters); - Mockito.when(registrationMock.getInitParameter(Mockito.anyString())) - .thenAnswer(answer -> { - String name = answer.getArgument(0); - return initParameters.get(name); - }); - return registrationMock; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/VaadinAppShellInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/VaadinAppShellInitializerTest.java deleted file mode 100644 index 24c9a14167b..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/VaadinAppShellInitializerTest.java +++ /dev/null @@ -1,547 +0,0 @@ -package com.vaadin.flow.server.startup; - -import net.jcip.annotations.NotThreadSafe; -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletRegistration; -import jakarta.servlet.http.HttpServletRequest; - -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; - -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.slf4j.ILoggerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.simple.SimpleLoggerFactory; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.PushConfiguration; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.page.AppShellConfigurator; -import com.vaadin.flow.component.page.BodySize; -import com.vaadin.flow.component.page.Inline; -import com.vaadin.flow.component.page.Inline.Position; -import com.vaadin.flow.component.page.Inline.Wrapping; -import com.vaadin.flow.component.page.Meta; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.component.page.TargetElement; -import com.vaadin.flow.component.page.Viewport; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.di.Lookup; -import com.vaadin.flow.router.PageTitle; -import com.vaadin.flow.server.AppShellRegistry; -import com.vaadin.flow.server.AppShellSettings; -import com.vaadin.flow.server.Constants; -import com.vaadin.flow.server.InitialPageSettings; -import com.vaadin.flow.server.InvalidApplicationConfigurationException; -import com.vaadin.flow.server.MockServletServiceSessionSetup; -import com.vaadin.flow.server.PWA; -import com.vaadin.flow.server.PageConfigurator; -import com.vaadin.flow.server.VaadinServletContext; -import com.vaadin.flow.server.VaadinServletRequest; -import com.vaadin.flow.shared.communication.PushMode; -import com.vaadin.flow.shared.ui.Transport; -import com.vaadin.flow.theme.AbstractTheme; -import com.vaadin.flow.theme.Theme; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -@NotThreadSafe -public class VaadinAppShellInitializerTest { - - public static class MyAppShellWithoutAnnotations - implements AppShellConfigurator { - } - - @Meta(name = "foo", content = "bar") - @Meta(name = "lorem", content = "ipsum") - @Inline("inline.html") - @Inline(position = Position.PREPEND, value = "inline.css") - @Inline(wrapping = Wrapping.JAVASCRIPT, position = Position.APPEND, target = TargetElement.BODY, value = "inline.js") - @Viewport("my-viewport") - @BodySize(height = "my-height", width = "my-width") - @PageTitle("my-title") - @Push(value = PushMode.MANUAL, transport = Transport.WEBSOCKET) - @Theme(themeClass = AbstractTheme.class) - public static class MyAppShellWithMultipleAnnotations - implements AppShellConfigurator { - } - - @Meta(name = "foo", content = "bar") - @Meta(name = "lorem", content = "ipsum") - @Inline("inline.html") - @Inline(position = Position.PREPEND, value = "inline.css") - @Inline(wrapping = Wrapping.JAVASCRIPT, position = Position.APPEND, target = TargetElement.BODY, value = "inline.js") - @Viewport("my-viewport") - @BodySize(height = "my-height", width = "my-width") - @PageTitle("my-title") - @Push(value = PushMode.MANUAL, transport = Transport.WEBSOCKET) - @Theme(themeClass = AbstractTheme.class) - public static class OffendingClass { - } - - public static class WebHolder extends Component { - } - - @Theme(themeClass = AbstractTheme.class) - @Push(PushMode.AUTOMATIC) - public static class NonOffendingExporter - extends WebComponentExporter { - public NonOffendingExporter() { - super("web-component"); - } - - @Override - public void configureInstance(WebComponent webComponent, - WebHolder component) { - } - } - - public static class MyAppShellWithConfigurator - implements AppShellConfigurator { - @Override - public void configurePage(AppShellSettings settings) { - settings.setViewport("my-viewport"); - settings.setPageTitle("my-title"); - settings.addMetaTag("foo", "bar"); - settings.addMetaTag("lorem", "ipsum"); - settings.addInlineFromFile("inline.html", Wrapping.AUTOMATIC); - settings.addInlineFromFile(Position.PREPEND, "inline.css", - Wrapping.AUTOMATIC); - settings.addInlineFromFile(TargetElement.BODY, Position.APPEND, - "inline.js", Wrapping.JAVASCRIPT); - settings.setBodySize("my-width", "my-height"); - - settings.addFavIcon("icon1", "icon1.png", "1x1"); - settings.addFavIcon("icon2", "icon2.png", "2x2"); - settings.addInlineWithContents(Position.PREPEND, - "window.messages = window.messages || [];\n" - + "window.messages.push(\"content script\");", - Wrapping.JAVASCRIPT); - settings.addInlineFromFile(Position.PREPEND, "inline.js", - Wrapping.JAVASCRIPT); - - settings.addLink("icons/favicon.ico", - new LinkedHashMap() { - { - put("rel", "shortcut icon"); - } - }); - settings.addLink("icons/icon-192.png", - new LinkedHashMap() { - { - put("rel", "icon"); - put("sizes", "192x192"); - } - }); - - settings.addLink("shortcut icon", "icons/favicon.ico"); - - settings.addFavIcon("icon", "icons/icon-192.png", "192x192"); - settings.addFavIcon("icon", "icons/icon-200.png", "2"); - } - } - - public static class OffendingClassWithConfigurator - implements PageConfigurator { - @Override - public void configurePage(InitialPageSettings settings) { - } - } - - @PWA(name = "name", shortName = "n") - @Viewport("my-viewport") - public static class OffendingPwaClass { - } - - @Viewport("my-viewport") - public static class OffendingNonPwaClass { - } - - @PWA(name = "name", shortName = "n") - @Viewport("my-viewport") - @BodySize(height = "my-height", width = "my-width") - public static class AppShellWithPWA implements AppShellConfigurator { - } - - public static class MyAppShellWithLoadingIndicatorConfig - implements AppShellConfigurator { - @Override - public void configurePage(AppShellSettings settings) { - settings.getLoadingIndicatorConfiguration().ifPresent( - indicator -> indicator.setApplyDefaultTheme(false)); - } - } - - public static class MyAppShellWithReconnectionDialogConfig - implements AppShellConfigurator { - @Override - public void configurePage(AppShellSettings settings) { - settings.getReconnectDialogConfiguration() - .ifPresent(dialog -> dialog.setDialogText("custom text")); - } - } - - public static class MyAppShellWithPushConfig - implements AppShellConfigurator { - @Override - public void configurePage(AppShellSettings settings) { - settings.getPushConfiguration() - .ifPresent(push -> push.setPushMode(PushMode.MANUAL)); - } - } - - @Rule - public ExpectedException exception = ExpectedException.none(); - - private VaadinAppShellInitializer initializer; - - private ServletContext servletContext; - private VaadinServletContext context; - private Set> classes; - private Document document; - private Map attributeMap = new HashMap<>(); - private MockServletServiceSessionSetup mocks; - private MockServletServiceSessionSetup.TestVaadinServletService service; - private PushConfiguration pushConfiguration; - private Logger logger; - private ApplicationConfiguration appConfig; - - @Before - public void setup() throws Exception { - logger = mockLog(VaadinAppShellInitializer.class); - - mocks = new MockServletServiceSessionSetup(); - - servletContext = mocks.getServletContext(); - - appConfig = mockApplicationConfiguration(); - - Lookup lookup = (Lookup) servletContext - .getAttribute(Lookup.class.getName()); - - Mockito.when(lookup.lookup(AppShellPredicate.class)) - .thenReturn(AppShellConfigurator.class::isAssignableFrom); - - attributeMap.put(Lookup.class.getName(), - servletContext.getAttribute(Lookup.class.getName())); - attributeMap.put(ApplicationConfiguration.class.getName(), appConfig); - - service = mocks.getService(); - Mockito.when(servletContext.getAttribute(Mockito.anyString())) - .then(invocationOnMock -> attributeMap - .get(invocationOnMock.getArguments()[0].toString())); - Mockito.doAnswer(invocationOnMock -> attributeMap.put( - invocationOnMock.getArguments()[0].toString(), - invocationOnMock.getArguments()[1])).when(servletContext) - .setAttribute(Mockito.anyString(), Mockito.any()); - - ServletRegistration registration = Mockito - .mock(ServletRegistration.class); - context = new VaadinServletContext(servletContext); - - classes = new HashSet<>(); - - Map registry = new HashMap<>(); - registry.put("foo", registration); - Mockito.when(servletContext.getServletRegistrations()) - .thenReturn((Map) registry); - Mockito.when(servletContext.getInitParameterNames()) - .thenReturn(Collections.emptyEnumeration()); - - initializer = new VaadinAppShellInitializer(); - document = Document.createShell(""); - - pushConfiguration = Mockito.mock(PushConfiguration.class); - } - - @After - public void teardown() throws Exception { - AppShellRegistry.getInstance(context).reset(); - clearIlogger(); - mocks.cleanup(); - } - - @Test - public void should_not_modifyDocument_when_noAnnotatedAppShell() - throws Exception { - classes.add(MyAppShellWithoutAnnotations.class); - initializer.process(classes, servletContext); - AppShellRegistry.getInstance(context).modifyIndexHtml(document, - createVaadinRequest("/")); - assertEquals(0, document.head().children().size()); - assertEquals(0, document.body().children().size()); - } - - @Test - public void should_not_modifyPushConfiguration_when_noAnnotatedAppShell() - throws Exception { - classes.add(MyAppShellWithoutAnnotations.class); - initializer.process(classes, servletContext); - - AppShellRegistry.getInstance(context) - .modifyPushConfiguration(pushConfiguration); - - initializer.process(Collections.emptySet(), servletContext); - } - - @Test - public void should_not_throw_when_noClassesFound_null() throws Exception { - initializer.process(null, servletContext); - } - - @Test - public void should_haveMetasAndBodySize_when_annotatedAppShell() - throws Exception { - classes.add(MyAppShellWithMultipleAnnotations.class); - - initializer.process(classes, servletContext); - - AppShellRegistry.getInstance(context).modifyIndexHtml(document, - createVaadinRequest("/")); - - List elements = document.head().children(); - assertEquals(7, elements.size()); - assertEquals("text/css", elements.get(5).attr("type")); - assertEquals("body,#outlet{width:my-width;height:my-height;}", - elements.get(5).childNode(0).toString()); - } - - @Test - public void should_haveInline_when_annotatedAppShell() throws Exception { - classes.add(MyAppShellWithMultipleAnnotations.class); - - initializer.process(classes, servletContext); - - AppShellRegistry.getInstance(context).modifyIndexHtml(document, - createVaadinRequest("/")); - - List headElements = document.head().children(); - assertEquals(7, headElements.size()); - assertEquals("text/css", headElements.get(0).attr("type")); - assertEquals("style", headElements.get(0).tagName()); - assertTrue(headElements.get(0).outerHtml().contains("#preloadedDiv")); - assertEquals("foo", headElements.get(1).attr("name")); - assertEquals("lorem", headElements.get(2).attr("name")); - assertEquals("viewport", headElements.get(3).attr("name")); - assertEquals("title", headElements.get(4).tagName()); - assertEquals("my-title", headElements.get(4).childNode(0).toString()); - - assertEquals("text/css", headElements.get(5).attr("type")); - assertEquals("style", headElements.get(5).tagName()); - assertTrue(headElements.get(5).outerHtml().contains("width:my-width")); - assertTrue( - headElements.get(5).outerHtml().contains("height:my-height")); - - assertEquals("text/javascript", headElements.get(6).attr("type")); - assertEquals("script", headElements.get(6).tagName()); - assertTrue(headElements.get(6).outerHtml() - .contains("might not yet be accessible")); - - List bodyElements = document.body().children(); - assertEquals(1, bodyElements.size()); - assertEquals("text/javascript", bodyElements.get(0).attr("type")); - assertEquals("script", bodyElements.get(0).tagName()); - assertTrue(bodyElements.get(0).outerHtml() - .contains("window.messages.push")); - } - - @Test - public void should_modifyPushConfiguration_when_annotatedAppShell() - throws Exception { - classes.add(MyAppShellWithMultipleAnnotations.class); - initializer.process(classes, servletContext); - - AppShellRegistry.getInstance(context) - .modifyPushConfiguration(pushConfiguration); - - Mockito.verify(pushConfiguration).setPushMode(PushMode.MANUAL); - Mockito.verify(pushConfiguration).setTransport(Transport.WEBSOCKET); - } - - @Test - public void should_not_haveMetas_when_not_callingInitializer() - throws Exception { - AppShellRegistry.getInstance(context).modifyIndexHtml(document, - createVaadinRequest("/")); - List elements = document.head().children(); - assertEquals(0, elements.size()); - } - - @Test - public void should_not_modifyPushConfiguration_when_not_callingInitializer() - throws Exception { - AppShellRegistry.getInstance(context) - .modifyPushConfiguration(pushConfiguration); - - Mockito.verify(pushConfiguration, Mockito.never()) - .setPushMode(Mockito.any(PushMode.class)); - } - - @Test - public void should_reuseContextAppShell_when_creatingNewInstance() - throws Exception { - AppShellRegistry registry = AppShellRegistry.getInstance(context); - - Assert.assertSame(registry, AppShellRegistry.getInstance(context)); - } - - @Test - public void should_throw_when_offendingClass() throws Exception { - exception.expect(InvalidApplicationConfigurationException.class); - exception.expectMessage(containsString( - "Found app shell configuration annotations in non")); - exception.expectMessage(containsString( - "- @Meta, @Inline, @Viewport, @BodySize, @Push, @Theme" - + " from")); - classes.add(MyAppShellWithoutAnnotations.class); - classes.add(OffendingClass.class); - initializer.process(classes, servletContext); - } - - @Test - public void offendingEmbeddedThemeClass_shouldNotThrow() throws Exception { - classes.add(NonOffendingExporter.class); - initializer.process(classes, servletContext); - } - - @Test - public void should_throw_when_multipleAppShell() throws Exception { - exception.expect(InvalidApplicationConfigurationException.class); - exception.expectMessage(containsString( - "Multiple classes implementing `AppShellConfigurator` were found")); - - classes.add(MyAppShellWithoutAnnotations.class); - classes.add(MyAppShellWithMultipleAnnotations.class); - initializer.process(classes, servletContext); - } - - @Test - public void should_throw_when_offendingClassWithConfigurator() - throws Exception { - exception.expect(InvalidApplicationConfigurationException.class); - exception.expectMessage(containsString( - "The `PageConfigurator` interface is deprecated since Vaadin 15 and has no effect.")); - exception.expectMessage( - containsString(MyAppShellWithoutAnnotations.class.getName())); - exception.expectMessage(containsString( - "- " + OffendingClassWithConfigurator.class.getName())); - classes.add(MyAppShellWithoutAnnotations.class); - classes.add(OffendingClassWithConfigurator.class); - initializer.process(classes, servletContext); - } - - @Test - public void should_not_throw_when_classWithPageConfigurator() - throws Exception { - classes.add(OffendingClassWithConfigurator.class); - initializer.process(classes, servletContext); - } - - @Test - public void should_not_throw_when_appShellAnnotationsAreAllowed_and_offendingClass() - throws Exception { - Mockito.when(appConfig.getBooleanProperty( - Constants.ALLOW_APPSHELL_ANNOTATIONS, false)).thenReturn(true); - classes.add(OffendingClass.class); - initializer.process(classes, servletContext); - - AppShellRegistry.getInstance(context).modifyIndexHtml(document, - createVaadinRequest("/")); - - List elements = document.head().children(); - assertEquals(0, elements.size()); - } - - @Test - public void should_link_to_PWA_article() throws Exception { - Mockito.when(appConfig.getBooleanProperty( - Constants.ALLOW_APPSHELL_ANNOTATIONS, false)).thenReturn(true); - ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); - classes.add(OffendingPwaClass.class); - initializer.process(classes, servletContext); - Mockito.verify(logger, Mockito.times(1)).error(arg.capture()); - assertTrue(arg.getValue() - .contains("We changed the way you configure PWAs")); - } - - @Test - public void should_not_link_to_PWA_article() throws Exception { - Mockito.when(appConfig.getBooleanProperty( - Constants.ALLOW_APPSHELL_ANNOTATIONS, false)).thenReturn(true); - ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); - classes.add(OffendingNonPwaClass.class); - initializer.process(classes, servletContext); - Mockito.verify(logger, Mockito.times(1)).error(arg.capture()); - assertFalse(arg.getValue() - .contains("We changed the way you configure PWAs")); - assertTrue(arg.getValue().contains("@Viewport")); - } - - private VaadinServletRequest createVaadinRequest(String pathInfo) { - HttpServletRequest request = createRequest(pathInfo); - return new VaadinServletRequest(request, service); - } - - private HttpServletRequest createRequest(String pathInfo) { - HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Mockito.when(request.getServletPath()).thenReturn(""); - Mockito.when(request.getPathInfo()).thenReturn(pathInfo); - Mockito.when(request.getRequestURL()) - .thenReturn(new StringBuffer(pathInfo)); - return request; - } - - private Logger mockLog(Class clz) throws Exception { - // wrap logger for clz in an spy - Logger spy = Mockito.spy(LoggerFactory.getLogger(clz.getName())); - ConcurrentMap ilogger = clearIlogger(); - // replace original logger with the spy - ilogger.put(clz.getName(), spy); - return spy; - } - - private ConcurrentMap clearIlogger() throws Exception { - ILoggerFactory ilogger = LoggerFactory.getILoggerFactory(); - Field field = SimpleLoggerFactory.class.getDeclaredField("loggerMap"); - field.setAccessible(true); - ConcurrentMap map = (ConcurrentMap) field - .get(ilogger); - map.clear(); - return map; - } - - private ApplicationConfiguration mockApplicationConfiguration() { - ApplicationConfiguration config = Mockito - .mock(ApplicationConfiguration.class); - Mockito.when(config.isProductionMode()).thenReturn(false); - Mockito.when(config.enableDevServer()).thenReturn(true); - - Mockito.when(config.getStringProperty(Mockito.anyString(), - Mockito.anyString())) - .thenAnswer(invocation -> invocation.getArgument(1)); - Mockito.when(config.getBooleanProperty(Mockito.anyString(), - Mockito.anyBoolean())) - .thenAnswer(invocation -> invocation.getArgument(1)); - return config; - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/WebComponentConfigurationRegistryInitializerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/WebComponentConfigurationRegistryInitializerTest.java deleted file mode 100644 index 4088eceb774..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/WebComponentConfigurationRegistryInitializerTest.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.startup; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.jcip.annotations.NotThreadSafe; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.WebComponentExporterFactory; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.component.webcomponent.WebComponentConfiguration; -import com.vaadin.flow.internal.CurrentInstance; -import com.vaadin.flow.server.InvalidCustomElementNameException; -import com.vaadin.flow.server.MockInstantiator; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.webcomponent.WebComponentConfigurationRegistry; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -@NotThreadSafe -public class WebComponentConfigurationRegistryInitializerTest { - private static final String DUPLICATE_PROPERTY_NAME = "one"; - - private WebComponentConfigurationRegistryInitializer initializer; - @Mock - private WebComponentConfigurationRegistry registry; - @Mock - private ServletContext servletContext; - @Mock - private VaadinService vaadinService; - @Mock - private VaadinContext context; - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - Mockito.when(vaadinService.getContext()).thenReturn(context); - Mockito.when( - context.getAttribute(WebComponentConfigurationRegistry.class)) - .thenReturn(registry); - Mockito.when(context.getAttribute( - eq(WebComponentConfigurationRegistry.class), any())) - .thenReturn(registry); - - initializer = new WebComponentConfigurationRegistryInitializer(); - when(servletContext.getAttribute( - WebComponentConfigurationRegistry.class.getName())) - .thenReturn(registry); - - VaadinService.setCurrent(vaadinService); - when(vaadinService.getInstantiator()) - .thenReturn(new MockInstantiator()); - } - - @After - public void cleanUp() { - CurrentInstance.clearAll(); - } - - @Test - public void process() throws ServletException { - initializer.process( - Stream.of(MyComponentExporter.class, UserBoxExporter.class, - ExporterFactory.class).collect(Collectors.toSet()), - servletContext); - ArgumentCaptor captor = ArgumentCaptor.forClass(Set.class); - Mockito.verify(registry).setConfigurations(captor.capture()); - Set set = captor.getValue(); - Assert.assertEquals(3, set.size()); - Set componentClasses = set.stream() - .map(WebComponentConfiguration.class::cast) - .map(WebComponentConfiguration::getComponentClass) - .collect(Collectors.toSet()); - Assert.assertTrue(componentClasses.contains(MyComponent.class)); - Assert.assertTrue(componentClasses.contains(UserBox.class)); - Assert.assertTrue(componentClasses.contains(InvalidName.class)); - } - - @Test - public void process_noExceptionWithNullArguments() { - try { - initializer.process(null, servletContext); - } catch (Exception e) { - Assert.fail( - "WebComponentRegistryInitializer.process should not throw with null argument"); - } - // Expect a call to setWebComponents even if we have an empty or null - // set - Mockito.verify(registry).setConfigurations(Collections.emptySet()); - } - - @Test - public void process_noExceptionForMultipleCorrectExportsOfTheSameComponent() { - try { - initializer.process( - Stream.of(MyComponentExporter.class, SiblingExporter.class) - .collect(Collectors.toSet()), - servletContext); - } catch (Exception e) { - Assert.fail("WebComponentRegistryInitializer.process should not " - + "throw with 'sibling' exporters"); - } - } - - @Test - public void emptySet_noExceptionAndWebComponentsSet() { - try { - initializer.process(Collections.emptySet(), servletContext); - } catch (Exception e) { - Assert.fail( - "WebComponentRegistryInitializer.process should not throw with empty set"); - } - Mockito.verify(registry).setConfigurations(Collections.emptySet()); - } - - @Test - public void duplicateNamesFoundprocess_exceptionIsThrown() - throws ServletException { - expectedEx.expect(ServletException.class); - expectedEx.expectCause(CauseMatcher.ex(IllegalArgumentException.class) - .msgStartsWith("Found two WebComponentExporter classes")); - initializer.process( - Stream.of(MyComponentExporter.class, DuplicateTagExporter.class) - .collect(Collectors.toSet()), - servletContext); - } - - @Test - public void invalidCustomElementName_initializerThrowsException() - throws ServletException { - expectedEx.expect(ServletException.class); - expectedEx.expectCause(CauseMatcher - .ex(InvalidCustomElementNameException.class) - .msgEquals(String.format( - "Tag name '%s' given by '%s' is not a valid custom element " - + "name.", - "invalid", - InvalidNameExporter.class.getCanonicalName()))); - - initializer.process(Collections.singleton(InvalidNameExporter.class), - servletContext); - } - - @Test - public void duplicatePropertyRegistration_doesNotCauseIssues() - throws ServletException { - initializer.process( - Collections.singleton(DuplicatePropertyExporter.class), - servletContext); - } - - @Test - public void duplicatePropertyRegistrationBetweenParentAndChild_doesNotCauseIssues() - throws ServletException { - initializer.process(Collections.singleton(ExtendingExporter.class), - servletContext); - } - - private static class MyComponent extends Component { - } - - private static class UserBox extends Component { - } - - private static class InvalidName extends Component { - } - - public static class MyComponentExporter - extends WebComponentExporter { - - public MyComponentExporter() { - this("my-component"); - } - - protected MyComponentExporter(String tag) { - super(tag); - addProperty(DUPLICATE_PROPERTY_NAME, "component"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class ExporterFactory - implements WebComponentExporterFactory { - - @Override - public WebComponentExporter create() { - return new PrivateExporter("foo-bar"); - } - - } - - private static class PrivateExporter - extends WebComponentExporter { - - private PrivateExporter(String tag) { - super(tag); - } - - @Override - protected void configureInstance(WebComponent webComponent, - InvalidName component) { - } - - } - - public static class UserBoxExporter extends WebComponentExporter { - - public UserBoxExporter() { - super("user-box"); - addProperty("user", "box"); - } - - @Override - public void configureInstance(WebComponent webComponent, - UserBox component) { - - } - } - - public static class InvalidNameExporter - extends WebComponentExporter { - - public InvalidNameExporter() { - super("invalid"); - } - - @Override - public void configureInstance(WebComponent webComponent, - InvalidName component) { - - } - } - - public static class ExtendingExporter extends MyComponentExporter { - - public ExtendingExporter() { - super("tag-1"); - addProperty(DUPLICATE_PROPERTY_NAME, "something"); - } - } - - public static class SiblingExporter - extends WebComponentExporter { - - public SiblingExporter() { - super("my-component-sibling"); - addProperty("name", "something"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class DuplicateTagExporter - extends WebComponentExporter { - - public DuplicateTagExporter() { - super("my-component"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class DuplicatePropertyExporter - extends WebComponentExporter { - - public DuplicatePropertyExporter() { - super("tag-2"); - addProperty(DUPLICATE_PROPERTY_NAME, "two"); - addProperty(DUPLICATE_PROPERTY_NAME, "four"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - public static class CauseMatcher extends BaseMatcher { - private final Class throwableType; - private boolean startsWith = false; - private String matchable = null; - - private CauseMatcher(Class throwableType) { - this.throwableType = throwableType; - } - - @Override - public boolean matches(Object o) { - Throwable throwable = ((Throwable) o).getCause(); - - if (!throwableType.equals(throwable.getClass())) { - return false; - } - - if (matchable != null) { - if (startsWith) { - return throwable.getMessage().startsWith(matchable); - } else { - return throwable.getMessage().equals(matchable); - } - } - return true; - } - - @Override - public void describeTo(Description description) { - description.appendText(String.format("<%s: %s%s>", - throwableType.getCanonicalName(), matchable, - (startsWith ? "..." : ""))); - } - - public static CauseMatcher ex( - Class throwableType) { - return new CauseMatcher(throwableType); - } - - public CauseMatcher msgStartsWith(String str) { - startsWith = true; - matchable = str; - return this; - } - - public CauseMatcher msgEquals(String str) { - startsWith = false; - matchable = str; - return this; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/WebComponentExporterAwareValidatorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/WebComponentExporterAwareValidatorTest.java deleted file mode 100644 index 4f1495d4bac..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/WebComponentExporterAwareValidatorTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.vaadin.flow.server.startup; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.ServletException; - -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.page.Push; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.router.Route; -import com.vaadin.flow.router.RouterLayout; -import com.vaadin.flow.server.InvalidApplicationConfigurationException; - -public class WebComponentExporterAwareValidatorTest { - - private static final String ERROR_HINT = "Move it to a single route/a top router layout/web component of the application"; - - @Rule - public ExpectedException expectedEx = ExpectedException.none(); - - private WebComponentExporterAwareValidator annotationValidator; - private ServletContext servletContext; - - @Before - public void init() { - annotationValidator = new WebComponentExporterAwareValidator(); - servletContext = Mockito.mock(ServletContext.class); - } - - @Tag(Tag.DIV) - public static class Parent extends Component implements RouterLayout { - } - - @Route(value = "", layout = Parent.class) - @Tag(Tag.DIV) - @Push - public static class ThemeViewportWithParent extends Component { - } - - @Tag(Tag.DIV) - @Push - public static class NonRoutePush extends Component { - } - - @Tag(Tag.DIV) - @Push - public static class WCExporter extends WebComponentExporter { - - public WCExporter() { - super(Tag.DIV); - } - - @Override - public void configureInstance(WebComponent webComponent, - Component component) { - - } - } - - @Tag(Tag.DIV) - public static abstract class AbstractMain extends Component { - } - - @Test - public void process_no_exception_is_thrown_for_correctly_setup_classes() - throws ServletException { - annotationValidator - .process(Stream.of(AbstractMain.class, WCExporter.class) - .collect(Collectors.toSet()), servletContext); - } - - @Test - public void process_all_failing_anotations_are_reported() - throws ServletException { - try { - annotationValidator.process( - Collections.singleton(ThemeViewportWithParent.class), - servletContext); - Assert.fail("No exception was thrown for faulty setup."); - } catch (InvalidApplicationConfigurationException iace) { - String errorMessage = iace.getMessage(); - assertHint(errorMessage, Push.class); - } - } - - @Test - public void process_non_linked_push_throws() throws ServletException { - assertNon_linked_theme_throws(NonRoutePush.class, Push.class); - } - - private void assertNon_linked_theme_throws(Class clazz, - Class annotationType) - throws ServletException { - expectedEx.expect(InvalidApplicationConfigurationException.class); - expectedEx.expectMessage(ERROR_HINT); - expectedEx.expectMessage(String.format( - "Class '%s' contains '%s', but it is not a router " - + "layout/top level route/web component.", - clazz.getName(), "@" + annotationType.getSimpleName())); - - annotationValidator.process( - Stream.of(clazz).collect(Collectors.toSet()), servletContext); - } - - private void assertHint(String msg, - Class anntationType) { - MatcherAssert.assertThat("Exception has hint.", msg, - CoreMatchers.allOf( - CoreMatchers - .containsString(anntationType.getSimpleName()), - CoreMatchers.containsString(ERROR_HINT))); - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/AnotherTestInstantiatorFactory.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/AnotherTestInstantiatorFactory.java deleted file mode 100644 index b09a20d5ae3..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/AnotherTestInstantiatorFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup.testdata; - -import java.util.stream.Stream; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.di.InstantiatorFactory; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServiceInitListener; - -public class AnotherTestInstantiatorFactory implements InstantiatorFactory { - - public static class TestInstantiator implements Instantiator { - - @Override - public boolean init(VaadinService service) { - return false; - } - - @Override - public Stream getServiceInitListeners() { - return null; - } - - @Override - public T getOrCreate(Class type) { - return null; - } - - @Override - public T createComponent( - Class componentClass) { - return null; - } - - } - - @Override - public Instantiator createInstantitor(VaadinService service) { - return null; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/OneMoreTestInstantiatorFactory.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/OneMoreTestInstantiatorFactory.java deleted file mode 100644 index a890f620a53..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/OneMoreTestInstantiatorFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup.testdata; - -import java.util.stream.Stream; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.di.InstantiatorFactory; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServiceInitListener; - -public class OneMoreTestInstantiatorFactory implements InstantiatorFactory { - - public static class TestInstantiator implements Instantiator { - - @Override - public boolean init(VaadinService service) { - return false; - } - - @Override - public Stream getServiceInitListeners() { - return null; - } - - @Override - public T getOrCreate(Class type) { - return null; - } - - @Override - public T createComponent( - Class componentClass) { - return null; - } - - } - - @Override - public Instantiator createInstantitor(VaadinService service) { - return null; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/TestInstantiatorFactory.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/TestInstantiatorFactory.java deleted file mode 100644 index 5f211f9821c..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/TestInstantiatorFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup.testdata; - -import java.util.stream.Stream; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.di.Instantiator; -import com.vaadin.flow.di.InstantiatorFactory; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.server.VaadinServiceInitListener; - -public class TestInstantiatorFactory implements InstantiatorFactory { - - public static class TestInstantiator implements Instantiator { - - @Override - public boolean init(VaadinService service) { - return false; - } - - @Override - public Stream getServiceInitListeners() { - return null; - } - - @Override - public T getOrCreate(Class type) { - return null; - } - - @Override - public T createComponent( - Class componentClass) { - return null; - } - - } - - @Override - public Instantiator createInstantitor(VaadinService service) { - return null; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/TestResourceProvider.java b/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/TestResourceProvider.java deleted file mode 100644 index 6a600118050..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/startup/testdata/TestResourceProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.startup.testdata; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.List; - -import com.vaadin.flow.di.ResourceProvider; - -public class TestResourceProvider implements ResourceProvider { - - @Override - public URL getApplicationResource(String path) { - return null; - } - - @Override - public List getApplicationResources(String path) throws IOException { - return null; - } - - @Override - public URL getClientResource(String path) { - return null; - } - - @Override - public InputStream getClientResourceAsStream(String path) - throws IOException { - return null; - } - -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/PropertyConfigurationImplTest.java b/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/PropertyConfigurationImplTest.java deleted file mode 100644 index ee3cacd1200..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/PropertyConfigurationImplTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.webcomponent; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; - -public class PropertyConfigurationImplTest { - - PropertyConfigurationImpl intPropertyConf; - - @Before - public void init() { - intPropertyConf = new PropertyConfigurationImpl<>(MyComponent.class, - "int", Integer.class, 1); - } - - @Test - public void onChange() { - intPropertyConf.onChange(MyComponent::setInt); - - MyComponent myComponent = new MyComponent(); - - intPropertyConf.getOnChangeHandler().accept(myComponent, 5); - - Assert.assertEquals( - "onChangeHandler should have been set and value " + "updated", - 5, myComponent.value); - } - - @Test(expected = IllegalStateException.class) - public void onChange_throwsIfCalledTwice() { - intPropertyConf.onChange(MyComponent::setInt); - intPropertyConf.onChange(MyComponent::setInt); - } - - @Test - public void readOnly() { - intPropertyConf.readOnly(); - - PropertyData data = intPropertyConf.getPropertyData(); - - // verify default value for completeness - Assert.assertEquals("default value is 1", 1, - (int) data.getDefaultValue()); - - Assert.assertTrue("read-only flag should have been set to true", - data.isReadOnly()); - } - - @Tag("for-reasons") - private static final class MyComponent extends Component { - private int value; - - public void setInt(int newValue) { - this.value = newValue; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentBindingTest.java b/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentBindingTest.java deleted file mode 100644 index 141ed6420d9..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentBindingTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.webcomponent; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.Tag; - -import elemental.json.Json; -import elemental.json.JsonObject; -import elemental.json.JsonValue; - -public class WebComponentBindingTest { - - private MyComponent component; - private WebComponentBinding binding; - - @Before - public void setUp() { - component = new MyComponent(); - binding = new WebComponentBinding<>(component); - PropertyConfigurationImpl integerProperty = new PropertyConfigurationImpl<>( - MyComponent.class, "int", Integer.class, 0); - integerProperty.onChange(MyComponent::setInt); - PropertyConfigurationImpl jsonProperty = new PropertyConfigurationImpl<>( - MyComponent.class, "json", JsonValue.class, null); - jsonProperty.onChange(MyComponent::setJson); - binding.bindProperty(integerProperty, false, null); - binding.bindProperty(jsonProperty, false, null); - } - - @Test - public void getComponent() { - Assert.assertEquals(component, binding.getComponent()); - } - - @Test - public void getPropertyType() { - Assert.assertEquals(Integer.class, binding.getPropertyType("int")); - Assert.assertEquals(JsonValue.class, binding.getPropertyType("json")); - - Assert.assertNull(binding.getPropertyType("not-a-property")); - } - - @Test - public void hasProperty() { - Assert.assertTrue(binding.hasProperty("int")); - Assert.assertTrue(binding.hasProperty("json")); - - Assert.assertFalse(binding.hasProperty("not-a-property")); - } - - @Test - public void updateValue() { - binding.updateProperty("int", 5); - Assert.assertEquals(5, component.integer); - - JsonObject obj = Json.createObject(); - obj.put("String", "Value"); - - binding.updateProperty("json", obj); - Assert.assertEquals("{\"String\":\"Value\"}", - component.jsonValue.toJson()); - } - - @Tag("tag") - private static class MyComponent extends Component { - int integer; - JsonValue jsonValue; - - public void setInt(int v) { - integer = v; - } - - public void setJson(JsonValue v) { - jsonValue = v; - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentConfigurationRegistryTest.java b/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentConfigurationRegistryTest.java deleted file mode 100644 index 8bd501b28df..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentConfigurationRegistryTest.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.webcomponent; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import net.jcip.annotations.NotThreadSafe; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.WebComponentExporterFactory.DefaultWebComponentExporterFactory; -import com.vaadin.flow.component.webcomponent.WebComponent; -import com.vaadin.flow.component.webcomponent.WebComponentConfiguration; -import com.vaadin.flow.server.VaadinContext; -import com.vaadin.flow.server.VaadinService; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; - -@NotThreadSafe -public class WebComponentConfigurationRegistryTest { - - private static final String MY_COMPONENT_TAG = "my-component"; - private static final String USER_BOX_TAG = "user-box"; - - protected WebComponentConfigurationRegistry registry; - - protected VaadinContext context; - - protected WebComponentConfigurationRegistry createRegistry() { - return new WebComponentConfigurationRegistry() { - }; - } - - @Before - public void init() { - VaadinService service = mock(VaadinService.class); - context = mock(VaadinContext.class); - VaadinService.setCurrent(service); - Mockito.when(service.getContext()).thenReturn(context); - WebComponentConfigurationRegistry instance = createRegistry(); - Mockito.when( - context.getAttribute(WebComponentConfigurationRegistry.class)) - .thenReturn(instance); - Mockito.when(context.getAttribute( - eq(WebComponentConfigurationRegistry.class), any())) - .thenReturn(instance); - registry = WebComponentConfigurationRegistry.getInstance(context); - } - - @Test - public void assertWebComponentRegistry() { - Assert.assertNotNull(registry); - } - - @Test - public void assertRegistryIsSingleton() { - Assert.assertSame( - "WebComponentConfigurationRegistry instance should be singleton", - registry, - WebComponentConfigurationRegistry.getInstance(context)); - } - - @Test - public void setConfigurations_allCanBeFoundInRegistry() { - Assert.assertTrue("Registry should have accepted the webComponents", - registry.setConfigurations(createConfigurations( - MyComponentExporter.class, UserBoxExporter.class))); - - Assert.assertEquals("Expected two targets to be registered", 2, - registry.getConfigurations().size()); - - Assert.assertEquals( - "Tag 'my-component' should have returned " - + "'WebComponentBuilder' matching MyComponent", - MyComponent.class, registry.getConfiguration(MY_COMPONENT_TAG) - .get().getComponentClass()); - Assert.assertEquals( - "Tag 'user-box' should have returned 'WebComponentBuilder' " - + "matching UserBox", - UserBox.class, registry.getConfiguration(USER_BOX_TAG).get() - .getComponentClass()); - } - - @Test - public void setConfigurations_getConfigurationsCallDoesNotChangeSetProtection() { - registry.setConfigurations( - createConfigurations(MyComponentExporter.class)); - - WebComponentConfiguration conf1 = registry - .getConfiguration("my-component").get(); - - Assert.assertNotNull(conf1); - - Assert.assertFalse(registry.setConfigurations( - createConfigurations(UserBoxExporter.class))); - - WebComponentConfiguration conf2 = registry - .getConfiguration("my-component").get(); - - Assert.assertEquals(conf1, conf2); - } - - @Test - public void getWebComponentConfigurationsForComponent() { - registry.setConfigurations( - createConfigurations(MyComponentExporter.class, - MyComponentExporter2.class, UserBoxExporter.class)); - - Set> set = registry - .getConfigurationsByComponentType(MyComponent.class); - - Assert.assertEquals("Set should contain two configurations", 2, - set.size()); - - Assert.assertTrue( - "Both configurations should have component class " - + "MyComponent.class", - set.stream().map(WebComponentConfiguration::getComponentClass) - .allMatch(clazz -> clazz.equals(MyComponent.class))); - } - - @Test - public void setConfigurationsTwice_onlyFirstSetIsAccepted() { - Set> configs1st = createConfigurations( - MyComponentExporter.class); - - Set> configs2nd = createConfigurations( - UserBoxExporter.class); - - Assert.assertTrue("Registry should have accepted the configurations", - registry.setConfigurations(configs1st)); - - Assert.assertFalse( - "Registry should not accept a second set of configurations.", - registry.setConfigurations(configs2nd)); - - Assert.assertEquals( - "Builders from the first Set should have been added", - MyComponent.class, - registry.getConfiguration("my" + "-component").get() - .getComponentClass()); - - Assert.assertFalse( - "Components from the second Set should not have been added", - registry.getConfiguration("user-box").isPresent()); - } - - @Test - public void getConfigurations_uninitializedReturnsEmptySet() { - WebComponentConfigurationRegistry uninitializedRegistry = new WebComponentConfigurationRegistry(); - - Set set = uninitializedRegistry.getConfigurations(); - - Assert.assertEquals("Configuration set should be empty", 0, set.size()); - } - - @Test - public void hasConfigurations() { - registry.setConfigurations( - createConfigurations(MyComponentExporter.class, - MyComponentExporter2.class, UserBoxExporter.class)); - - Assert.assertTrue("Should have configurations, when 3 were set", - registry.hasConfigurations()); - } - - @Test - public void hasConfigurations_noConfigurations() { - Assert.assertFalse("New registry should have no configurations", - registry.hasConfigurations()); - - registry.setConfigurations(Collections.emptySet()); - - Assert.assertFalse( - "Should not have configurations, when empty set is" + " given", - registry.hasConfigurations()); - } - - @Test - public void setSameRouteValueFromDifferentThreads_ConcurrencyTest() - throws InterruptedException, ExecutionException { - final int THREADS = 10; - - ExecutorService executorService = Executors.newFixedThreadPool(THREADS); - - List> callables = IntStream.range(0, THREADS) - .mapToObj(i -> { - Callable callable = () -> { - // Add random sleep for better possibility to run at - // same time - Thread.sleep(new Random().nextInt(200)); - return new AtomicBoolean( - registry.setConfigurations(createConfigurations( - MyComponentExporter.class))); - }; - return callable; - }).collect(Collectors.toList()); - - List> futures = executorService - .invokeAll(callables); - - executorService.shutdown(); - - Assert.assertEquals("Expected a result for all threads", THREADS, - futures.size()); - - List results = new ArrayList<>(); - for (Future resultFuture : futures) { - results.add(resultFuture.get()); - } - - Assert.assertEquals("Expected all except one thread to return false", - THREADS - 1, - results.stream().filter(result -> !result.get()).count()); - - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected Set> createConfigurations( - Class>... exporters) { - WebComponentExporter.WebComponentConfigurationFactory factory = new WebComponentExporter.WebComponentConfigurationFactory(); - - Set> configurations = new HashSet<>(); - for (Class> exporter : exporters) - configurations.add(factory.create( - new DefaultWebComponentExporterFactory(exporter).create())); - return configurations; - } - - protected class MyComponent extends Component { - } - - protected class UserBox extends Component { - } - - protected static class MyComponentExporter - extends WebComponentExporter { - public MyComponentExporter() { - super("my-component"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - protected static class MyComponentExporter2 - extends WebComponentExporter { - - public MyComponentExporter2() { - super("my-component-2"); - } - - @Override - public void configureInstance(WebComponent webComponent, - MyComponent component) { - - } - } - - protected static class UserBoxExporter - extends WebComponentExporter { - - public UserBoxExporter() { - super("user-box"); - } - - @Override - public void configureInstance(WebComponent webComponent, - UserBox component) { - - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentExporterUtilsTest.java b/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentExporterUtilsTest.java deleted file mode 100644 index b2a36dc0ed4..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentExporterUtilsTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.flow.server.webcomponent; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import org.hamcrest.CoreMatchers; -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.WebComponentExporterFactory; -import com.vaadin.flow.component.WebComponentExporterFactory.DefaultWebComponentExporterFactory; -import com.vaadin.flow.component.webcomponent.WebComponent; - -@SuppressWarnings("rawtypes") -public class WebComponentExporterUtilsTest { - - @Test - public void getFactories_notEligibleExportersAreFiltered_factoriesAreReturned() { - - Set factories = WebComponentExporterUtils - .getFactories(new HashSet<>(Arrays.asList(GoodExporter.class, - AbstractExporter.class, PackageLocalExporter.class, - NoPublicCtorExporter.class, ExporterFactory.class))); - Assert.assertEquals(2, factories.size()); - - Iterator iterator = factories.iterator(); - WebComponentExporterFactory factory = iterator.next(); - WebComponentExporterFactory another = iterator.next(); - if (factory instanceof ExporterFactory) { - assertFactories(factory, another); - } else { - assertFactories(another, factory); - } - } - - private void assertFactories(WebComponentExporterFactory factory, - WebComponentExporterFactory anotherFactory) { - Assert.assertTrue( - anotherFactory instanceof DefaultWebComponentExporterFactory); - WebComponentExporter exporter = anotherFactory.create(); - MatcherAssert.assertThat(exporter, - CoreMatchers.instanceOf(GoodExporter.class)); - - exporter = factory.create(); - MatcherAssert.assertThat(exporter, - CoreMatchers.instanceOf(NoDefaultCtorExporter.class)); - } - - public static class GoodExporter extends WebComponentExporter { - - public GoodExporter() { - super("a-b"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - - } - - } - - public static abstract class AbstractExporter - extends WebComponentExporter { - - public AbstractExporter() { - super("a-b"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - - } - - } - - static abstract class PackageLocalExporter - extends WebComponentExporter { - - public PackageLocalExporter() { - super("a-b"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - - } - - } - - public static class NoPublicCtorExporter - extends WebComponentExporter { - - NoPublicCtorExporter() { - super("a-b"); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - - } - - } - - public static class NoDefaultCtorExporter - extends WebComponentExporter { - - public NoDefaultCtorExporter(String tag) { - super(tag); - } - - @Override - protected void configureInstance(WebComponent webComponent, - Component component) { - - } - - } - - public static class ExporterFactory - implements WebComponentExporterFactory { - - @Override - public WebComponentExporter create() { - return new NoDefaultCtorExporter("foo-bar"); - } - } -} diff --git a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentGeneratorTest.java b/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentGeneratorTest.java deleted file mode 100644 index f10b394e467..00000000000 --- a/flow-server/src/test/java/com/vaadin/flow/server/webcomponent/WebComponentGeneratorTest.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2000-2022 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.flow.server.webcomponent; - -import java.util.Map; - -import org.hamcrest.MatcherAssert; -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.flow.component.Component; -import com.vaadin.flow.component.WebComponentExporter; -import com.vaadin.flow.component.WebComponentExporterFactory.DefaultWebComponentExporterFactory; -import com.vaadin.flow.component.webcomponent.WebComponent; - -import static org.hamcrest.core.StringContains.containsString; -import static org.hamcrest.core.StringStartsWith.startsWith; - -public class WebComponentGeneratorTest { - - @Test - public void generatedReplacementMapContainsExpectedEntriesIncludingUi() { - assertGeneratedReplacementMapContainsExpectedEntries(true); - } - - @Test - public void generatedReplacementMapContainsExpectedEntriesExcludingUi() { - assertGeneratedReplacementMapContainsExpectedEntries(false); - } - - public void assertGeneratedReplacementMapContainsExpectedEntries( - boolean generateUi) { - MyComponentExporter exporter = new MyComponentExporter(); - - Map replacementsMap = WebComponentGenerator - .getReplacementsMap("my-component", - new WebComponentExporter.WebComponentConfigurationFactory() - .create(exporter).getPropertyDataSet(), - "/foo", generateUi, null); - - Assert.assertTrue("Missing dashed tag name", - replacementsMap.containsKey("TagDash")); - Assert.assertTrue("Missing camel cased tag name", - replacementsMap.containsKey("TagCamel")); - Assert.assertTrue("Missing 'AttributeChange'", - replacementsMap.containsKey("AttributeChange")); - Assert.assertTrue("Missing 'PropertyDefaults'", - replacementsMap.containsKey("PropertyDefaults")); - Assert.assertTrue("Missing 'PropertyMethods'", - replacementsMap.containsKey("PropertyMethods")); - Assert.assertTrue("Missing 'PropertyValues'", - replacementsMap.containsKey("PropertyValues")); - Assert.assertTrue("Missing frontend resources path", - replacementsMap.containsKey("frontend_resources")); - Assert.assertTrue("Missing ui import", - replacementsMap.containsKey("ui_import")); - - Assert.assertEquals("my-component", replacementsMap.get("TagDash")); - Assert.assertEquals("MyComponent", replacementsMap.get("TagCamel")); - - Assert.assertEquals("/foo", replacementsMap.get("frontend_resources")); - - if (generateUi) { - Assert.assertEquals( - "", - replacementsMap.get("ui_import")); - } else { - Assert.assertEquals("", replacementsMap.get("ui_import")); - } - - String attributeChange = replacementsMap.get("AttributeChange"); - MatcherAssert.assertThat(attributeChange, - containsString(String.format("if (attribute === 'message') {%n" - + " this['message'] = this._deserializeValue(value, " - + "String);"))); - MatcherAssert.assertThat(attributeChange, containsString( - String.format("if (attribute === 'integer-value') {%n" - + " this['integer-value'] = this._deserializeValue" - + "(value, Number);"))); - MatcherAssert.assertThat(attributeChange, containsString( - String.format("if (attribute === 'camel-case-value') {%n" - + " this['camelCaseValue'] = this._deserializeValue" - + "(value, Number);"))); - MatcherAssert.assertThat(attributeChange, - containsString(String.format("if (attribute === 'response') {%n" - + " this['response'] = this._deserializeValue(value," - + " String);"))); - - String propertyMethods = replacementsMap.get("PropertyMethods"); - MatcherAssert.assertThat(propertyMethods, - containsString("get ['message']() {")); - MatcherAssert.assertThat(propertyMethods, - containsString("set ['message'](value) {")); - MatcherAssert.assertThat(propertyMethods, - containsString("this._sync('message',")); - MatcherAssert.assertThat(propertyMethods, - containsString("set ['integer-value'](value) {")); - MatcherAssert.assertThat(propertyMethods, - containsString("this._sync('integer-value',")); - MatcherAssert.assertThat(propertyMethods, - containsString("set ['response'](value) {")); - MatcherAssert.assertThat(propertyMethods, - containsString("this._sync('response',")); - - String propertyValues = replacementsMap.get("PropertyValues"); - MatcherAssert.assertThat(propertyValues, - containsString("'message': this['message']")); - MatcherAssert.assertThat(propertyValues, - containsString("'integer-value': this['integer-value']")); - MatcherAssert.assertThat(propertyValues, - containsString("'response': this['response']")); - - String propertyDefaults = replacementsMap.get("PropertyDefaults"); - MatcherAssert.assertThat(propertyDefaults, - containsString("this['_message'] = ''")); - MatcherAssert.assertThat(propertyDefaults, - containsString("this['_integer-value'] = 0")); - MatcherAssert.assertThat(propertyDefaults, - containsString("this['_response'] = 'hello'")); - } - - @Test - public void providesHTMLModuleInBowerMode() { - String module = WebComponentGenerator.generateModule( - new DefaultWebComponentExporterFactory( - MyComponentExporter.class), - "", true, null); - // make sure that the test works on windows machines: - module = module.replace("\r", ""); - MatcherAssert.assertThat(module, startsWith( - "\n" + "