View Javadoc
1   /*
2    * SPDX-License-Identifier: Apache-2.0
3    * See LICENSE file for details.
4    *
5    * Copyright 2018-2026 Hazendaz
6    * Copyright 2011-2018 tunyk
7    */
8   package com.tunyk.mvn.plugins.htmlcompressor;
9   
10  import java.nio.file.Files;
11  import java.nio.file.Path;
12  
13  import org.apache.maven.plugin.MojoExecutionException;
14  import org.junit.jupiter.api.AfterAll;
15  import org.junit.jupiter.api.Assertions;
16  import org.junit.jupiter.api.BeforeAll;
17  import org.junit.jupiter.api.BeforeEach;
18  import org.junit.jupiter.api.Test;
19  import org.junit.jupiter.api.io.TempDir;
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  /**
24   * The Class HtmlCompressorMojoTest.
25   */
26  class HtmlCompressorMojoTest {
27  
28      /** The Constant LOG. */
29      private static final Logger LOG = LoggerFactory.getLogger(HtmlCompressorMojoTest.class);
30  
31      /**
32       * Sets the up class.
33       */
34      @BeforeAll
35      static void setUpClass() {
36          LOG.info("Setting up class...");
37      }
38  
39      /**
40       * Tear down class.
41       */
42      @AfterAll
43      static void tearDownClass() {
44          LOG.info("Mojo test finished.");
45      }
46  
47      /**
48       * Sets the up.
49       */
50      @BeforeEach
51      void setUp() {
52          LOG.info("Setting up data for testing...");
53      }
54  
55      /**
56       * Test execute with default settings produces output files and statistics.
57       *
58       * @throws MojoExecutionException
59       *             the mojo execution exception
60       */
61      @Test
62      void testExecute() throws MojoExecutionException {
63          LOG.info("Testing mojo execution...");
64  
65          HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
66          htmlCompressorMojo.setSrcFolder("src/test/resources/html");
67          htmlCompressorMojo.setJavascriptHtmlSpriteIntegrationFile("src/test/resources/html/integration.js");
68          htmlCompressorMojo.setTargetFolder("target/htmlcompressor/html");
69          htmlCompressorMojo.execute();
70  
71          // Verify output files were produced
72          Assertions.assertTrue(Files.exists(Path.of("target/htmlcompressor/html/templates/Template1.html")),
73                  "Compressed Template1.html should exist in target folder");
74          Assertions.assertTrue(Files.exists(Path.of("target/htmlcompressor/html/templates/Template2.html")),
75                  "Compressed Template2.html should exist in target folder");
76  
77          LOG.info("Passed");
78      }
79  
80      /**
81       * Test execute when skip is true produces no output.
82       *
83       * @param tempDir
84       *            the temp dir provided by JUnit
85       *
86       * @throws MojoExecutionException
87       *             the mojo execution exception
88       */
89      @Test
90      void testExecuteSkip(@TempDir Path tempDir) throws MojoExecutionException {
91          LOG.info("Testing mojo execution with skip=true...");
92  
93          HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
94          htmlCompressorMojo.setSrcFolder("src/test/resources/html");
95          htmlCompressorMojo.setTargetFolder(tempDir.toString());
96          htmlCompressorMojo.setSkip(true);
97          htmlCompressorMojo.execute();
98  
99          // No files should be created in the target directory when skipped
100         Assertions.assertFalse(Files.exists(tempDir.resolve("templates/Template1.html")),
101                 "No output files should be created when skip=true");
102 
103         LOG.info("Passed");
104     }
105 
106     /**
107      * Test execute when enabled is false produces no output.
108      *
109      * @param tempDir
110      *            the temp dir provided by JUnit
111      *
112      * @throws MojoExecutionException
113      *             the mojo execution exception
114      */
115     @Test
116     void testExecuteDisabled(@TempDir Path tempDir) throws MojoExecutionException {
117         LOG.info("Testing mojo execution with enabled=false...");
118 
119         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
120         htmlCompressorMojo.setSrcFolder("src/test/resources/html");
121         htmlCompressorMojo.setTargetFolder(tempDir.toString());
122         htmlCompressorMojo.setEnabled(false);
123         htmlCompressorMojo.execute();
124 
125         // No files should be created when compression is disabled
126         Assertions.assertFalse(Files.exists(tempDir.resolve("templates/Template1.html")),
127                 "No output files should be created when enabled=false");
128 
129         LOG.info("Passed");
130     }
131 
132     /**
133      * Test execute when src folder does not exist produces no output and no exception.
134      *
135      * @param tempDir
136      *            the temp dir provided by JUnit
137      *
138      * @throws MojoExecutionException
139      *             the mojo execution exception
140      */
141     @Test
142     void testExecuteNonExistentSrcFolder(@TempDir Path tempDir) throws MojoExecutionException {
143         LOG.info("Testing mojo execution with non-existent source folder...");
144 
145         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
146         htmlCompressorMojo.setSrcFolder("/nonexistent/path/to/resources");
147         htmlCompressorMojo.setTargetFolder(tempDir.toString());
148 
149         // Should not throw an exception; just log a warning and return
150         Assertions.assertDoesNotThrow(htmlCompressorMojo::execute,
151                 "Execution should not throw when source folder does not exist");
152 
153         LOG.info("Passed");
154     }
155 
156     /**
157      * Test execute with deprecated fileExt parameter.
158      *
159      * @param tempDir
160      *            the temp dir provided by JUnit
161      *
162      * @throws MojoExecutionException
163      *             the mojo execution exception
164      */
165     @Test
166     @SuppressWarnings("deprecation")
167     void testExecuteWithDeprecatedFileExt(@TempDir Path tempDir) throws MojoExecutionException {
168         LOG.info("Testing mojo execution with deprecated fileExt parameter...");
169 
170         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
171         htmlCompressorMojo.setSrcFolder("src/test/resources/html");
172         htmlCompressorMojo.setTargetFolder(tempDir.toString());
173         htmlCompressorMojo.setJavascriptHtmlSprite(false);
174         // Set deprecated fileExt parameter (should be used when fileExtensions is null)
175         htmlCompressorMojo.setFileExt(new String[] { "html" });
176         htmlCompressorMojo.execute();
177 
178         // Files should be processed using the deprecated extension list
179         Assertions.assertTrue(Files.exists(tempDir.resolve("templates/Template1.html")),
180                 "Template1.html should be in output when using deprecated fileExt");
181 
182         LOG.info("Passed");
183     }
184 
185     /**
186      * Test execute with javascript html sprite disabled.
187      *
188      * @param tempDir
189      *            the temp dir provided by JUnit
190      *
191      * @throws MojoExecutionException
192      *             the mojo execution exception
193      */
194     @Test
195     void testExecuteWithJavascriptSpriteDisabled(@TempDir Path tempDir) throws MojoExecutionException {
196         LOG.info("Testing mojo execution with javascript sprite disabled...");
197 
198         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
199         htmlCompressorMojo.setSrcFolder("src/test/resources/html");
200         htmlCompressorMojo.setTargetFolder(tempDir.toString());
201         htmlCompressorMojo.setJavascriptHtmlSprite(false);
202         htmlCompressorMojo.setHtmlCompressionStatistics(tempDir.resolve("statistics.txt").toString());
203         htmlCompressorMojo.execute();
204 
205         // HTML files should be compressed
206         Assertions.assertTrue(Files.exists(tempDir.resolve("templates/Template1.html")),
207                 "Template1.html should be compressed to target folder");
208         // No integration JS file should be created
209         Assertions.assertFalse(Files.exists(tempDir.resolve("integration.js")),
210                 "Integration JS should not be created when sprite is disabled");
211 
212         LOG.info("Passed");
213     }
214 
215     /**
216      * Test HtmlCompressorMojo getters and setters for all configurable parameters.
217      */
218     @Test
219     void testHtmlMojoGettersSetters() {
220         LOG.info("Testing HtmlCompressorMojo getters and setters...");
221 
222         HtmlCompressorMojo mojo = new HtmlCompressorMojo();
223 
224         // Skip
225         Assertions.assertFalse(mojo.isSkip());
226         mojo.setSkip(true);
227         Assertions.assertTrue(mojo.isSkip());
228 
229         // Enabled
230         Assertions.assertTrue(mojo.getEnabled());
231         mojo.setEnabled(false);
232         Assertions.assertFalse(mojo.getEnabled());
233 
234         // Remove comments
235         Assertions.assertTrue(mojo.getRemoveComments());
236         mojo.setRemoveComments(false);
237         Assertions.assertFalse(mojo.getRemoveComments());
238 
239         // Remove multi-spaces
240         Assertions.assertTrue(mojo.getRemoveMultiSpaces());
241         mojo.setRemoveMultiSpaces(false);
242         Assertions.assertFalse(mojo.getRemoveMultiSpaces());
243 
244         // Remove intertag spaces
245         Assertions.assertFalse(mojo.getRemoveIntertagSpaces());
246         mojo.setRemoveIntertagSpaces(true);
247         Assertions.assertTrue(mojo.getRemoveIntertagSpaces());
248 
249         // Remove quotes
250         Assertions.assertFalse(mojo.getRemoveQuotes());
251         mojo.setRemoveQuotes(true);
252         Assertions.assertTrue(mojo.getRemoveQuotes());
253 
254         // Simple doctype
255         Assertions.assertFalse(mojo.getSimpleDoctype());
256         mojo.setSimpleDoctype(true);
257         Assertions.assertTrue(mojo.getSimpleDoctype());
258 
259         // Remove script attributes
260         Assertions.assertFalse(mojo.getRemoveScriptAttributes());
261         mojo.setRemoveScriptAttributes(true);
262         Assertions.assertTrue(mojo.getRemoveScriptAttributes());
263 
264         // Remove style attributes
265         Assertions.assertFalse(mojo.getRemoveStyleAttributes());
266         mojo.setRemoveStyleAttributes(true);
267         Assertions.assertTrue(mojo.getRemoveStyleAttributes());
268 
269         // Remove link attributes
270         Assertions.assertFalse(mojo.getRemoveLinkAttributes());
271         mojo.setRemoveLinkAttributes(true);
272         Assertions.assertTrue(mojo.getRemoveLinkAttributes());
273 
274         // Remove form attributes
275         Assertions.assertFalse(mojo.getRemoveFormAttributes());
276         mojo.setRemoveFormAttributes(true);
277         Assertions.assertTrue(mojo.getRemoveFormAttributes());
278 
279         // Remove input attributes
280         Assertions.assertFalse(mojo.getRemoveInputAttributes());
281         mojo.setRemoveInputAttributes(true);
282         Assertions.assertTrue(mojo.getRemoveInputAttributes());
283 
284         // Simple boolean attributes
285         Assertions.assertFalse(mojo.getSimpleBooleanAttributes());
286         mojo.setSimpleBooleanAttributes(true);
287         Assertions.assertTrue(mojo.getSimpleBooleanAttributes());
288 
289         // Remove javascript protocol
290         Assertions.assertFalse(mojo.getRemoveJavaScriptProtocol());
291         mojo.setRemoveJavaScriptProtocol(true);
292         Assertions.assertTrue(mojo.getRemoveJavaScriptProtocol());
293 
294         // Remove HTTP protocol
295         Assertions.assertFalse(mojo.getRemoveHttpProtocol());
296         mojo.setRemoveHttpProtocol(true);
297         Assertions.assertTrue(mojo.getRemoveHttpProtocol());
298 
299         // Remove HTTPS protocol
300         Assertions.assertFalse(mojo.getRemoveHttpsProtocol());
301         mojo.setRemoveHttpsProtocol(true);
302         Assertions.assertTrue(mojo.getRemoveHttpsProtocol());
303 
304         // Compress CSS
305         Assertions.assertFalse(mojo.getCompressCss());
306         mojo.setCompressCss(true);
307         Assertions.assertTrue(mojo.getCompressCss());
308 
309         // Preserve line breaks
310         Assertions.assertFalse(mojo.getPreserveLineBreaks());
311         mojo.setPreserveLineBreaks(true);
312         Assertions.assertTrue(mojo.getPreserveLineBreaks());
313 
314         // Compress JavaScript
315         Assertions.assertFalse(mojo.getCompressJavaScript());
316         mojo.setCompressJavaScript(true);
317         Assertions.assertTrue(mojo.getCompressJavaScript());
318 
319         // JS compressor type
320         Assertions.assertEquals("yui", mojo.getJsCompressor());
321         mojo.setJsCompressor("closure");
322         Assertions.assertEquals("closure", mojo.getJsCompressor());
323 
324         // Closure optimization level
325         Assertions.assertEquals("simple", mojo.getClosureOptLevel());
326         mojo.setClosureOptLevel("advanced");
327         Assertions.assertEquals("advanced", mojo.getClosureOptLevel());
328 
329         // Generate statistics
330         Assertions.assertTrue(mojo.getGenerateStatistics());
331         mojo.setGenerateStatistics(false);
332         Assertions.assertFalse(mojo.getGenerateStatistics());
333 
334         // Source and target folders
335         mojo.setSrcFolder("src/main/webapp");
336         Assertions.assertEquals("src/main/webapp", mojo.getSrcFolder());
337         mojo.setTargetFolder("target/compressed");
338         Assertions.assertEquals("target/compressed", mojo.getTargetFolder());
339 
340         // Javascript sprite settings
341         Assertions.assertTrue(mojo.getJavascriptHtmlSprite());
342         mojo.setJavascriptHtmlSprite(false);
343         Assertions.assertFalse(mojo.getJavascriptHtmlSprite());
344 
345         mojo.setJavascriptHtmlSpriteIntegrationFile("src/integration.js");
346         Assertions.assertEquals("src/integration.js", mojo.getJavascriptHtmlSpriteIntegrationFile());
347 
348         mojo.setJavascriptHtmlSpriteTargetFile("target/sprite.js");
349         Assertions.assertEquals("target/sprite.js", mojo.getJavascriptHtmlSpriteTargetFile());
350 
351         // Encoding
352         mojo.setEncoding("ISO-8859-1");
353         Assertions.assertEquals("ISO-8859-1", mojo.getEncoding());
354 
355         // HTML compression statistics file
356         mojo.setHtmlCompressionStatistics("target/stats.txt");
357         Assertions.assertEquals("target/stats.txt", mojo.getHtmlCompressionStatistics());
358 
359         // File extensions
360         mojo.setFileExt(new String[] { "xhtml" });
361         Assertions.assertArrayEquals(new String[] { "xhtml" }, mojo.getFileExt());
362         mojo.setFileExtensions(new String[] { "html", "htm" });
363         Assertions.assertArrayEquals(new String[] { "html", "htm" }, mojo.getFileExtensions());
364 
365         // YUI CSS line break
366         Assertions.assertEquals(-1, mojo.getYuiCssLineBreak());
367         mojo.setYuiCssLineBreak(120);
368         Assertions.assertEquals(120, mojo.getYuiCssLineBreak());
369 
370         // Closure custom externs only
371         Assertions.assertFalse(mojo.getClosureCustomExternsOnly());
372         mojo.setClosureCustomExternsOnly(true);
373         Assertions.assertTrue(mojo.getClosureCustomExternsOnly());
374 
375         // YUI JS configuration
376         Assertions.assertFalse(mojo.getYuiJsNoMunge());
377         mojo.setYuiJsNoMunge(true);
378         Assertions.assertTrue(mojo.getYuiJsNoMunge());
379 
380         Assertions.assertFalse(mojo.getYuiJsPreserveAllSemiColons());
381         mojo.setYuiJsPreserveAllSemiColons(true);
382         Assertions.assertTrue(mojo.getYuiJsPreserveAllSemiColons());
383 
384         Assertions.assertEquals(-1, mojo.getYuiJsLineBreak());
385         mojo.setYuiJsLineBreak(200);
386         Assertions.assertEquals(200, mojo.getYuiJsLineBreak());
387 
388         Assertions.assertFalse(mojo.getYuiJsDisableOptimizations());
389         mojo.setYuiJsDisableOptimizations(true);
390         Assertions.assertTrue(mojo.getYuiJsDisableOptimizations());
391 
392         // Preserve pattern arrays
393         mojo.setPreservePatterns(new String[] { "<span>.*?</span>" });
394         Assertions.assertArrayEquals(new String[] { "<span>.*?</span>" }, mojo.getPreservePatterns());
395 
396         // Closure externs
397         mojo.setClosureExterns(new String[] { "externs1.js", "externs2.js" });
398         Assertions.assertArrayEquals(new String[] { "externs1.js", "externs2.js" }, mojo.getClosureExterns());
399 
400         LOG.info("Passed");
401     }
402 
403     /**
404      * Test execute with predefined preserve patterns (PHP_TAG_PATTERN).
405      *
406      * @param tempDir
407      *            the temp dir provided by JUnit
408      *
409      * @throws MojoExecutionException
410      *             the mojo execution exception
411      */
412     @Test
413     void testExecuteWithPredefinedPreservePatterns(@TempDir Path tempDir) throws MojoExecutionException {
414         LOG.info("Testing mojo execution with predefined preserve patterns...");
415 
416         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
417         htmlCompressorMojo.setSrcFolder("src/test/resources/html");
418         htmlCompressorMojo.setTargetFolder(tempDir.toString());
419         htmlCompressorMojo.setJavascriptHtmlSprite(false);
420         htmlCompressorMojo.setHtmlCompressionStatistics(tempDir.resolve("statistics.txt").toString());
421         htmlCompressorMojo
422                 .setPredefinedPreservePatterns(new String[] { "PHP_TAG_PATTERN", "SERVER_SCRIPT_TAG_PATTERN" });
423         htmlCompressorMojo.execute();
424 
425         // Files should still be created successfully
426         Assertions.assertTrue(Files.exists(tempDir.resolve("templates/Template1.html")),
427                 "Template1.html should exist in output when using predefined preserve patterns");
428 
429         LOG.info("Passed");
430     }
431 
432     /**
433      * Test execute with custom preserve patterns.
434      *
435      * @param tempDir
436      *            the temp dir provided by JUnit
437      *
438      * @throws MojoExecutionException
439      *             the mojo execution exception
440      */
441     @Test
442     void testExecuteWithCustomPreservePatterns(@TempDir Path tempDir) throws MojoExecutionException {
443         LOG.info("Testing mojo execution with custom preserve patterns...");
444 
445         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
446         htmlCompressorMojo.setSrcFolder("src/test/resources/html");
447         htmlCompressorMojo.setTargetFolder(tempDir.toString());
448         htmlCompressorMojo.setJavascriptHtmlSprite(false);
449         htmlCompressorMojo.setHtmlCompressionStatistics(tempDir.resolve("statistics.txt").toString());
450         htmlCompressorMojo.setPreservePatterns(new String[] { "<div[^>]*>.*?</div>" });
451         htmlCompressorMojo.execute();
452 
453         // Files should still be created successfully
454         Assertions.assertTrue(Files.exists(tempDir.resolve("templates/Template1.html")),
455                 "Template1.html should exist in output when using custom preserve patterns");
456 
457         LOG.info("Passed");
458     }
459 
460     /**
461      * Test execute with invalid preserve pattern throws MojoExecutionException.
462      */
463     @Test
464     void testExecuteWithInvalidPreservePatternThrows() {
465         LOG.info("Testing mojo execution with invalid preserve pattern...");
466 
467         HtmlCompressorMojo htmlCompressorMojo = new HtmlCompressorMojo();
468         htmlCompressorMojo.setSrcFolder("src/test/resources/html");
469         htmlCompressorMojo.setTargetFolder("target/test/invalid-pattern");
470         htmlCompressorMojo.setJavascriptHtmlSprite(false);
471         // Invalid regex pattern should cause MojoExecutionException
472         htmlCompressorMojo.setPreservePatterns(new String[] { "[invalid-regex(" });
473 
474         Assertions.assertThrows(MojoExecutionException.class, htmlCompressorMojo::execute,
475                 "Should throw MojoExecutionException for invalid preserve pattern regex");
476 
477         LOG.info("Passed");
478     }
479 }