Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions flow-tests/vaadin-spring-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

<properties>
<maven.deploy.skip>true</maven.deploy.skip>
<component.version>25.2-SNAPSHOT</component.version>
<nimbus-jose-jwt.version>10.9.1</nimbus-jose-jwt.version>
</properties>

Expand Down Expand Up @@ -72,10 +71,19 @@
<artifactId>flow-html-components</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Faux Lumo replacements for the real vaadin-lumo-theme: the Lumo
class satisfies Flow's classpath detection for @Theme(name), and
test-lumo-theme ships the fake lumo/fake-lumo.css public resource.
Neither pulls any Vaadin component npm packages. -->
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-lumo-theme</artifactId>
<version>${component.version}</version>
<artifactId>flow-test-lumo</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>test-lumo-theme</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,74 +118,4 @@
</plugins>
</build>

<profiles>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess the dependencies were added to increase the startup class scanning effort. Removing all of them might somehow make the benchmark tests less effective.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes but the benchmark would need to be outside the flow project if it tests the full platform

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Makes sense. Actually, it already runs only as a nightly CI build, not during PR validation.

<profile>
<id>benchmark-directory-addons</id>
<!-- Profile is meant only for measuring reload time of application with -->
<!-- multiple dependencies to add-ons for Vaadin 24. -->
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-core</artifactId>
<version>${component.version}</version>
</dependency>
<dependency>
<groupId>org.vaadin.addons.componentfactory</groupId>
<artifactId>vcf-input-mask</artifactId>
<version>2.0.0</version>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.vaadin.componentfactory</groupId>
<artifactId>idle-notification</artifactId>
<version>2.0.1</version>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.vaadin.componentfactory</groupId>
<artifactId>autocomplete</artifactId>
<version>24.1.5</version>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.vaadin.componentfactory</groupId>
<artifactId>lookup-field-flow</artifactId>
<version>24.0.2</version>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.vaadin.componentfactory</groupId>
<artifactId>togglebutton</artifactId>
<version>3.0.0</version>
<exclusions>
<exclusion>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { css } from '@vaadin/vaadin-themable-mixin/register-styles.js';

const globalStyles = css`
const globalStyles = `
@keyframes element-rendered {
}

/*
* The attribute selector makes sure the element which animates isn't just a tag but an upgraded web component
* (button logic adds the role="button" attribute to the host element).
*/
vaadin-button[role='button'] {
animation: element-rendered;
}

button {
animation: element-rendered;
}
Expand All @@ -28,7 +18,7 @@ const globalStyles = css`
`;

const style = document.createElement('style');
style.textContent = globalStyles.cssText;
style.textContent = globalStyles;
document.head.appendChild(style);
window.layout = window.layout || {};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { css } from '@vaadin/vaadin-themable-mixin/register-styles.js';

const globalStyles = css`
const globalStyles = `
@keyframes element-rendered {
}

/*
* The attribute selector makes sure the element which animates isn't just a tag but an upgraded web component
* (button logic adds the role="button" attribute to the host element).
*/
vaadin-button[role='button'] {
animation: element-rendered;
}

button {
animation: element-rendered;
}
Expand All @@ -28,7 +18,7 @@ const globalStyles = css`
`;

const style = document.createElement('style');
style.textContent = globalStyles.cssText;
style.textContent = globalStyles;
document.head.appendChild(style);
window.layout = window.layout || {};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WrapsElement;
import org.openqa.selenium.remote.LocalFileDetector;
import org.openqa.selenium.remote.RemoteWebElement;

import com.vaadin.testbench.TestBenchElement;

import static com.vaadin.flow.spring.test.UploadView.UPLOAD_ID;

