Skip to content

Commit

Permalink
fix: Add missing check for default frontend folder existence (#18872)
Browse files Browse the repository at this point in the history
* fix: Add missing check for default frontend folder existence

* Add legacy location to plugins

* Fix incorrect relative path in Gradle plugin

* add unit tests

* add unit test for gradle
  • Loading branch information
mshabarov authored Mar 4, 2024
1 parent b174cc7 commit 0f7bf62
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ class VaadinSmokeTest : AbstractGradleTest() {
expect(false, buildInfo.toJson()) { buildInfo.getBoolean(InitParameters.SERVLET_PARAMETER_PRODUCTION_MODE) }
}

@Test
fun testPrepareFrontend_legacyFrontendFolder_usesLegacy() {
testProject.newFolder("frontend");
testProject.build("vaadinPrepareFrontend")
expect(true) { File(testProject.dir, "frontend/generated").exists() }
}

@Test
fun `vaadinBuildFrontend not ran by default in development mode`() {
val result: BuildResult = testProject.build("build")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ public class PluginEffectiveConfiguration(
.convention(project.projectDir)

public val frontendDirectory: Provider<File> = extension.frontendDirectory
.convention(File(project.projectDir, FrontendUtils.DEFAULT_FRONTEND_DIR))
.convention(FrontendUtils.getLegacyFrontendFolderIfExists(project.projectDir, File(project.projectDir, FrontendUtils.DEFAULT_FRONTEND_DIR)))

public val generateBundle: Provider<Boolean> = extension.generateBundle
.convention(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public abstract class FlowModeAbstractMojo extends AbstractMojo
/**
* A directory with project's frontend source files.
*/
@Parameter(defaultValue = "${project.basedir}/src/main/" + FRONTEND)
@Parameter(defaultValue = "${null}")
private File frontendDirectory;

/**
Expand Down Expand Up @@ -299,7 +299,13 @@ public boolean eagerServerLoad() {

@Override
public File frontendDirectory() {
return frontendDirectory;
if (frontendDirectory != null) {
return frontendDirectory;
}
File defaultFrontendFolder = new File(projectBasedir,
FrontendUtils.DEFAULT_FRONTEND_DIR);
return FrontendUtils.getLegacyFrontendFolderIfExists(projectBasedir,
defaultFrontendFolder);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.vaadin.flow.server.Constants;
import com.vaadin.flow.server.InitParameters;
import com.vaadin.flow.server.frontend.FrontendTools;
import com.vaadin.flow.server.frontend.FrontendUtils;
import com.vaadin.flow.server.frontend.installer.NodeInstaller;

import elemental.json.Json;
Expand Down Expand Up @@ -282,6 +283,24 @@ public void jarPackaging_copyProjectFrontendResources()
Mockito.verify(project, Mockito.atLeastOnce()).getArtifacts();
}

@Test
public void getFrontendFolder_legacyExists_propertyNotSet_returnsLegacy()
throws IllegalAccessException {
Assert.assertFalse(
new File(projectBase, FrontendUtils.DEFAULT_FRONTEND_DIR)
.exists());
ReflectionUtils.setVariableValueInObject(mojo, "frontendDirectory",
null);
File legacyFrontend = new File(projectBase,
FrontendUtils.LEGACY_FRONTEND_DIR);
if (!legacyFrontend.mkdir()) {
Assert.fail("Failed to generate legacy frontend folder");
}
Assert.assertEquals(
"Expected legacy frontend folder to be used if exists",
legacyFrontend, mojo.frontendDirectory());
}

private void assertPackageJsonContent() throws IOException {
JsonObject packageJsonObject = getPackageJson(packageJson);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public static void prepareFrontend(PluginAdapterBase adapter)
Lookup lookup = adapter.createLookup(classFinder);

Options options = new Options(lookup, adapter.npmFolder())
.withFrontendDirectory(getFrontendDirectory(adapter))
.withFrontendDirectory(adapter.frontendDirectory())
.withBuildDirectory(adapter.buildFolder())
.withJarFrontendResourcesFolder(
getJarFrontendResourcesFolder(adapter))
Expand Down Expand Up @@ -182,8 +182,7 @@ public static void prepareFrontend(PluginAdapterBase adapter)
private static File getJarFrontendResourcesFolder(
PluginAdapterBase adapter) {
return new File(
new File(getFrontendDirectory(adapter),
FrontendUtils.GENERATED),
new File(adapter.frontendDirectory(), FrontendUtils.GENERATED),
FrontendUtils.JAR_RESOURCES_FOLDER);
}

Expand Down Expand Up @@ -232,7 +231,7 @@ public static File propagateBuildInfo(PluginAdapterBase adapter) {
e);
}
buildInfo.put(FRONTEND_TOKEN,
getFrontendDirectory(adapter).getAbsolutePath());
adapter.frontendDirectory().getAbsolutePath());
buildInfo.put(CONNECT_JAVA_SOURCE_FOLDER_TOKEN,
adapter.javaSourceFolder().getAbsolutePath());
buildInfo.put(JAVA_RESOURCE_FOLDER_TOKEN,
Expand Down Expand Up @@ -306,7 +305,7 @@ public static void runNodeUpdater(PluginAdapterBuild adapter)
try {
Options options = new com.vaadin.flow.server.frontend.Options(
lookup, adapter.npmFolder())
.withFrontendDirectory(getFrontendDirectory(adapter))
.withFrontendDirectory(adapter.frontendDirectory())
.withBuildDirectory(adapter.buildFolder())
.withRunNpmInstall(adapter.runNpmInstall())
.withWebpack(adapter.webpackOutputDirectory(),
Expand Down Expand Up @@ -372,7 +371,7 @@ public static void runDevBuildNodeUpdater(PluginAdapterBuild adapter)
try {
Options options = new com.vaadin.flow.server.frontend.Options(
lookup, adapter.npmFolder()).withProductionMode(false)
.withFrontendDirectory(getFrontendDirectory(adapter))
.withFrontendDirectory(adapter.frontendDirectory())
.withBuildDirectory(adapter.buildFolder())
.withRunNpmInstall(adapter.runNpmInstall())
.withWebpack(adapter.webpackOutputDirectory(),
Expand Down Expand Up @@ -413,25 +412,6 @@ public static void runDevBuildNodeUpdater(PluginAdapterBuild adapter)
}
}

/**
* Get the legacy frontend folder if available and new folder doesn't exist.
*
* @param adapter
* PluginAdapterBase
* @return correct folder or legacy folder if not user defined
*/
public static File getFrontendDirectory(PluginAdapterBase adapter) {
File frontendDir = adapter.frontendDirectory();
if (!frontendDir.exists() && frontendDir.toPath()
.endsWith(DEFAULT_FRONTEND_DIR.substring(2))) {
File legacy = new File(adapter.npmFolder(), LEGACY_FRONTEND_DIR);
if (legacy.exists()) {
return legacy;
}
}
return frontendDir;
}

/**
* The generated folder should be under frontend folder and will be moved to
* the legacy package if not changed by the user.
Expand All @@ -445,8 +425,7 @@ public static File getGeneratedFrontendDirectory(
if (adapter.generatedTsFolder().toPath()
.startsWith(adapter.frontendDirectory().toPath())) {
// Possibly move frontend folder.
File frontendDirectory = getFrontendDirectory(adapter);
return new File(frontendDirectory, GENERATED);
return new File(adapter.frontendDirectory(), GENERATED);
}
// Return given generated folder
return adapter.generatedTsFolder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,18 +596,50 @@ public static File resolveFrontendPath(File projectRoot,
getFrontendFolder(projectRoot, deploymentConfiguration));
}

private static File getFrontendFolder(File projectRoot,
/**
* Get the frontend folder location from configuration and fallbacks to
* {@link #LEGACY_FRONTEND_DIR} if it doesn't exist.
*
* @param projectRoot
* project's root directory
* @param deploymentConfiguration
* applications' configuration
* @return frontend folder location that is used by application to look for
* frontend files
*/
public static File getFrontendFolder(File projectRoot,
AbstractConfiguration deploymentConfiguration) {
String frontendFolderPath = deploymentConfiguration.getStringProperty(
FrontendUtils.PARAM_FRONTEND_DIR,
FrontendUtils.DEFAULT_FRONTEND_DIR);
PARAM_FRONTEND_DIR,
System.getProperty(PARAM_FRONTEND_DIR, DEFAULT_FRONTEND_DIR));

File f = new File(frontendFolderPath);
if (f.isAbsolute()) {
return f;
File frontendFolderFile = new File(frontendFolderPath);
if (!frontendFolderFile.isAbsolute()) {
frontendFolderFile = new File(projectRoot, frontendFolderPath);
}

return new File(projectRoot, frontendFolderPath);
return getLegacyFrontendFolderIfExists(projectRoot, frontendFolderFile);
}

/**
* Get the legacy frontend folder if available and new folder doesn't exist.
*
* @param projectRoot
* project's root directory
* @param frontendDir
* the frontend directory location from project's configuration
* @return correct folder or legacy folder if not user defined
*/
public static File getLegacyFrontendFolderIfExists(File projectRoot,
File frontendDir) {
if (!frontendDir.exists() && frontendDir.toPath()
.endsWith(DEFAULT_FRONTEND_DIR.substring(2))) {
File legacy = new File(projectRoot, LEGACY_FRONTEND_DIR);
if (legacy.exists()) {
return legacy;
}
}
return frontendDir;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,8 @@ public static Optional<String> getThemeName(VaadinContext context) {
return getThemeAnnotation(context).map(Theme::value);
} else {
File themeJs;
String frontendFolderPath = config.getStringProperty(
FrontendUtils.PARAM_FRONTEND_DIR,
FrontendUtils.DEFAULT_FRONTEND_DIR);
String frontendFolderPath = FrontendUtils
.getProjectFrontendDir(config).getPath();
if (frontendFolderPath.startsWith("./")) {
themeJs = Paths.get(config.getProjectFolder().getPath(),
frontendFolderPath, FrontendUtils.GENERATED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.slf4j.LoggerFactory;

import com.vaadin.flow.internal.Pair;
import com.vaadin.flow.server.AbstractConfiguration;
import com.vaadin.flow.server.ExecutionFailedException;
import com.vaadin.flow.server.frontend.installer.NodeInstaller;
import com.vaadin.flow.server.frontend.scanner.FrontendDependencies;
Expand Down Expand Up @@ -651,6 +652,22 @@ public void isHillaViewsUsed_noViews_false() throws IOException {
FrontendUtils.isHillaViewsUsed(frontend));
}

@Test
public void getFrontendFolder_hasLegacyFolder_returnsLegacyFolder()
throws IOException {
File frontend = tmpDir.newFolder(FrontendUtils.LEGACY_FRONTEND_DIR);
AbstractConfiguration config = Mockito
.mock(AbstractConfiguration.class);
Mockito.when(config.getStringProperty(Mockito.anyString(),
Mockito.anyString()))
.thenReturn(FrontendUtils.DEFAULT_FRONTEND_DIR);
File resolvedFrontend = FrontendUtils
.getFrontendFolder(tmpDir.getRoot(), config);
Assert.assertEquals(
"Expected legacy frontend folder to be used if exists",
frontend, resolvedFrontend);
}

private File prepareFrontendForRoutesFile(String fileName, String content)
throws IOException {
File frontend = tmpDir.newFolder(FrontendUtils.DEFAULT_FRONTEND_DIR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,26 +208,19 @@ public static DevModeHandler initDevModeHandler(Set<Class<?>> classes,
new StatisticsSender(storage));
}

String frontendFolder = config.getStringProperty(PARAM_FRONTEND_DIR,
System.getProperty(PARAM_FRONTEND_DIR, DEFAULT_FRONTEND_DIR));

// If new default frontend folder not exists check for legacy folder.
if (frontendFolder.endsWith(DEFAULT_FRONTEND_DIR)
&& !new File(frontendFolder).exists()) {
File legacy = new File(baseDir, LEGACY_FRONTEND_DIR);
if (legacy.exists()) {
frontendFolder = LEGACY_FRONTEND_DIR;
}
}
File frontendFolder = FrontendUtils.getProjectFrontendDir(config);
String frontendGeneratedFolderPath = config.getStringProperty(
PROJECT_FRONTEND_GENERATED_DIR_TOKEN, FrontendUtils
.getFrontendGeneratedFolder(frontendFolder).getPath());
File frontendGeneratedFolder = new File(frontendGeneratedFolderPath);

Lookup lookupFromContext = context.getAttribute(Lookup.class);
Lookup lookupForClassFinder = Lookup.of(new DevModeClassFinder(classes),
ClassFinder.class);
Lookup lookup = Lookup.compose(lookupForClassFinder, lookupFromContext);
Options options = new Options(lookup, baseDir)
.withFrontendDirectory(new File(frontendFolder))
.withFrontendGeneratedFolder(
new File(frontendFolder + GENERATED))
.withFrontendDirectory(frontendFolder)
.withFrontendGeneratedFolder(frontendGeneratedFolder)
.withBuildDirectory(config.getBuildFolder());

log().info("Starting dev-mode updaters in {} folder.",
Expand Down Expand Up @@ -273,13 +266,6 @@ public static DevModeHandler initDevModeHandler(Set<Class<?>> classes,
InitParameters.ADDITIONAL_POSTINSTALL_PACKAGES, "")
.split(",");

String frontendGeneratedFolderName = config.getStringProperty(
PROJECT_FRONTEND_GENERATED_DIR_TOKEN,
new File(frontendFolder).isAbsolute()
? Paths.get(frontendFolder, GENERATED).toString()
: Paths.get(baseDir.getAbsolutePath(), frontendFolder,
GENERATED).toString());
File frontendGeneratedFolder = new File(frontendGeneratedFolderName);
File jarFrontendResourcesFolder = new File(frontendGeneratedFolder,
FrontendUtils.JAR_RESOURCES_FOLDER);
JsonObject tokenFileData = Json.createObject();
Expand Down

0 comments on commit 0f7bf62

Please sign in to comment.