View Javadoc
1   /*
2    * SPDX-License-Identifier: LGPL-2.1-or-later
3    * See LICENSE file for details.
4    *
5    * Copyright 2012-2026 Hazendaz.
6    */
7   package net.alchim31.maven.yuicompressor;
8   
9   import java.io.File;
10  import java.nio.charset.StandardCharsets;
11  import java.nio.file.Files;
12  import java.util.List;
13  
14  import org.apache.maven.api.plugin.testing.MojoExtension;
15  import org.codehaus.plexus.build.DefaultBuildContext;
16  import org.junit.jupiter.api.Assertions;
17  import org.junit.jupiter.api.Test;
18  import org.junit.jupiter.api.io.TempDir;
19  import org.mockito.ArgumentMatchers;
20  import org.mockito.Mockito;
21  import org.sonatype.plexus.build.incremental.BuildContext;
22  
23  /**
24   * Tests for {@link JSLintMojo} using direct instantiation.
25   */
26  // Note: public here needed for javadocs to work so don't remove it
27  public class JSLintMojoTest {
28  
29      /** Temporary directory for test output files. */
30      @TempDir
31      File tempDir;
32  
33      /**
34       * Test that executing the JSLintMojo with a valid JS file completes without throwing.
35       *
36       * @throws Exception
37       *             if test setup or execution fails
38       */
39      @Test
40      void testMojoExecute_withValidJsFile_doesNotThrow() throws Exception {
41          final File webappDir = tempDir.toPath().resolve("webapp-jslint").toFile();
42          webappDir.mkdirs();
43          final File jsFile = webappDir.toPath().resolve("simple.js").toFile();
44          Files.write(jsFile.toPath(), "var x = 1;".getBytes(StandardCharsets.UTF_8));
45  
46          final var mojo = createAndConfigureMojo(webappDir);
47          Assertions.assertDoesNotThrow(mojo::execute, "JSLintMojo.execute() should not throw for valid JS");
48      }
49  
50      /**
51       * Test that mojo execution is skipped when {@code skip} is set to true.
52       *
53       * @throws Exception
54       *             if test setup or execution fails
55       */
56      @Test
57      void testMojoExecute_skipTrue_doesNotProcess() throws Exception {
58          final File webappDir = tempDir.toPath().resolve("webapp-jslint-skip").toFile();
59          webappDir.mkdirs();
60          final var mojo = createAndConfigureMojo(webappDir);
61          MojoExtension.setVariableValueToObject(mojo, "skip", true);
62  
63          Assertions.assertDoesNotThrow(mojo::execute, "JSLintMojo.execute() with skip=true should not throw");
64      }
65  
66      /**
67       * Test that the default includes for JSLintMojo return the expected JS glob.
68       *
69       * @throws Exception
70       *             if test fails
71       */
72      @Test
73      void testGetDefaultIncludes_returnsJsGlob() throws Exception {
74          final var mojo = new JSLintMojo();
75          final String[] includes = mojo.getDefaultIncludes();
76          Assertions.assertNotNull(includes, "Default includes should not be null");
77          Assertions.assertEquals(1, includes.length, "Expected exactly one default include pattern");
78          Assertions.assertEquals("**/**.js", includes[0], "Default include should match '**/**.js'");
79      }
80  
81      /**
82       * Test that afterProcess() completes without throwing (it is a no-op).
83       *
84       * @throws Exception
85       *             if test fails
86       */
87      @Test
88      void testAfterProcess_doesNotThrow() throws Exception {
89          final var mojo = new JSLintMojo();
90          Assertions.assertDoesNotThrow(mojo::afterProcess, "afterProcess() should be a no-op");
91      }
92  
93      // ----------------------------------------------------------------------- helpers
94  
95      /**
96       * Creates and configures a {@link JSLintMojo} with the given webapp directory.
97       *
98       * @param warSourceDirectory
99       *            the webapp source directory containing JS files
100      *
101      * @return configured mojo
102      *
103      * @throws Exception
104      *             if field injection fails
105      */
106     private JSLintMojo createAndConfigureMojo(File warSourceDirectory) throws Exception {
107         final var mojo = new JSLintMojo();
108         final BuildContext legacyCtx = Mockito.mock(BuildContext.class);
109         Mockito.lenient().when(legacyCtx.newFileOutputStream(ArgumentMatchers.any(File.class)))
110                 .thenAnswer(inv -> Files.newOutputStream(((File) inv.getArgument(0)).toPath()));
111         final var buildContext = new DefaultBuildContext(legacyCtx);
112         MojoExtension.setVariableValueToObject(mojo, "buildContext", buildContext);
113         MojoExtension.setVariableValueToObject(mojo, "skip", false);
114         MojoExtension.setVariableValueToObject(mojo, "jswarn", false);
115         MojoExtension.setVariableValueToObject(mojo, "failOnWarning", false);
116         MojoExtension.setVariableValueToObject(mojo, "excludeResources", true);
117         MojoExtension.setVariableValueToObject(mojo, "excludeWarSourceDirectory", false);
118         MojoExtension.setVariableValueToObject(mojo, "warSourceDirectory", warSourceDirectory);
119         MojoExtension.setVariableValueToObject(mojo, "webappDirectory",
120                 tempDir.toPath().resolve("webapp-output").toFile());
121         MojoExtension.setVariableValueToObject(mojo, "outputDirectory", tempDir.toPath().resolve("classes").toFile());
122         MojoExtension.setVariableValueToObject(mojo, "sourceDirectory",
123                 tempDir.toPath().resolve("nonexistent-src").toFile());
124         MojoExtension.setVariableValueToObject(mojo, "resources", List.of());
125         return mojo;
126     }
127 }