Expand All @@ -46,9 +41,7 @@ public void multiFileUpload() throws Exception {

File tempFile = createTempFile("foo");

TestBenchElement input = $(TestBenchElement.class).id(UPLOAD_ID);
setLocalFileDetector(input);
input.sendKeys(tempFile.getPath());
uploadFileToNativeInput(UPLOAD_ID, tempFile);

waitUntil(driver -> isElementPresent(By.className("uploaded-text")));
WebElement uploadedText = findElement(By.className("uploaded-text"));
Expand Down Expand Up @@ -80,22 +73,4 @@ private File createTempFile(String content) throws IOException {
tempFile.deleteOnExit();
return tempFile;
}

private void setLocalFileDetector(WebElement element) throws Exception {
if (getRunLocallyBrowser() != null) {
return;
}

if (element instanceof WrapsElement) {
element = ((WrapsElement) element).getWrappedElement();
}
if (element instanceof RemoteWebElement) {
((RemoteWebElement) element)
.setFileDetector(new LocalFileDetector());
} else {
throw new IllegalArgumentException(
"Expected argument of type RemoteWebElement, received "
+ element.getClass().getName());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright 2000-2026 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.flow.spring.test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.function.Supplier;

import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.html.H4;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Input;
import com.vaadin.flow.component.html.NativeButton;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.server.StreamRegistration;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.StreamResourceRegistry;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.streams.UploadHandler;

/**
* The "upload your loan application" UI shared by the Spring Security test
* apps. It uses a native {@code <input type="file">} that posts the selected
* file as a raw XHR body with an {@code X-Filename} header to a session-scoped
* {@link UploadHandler} (the servlets are not {@code @MultipartConfig}), and on
* success shows a confirmation paragraph (id {@code uploadText}) and the
* uploaded image (id {@code uploadImage}). It pulls no Vaadin component npm
* packages.
*/
public final class LoanApplicationUpload {

private LoanApplicationUpload() {
}

/**
* Adds the loan application upload UI to the given view.
*
* @param view
* the view to add the upload components to
* @param uploaderName
* supplies the name shown in the confirmation text, evaluated
* when an upload succeeds
*/
public static void addTo(HasComponents view,
Supplier<String> uploaderName) {
ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
UploadHandler uploadHandler = event -> {
try (InputStream inputStream = event.getInputStream()) {
inputStream.transferTo(imageStream);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
event.getUI().access(() -> {
Paragraph p = new Paragraph(
"Loan application uploaded by " + uploaderName.get());
p.setId("uploadText");
view.add(p);
Image image = new Image(new StreamResource("image.png",
() -> new ByteArrayInputStream(
imageStream.toByteArray())),
"image");
image.setId("uploadImage");
view.add(image);
});
};

StreamResourceRegistry resourceRegistry = VaadinSession.getCurrent()
.getResourceRegistry();
StreamRegistration streamRegistration = resourceRegistry
.registerResource(uploadHandler);
String uploadUrl = resourceRegistry
.getTargetURI(streamRegistration.getResource()).toString();

// The upload posts via fetch(), which does not piggyback Flow's UIDL
// sync. Click a hidden button after the response to force a server
// roundtrip that pulls down the queued DOM updates.
NativeButton uploadSync = new NativeButton("", event -> {
});
uploadSync.getStyle().set("display", "none");

Input uploadInput = new Input();
uploadInput.setType("file");
uploadInput.setId("uploadInput");
uploadInput.getElement().executeJs(
"""
this.addEventListener('change', () => {
const file = this.files[0];
if (!file) return;
fetch($0, {
method: 'POST',
headers: {
'Content-Type': file.type || 'application/octet-stream',
'X-Filename': encodeURIComponent(file.name)
},
body: file
}).then(() => $1.click());
});
""",
uploadUrl, uploadSync.getElement());

view.add(new H4("Upload your loan application"), uploadInput,
uploadSync);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,18 @@
*/
package com.vaadin.flow.spring.test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.WrapsElement;
import org.openqa.selenium.remote.LocalFileDetector;
import org.openqa.selenium.remote.RemoteWebElement;

import com.vaadin.flow.testutil.ChromeBrowserTest;
import com.vaadin.testbench.TestBenchElement;

public abstract class AbstractSpringTest extends ChromeBrowserTest {

Expand Down Expand Up @@ -77,4 +84,42 @@ private String getProperty(String key) {

}

/**
* Selects the given file in the native {@code <input type="file">} located
* by id. The file is transferred to the browser first, so this works with
* both locally run and remote browsers.
*
* @param inputId
* the id of the file input element
* @param file
* the local file to upload
*/
protected void uploadFileToNativeInput(String inputId, File file) {
TestBenchElement input = $(TestBenchElement.class).id(inputId);
setLocalFileDetector(input);
input.sendKeys(file.getAbsolutePath());
}

/*
* A remote browser cannot read a file path typed into the input, so the
* local file has to be transferred to it. On a locally run browser this is
* a no-op.
*/
private void setLocalFileDetector(WebElement element) {
if (getRunLocallyBrowser() != null) {
return;
}
if (element instanceof WrapsElement) {
element = ((WrapsElement) element).getWrappedElement();
}
if (element instanceof RemoteWebElement) {
((RemoteWebElement) element)
.setFileDetector(new LocalFileDetector());
} else {
throw new IllegalArgumentException(
"Expected argument of type RemoteWebElement, received "
+ element.getClass().getName());
}
}

}
Loading
Loading