Skip to content

Commit 6af4041

Browse files
vaadin-botArtur-
andauthored
fix: Detect theme component CSS changes even without theme.json (#23452) (#23457)
themeShadowDOMStylesheetsChanged only scanned for components/ folders in themes discovered via theme.json. Themes without a theme.json (but with a components/ directory) were silently skipped, so the dev bundle was never rebuilt to include their component styles. Always include the main theme name when scanning for components/ folders, regardless of whether theme.json exists. Fixes #23438 Co-authored-by: Artur Signell <artur@vaadin.com>
1 parent c077045 commit 6af4041

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

flow-server/src/main/java/com/vaadin/flow/server/frontend/ThemeValidationUtil.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.Collection;
2626
import java.util.Collections;
2727
import java.util.HashMap;
28+
import java.util.HashSet;
2829
import java.util.List;
2930
import java.util.Map;
3031
import java.util.Optional;
@@ -173,12 +174,18 @@ public static boolean themeShadowDOMStylesheetsChanged(Options options,
173174
.map(ThemeDefinition::getName).filter(name -> !name.isBlank())
174175
.map(themeName -> {
175176
Map<String, JsonNode> themeJsonContents = new HashMap<>();
176-
ThemeUtils.getThemeJson(themeName, frontendDirectory)
177-
.ifPresent(
178-
themeJson -> collectThemeJsonContentsInFrontend(
179-
options, themeJsonContents,
180-
themeName, themeJson));
181-
return themeJsonContents.keySet().stream()
177+
Optional<JsonNode> themeJson = ThemeUtils
178+
.getThemeJson(themeName, frontendDirectory);
179+
themeJson.ifPresent(
180+
json -> collectThemeJsonContentsInFrontend(options,
181+
themeJsonContents, themeName, json));
182+
// Always include the main theme itself, even
183+
// without theme.json, so its components/ folder
184+
// is checked
185+
Set<String> themeNames = new HashSet<>(
186+
themeJsonContents.keySet());
187+
themeNames.add(themeName);
188+
return themeNames.stream()
182189
.map(name -> ThemeUtils
183190
.getThemeFolder(frontendDirectory, name))
184191
.map(dir -> new File(dir, "components"))

flow-server/src/test/java/com/vaadin/flow/server/frontend/BundleValidationTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,39 @@ public void projectParentInJarThemeComponentsCSS_removedFromProject_bundleRebuil
17951795
needsBuild);
17961796
}
17971797

1798+
@Test
1799+
public void projectThemeComponentsCSS_noThemeJson_bundleRebuild()
1800+
throws IOException {
1801+
// Theme has components/ folder with CSS but no theme.json
1802+
String cssTemplate = "[part=\"input-field\"]{background: %s; }";
1803+
createPackageJsonStub(BLANK_PACKAGE_JSON_WITH_HASH);
1804+
1805+
// Create components CSS file without creating theme.json
1806+
String themeLocation = "themes/my-theme/components/";
1807+
File stylesheetFile = new File(temporaryFolder.getRoot(),
1808+
DEFAULT_FRONTEND_DIR + themeLocation + "vaadin-text-field.css");
1809+
FileUtils.forceMkdir(stylesheetFile.getParentFile());
1810+
FileUtils.write(stylesheetFile, String.format(cssTemplate, "blue"),
1811+
StandardCharsets.UTF_8);
1812+
1813+
final FrontendDependenciesScanner depScanner = Mockito
1814+
.mock(FrontendDependenciesScanner.class);
1815+
final ThemeDefinition themeDefinition = Mockito
1816+
.mock(ThemeDefinition.class);
1817+
Mockito.when(themeDefinition.getName()).thenReturn("my-theme");
1818+
Mockito.when(depScanner.getThemeDefinition())
1819+
.thenReturn(themeDefinition);
1820+
1821+
ObjectNode stats = getBasicStats();
1822+
setupFrontendUtilsMock(stats);
1823+
1824+
boolean needsBuild = BundleValidationUtil.needsBuild(options,
1825+
depScanner, mode);
1826+
Assert.assertTrue(
1827+
"Should rebuild when theme has components CSS but no theme.json",
1828+
needsBuild);
1829+
}
1830+
17981831
@Test
17991832
public void indexTsAdded_rebuildRequired() throws IOException {
18001833
createPackageJsonStub(BLANK_PACKAGE_JSON_WITH_HASH);

0 commit comments

Comments
 (0)