View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.gui;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static org.mockito.ArgumentMatchers.any;
24  import static org.mockito.ArgumentMatchers.startsWith;
25  import static org.mockito.Mockito.doCallRealMethod;
26  import static org.mockito.Mockito.mockConstruction;
27  import static org.mockito.Mockito.mockStatic;
28  import static org.mockito.Mockito.when;
29  
30  import java.awt.Component;
31  import java.awt.Window;
32  import java.io.File;
33  import java.io.IOException;
34  import java.util.Arrays;
35  
36  import javax.swing.JButton;
37  import javax.swing.JComboBox;
38  import javax.swing.JFileChooser;
39  import javax.swing.JOptionPane;
40  import javax.swing.JTextArea;
41  import javax.swing.filechooser.FileFilter;
42  
43  import org.junit.jupiter.api.AfterEach;
44  import org.junit.jupiter.api.BeforeEach;
45  import org.junit.jupiter.api.Test;
46  import org.mockito.MockedConstruction;
47  import org.mockito.MockedStatic;
48  
49  import com.puppycrawl.tools.checkstyle.AbstractGuiTestSupport;
50  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
51  
52  public class MainFrameTest extends AbstractGuiTestSupport {
53  
54      private static final String TEST_FILE_NAME = "InputMainFrame.java";
55      private static final String NON_EXISTENT_FILE_NAME = "non-existent.file";
56  
57      private MainFrame mainFrame;
58  
59      @Override
60      protected String getPackageLocation() {
61          return "com/puppycrawl/tools/checkstyle/gui/mainframe";
62      }
63  
64      @BeforeEach
65      public void prepare() {
66          mainFrame = new MainFrame();
67      }
68  
69      @AfterEach
70      public void tearDown() {
71          Arrays.stream(mainFrame.getOwnedWindows())
72                  .forEach(Window::dispose);
73      }
74  
75      @Test
76      public void testOpenFile() throws IOException {
77          mainFrame.openFile(new File(getPath(TEST_FILE_NAME)));
78          assertWithMessage("Unexpected frame title")
79                  .that(mainFrame.getTitle())
80                  .isEqualTo("Checkstyle GUI : " + TEST_FILE_NAME);
81      }
82  
83      /**
84       * Test for opening a non-existent file.
85       * {@code JOptionPane} is mocked to prevent showing a modal message box.
86       *
87       * @throws IOException if I/O exception occurs while forming the path.
88       */
89      @Test
90      public void testOpenNonExistentFile() throws IOException {
91          final File file = new File(getPath(NON_EXISTENT_FILE_NAME));
92          try (MockedStatic<JOptionPane> optionPane = mockStatic(JOptionPane.class)) {
93              mainFrame.openFile(file);
94              optionPane.verify(() -> {
95                  JOptionPane.showMessageDialog(any(Component.class),
96                          startsWith("FileNotFoundException occurred while opening file"));
97              });
98          }
99          final MainFrameModel model = TestUtil.getInternalState(mainFrame,
100                 "model", MainFrameModel.class);
101         assertWithMessage("Unexpected current file")
102                 .that(model.getCurrentFile())
103                 .isEqualTo(file);
104     }
105 
106     @Test
107     public void testChangeMode() {
108         final JComboBox<MainFrameModel.ParseMode> modesCombobox =
109                 findComponentComboBoxByName(mainFrame, "modesCombobox");
110         modesCombobox.setSelectedItem(MainFrameModel.ParseMode.JAVA_WITH_COMMENTS);
111         final MainFrameModel model = TestUtil.getInternalState(mainFrame,
112                 "model", MainFrameModel.class);
113         final MainFrameModel.ParseMode parseMode = TestUtil.getInternalState(model,
114                 "parseMode", MainFrameModel.ParseMode.class);
115         assertWithMessage("Unexpected parse mode")
116                 .that(parseMode)
117                 .isEqualTo(MainFrameModel.ParseMode.JAVA_WITH_COMMENTS);
118     }
119 
120     /**
121      * Test for opening a file with the "Open File" button.
122      * {@code JFileChooser} is mocked to prevent showing a modal dialog box.
123      *
124      * @throws IOException if I/O exception occurs while forming the path.
125      */
126     @Test
127     public void testOpenFileButton() throws IOException {
128         final JButton openFileButton = findComponentByName(mainFrame,
129                 "openFileButton", JButton.class);
130         final File testFile = new File(getPath(TEST_FILE_NAME));
131         try (MockedConstruction<JFileChooser> mocked = mockConstruction(
132                 JFileChooser.class, (mock, context) -> {
133                     when(mock.showOpenDialog(mainFrame)).thenReturn(JFileChooser.APPROVE_OPTION);
134                     when(mock.getSelectedFile()).thenReturn(testFile);
135                 })) {
136             openFileButton.doClick();
137         }
138         assertWithMessage("Unexpected frame title")
139                 .that(mainFrame.getTitle())
140                 .isEqualTo("Checkstyle GUI : " + TEST_FILE_NAME);
141     }
142 
143     /**
144      * Test for the {@link FileFilter} passed to {@code JFileChooser} to gain 100% coverage.
145      * {@code JFileChooser} is mocked to obtain an instance of {@code JavaFileFilter} class.
146      */
147     @Test
148     public void testFileFilter() {
149         final JButton openFileButton = findComponentByName(mainFrame,
150                 "openFileButton", JButton.class);
151         try (MockedConstruction<JFileChooser> mocked = mockConstruction(
152                 JFileChooser.class, (mock, context) -> {
153                     when(mock.showOpenDialog(mainFrame)).thenReturn(JFileChooser.CANCEL_OPTION);
154                     when(mock.getFileFilter()).thenCallRealMethod();
155                     doCallRealMethod().when(mock).setFileFilter(any(FileFilter.class));
156                 })) {
157             openFileButton.doClick();
158 
159             final FileFilter fileFilter = mocked.constructed().get(0).getFileFilter();
160             assertWithMessage("The file should be accepted")
161                     .that(fileFilter.accept(new File(TEST_FILE_NAME)))
162                     .isTrue();
163             assertWithMessage("Unexpected frame title")
164                     .that(fileFilter.getDescription())
165                     .isEqualTo("Java Source File");
166         }
167     }
168 
169     @Test
170     public void testExpandButton() {
171         final JButton expandButton = findComponentByName(mainFrame,
172                 "expandButton", JButton.class);
173         final JTextArea xpathTextArea = findComponentByName(mainFrame,
174                 "xpathTextArea", JTextArea.class);
175         expandButton.doClick();
176         assertWithMessage("The XPath text area should be visible")
177                 .that(xpathTextArea.isVisible())
178                 .isTrue();
179         expandButton.doClick();
180         assertWithMessage("The XPath text area should be hidden")
181                 .that(xpathTextArea.isVisible())
182                 .isFalse();
183     }
184 
185     @Test
186     public void testFindNodeButton() throws IOException {
187         mainFrame.openFile(new File(getPath(TEST_FILE_NAME)));
188         final JButton findNodeButton = findComponentByName(mainFrame,
189                 "findNodeButton", JButton.class);
190         final JTextArea xpathTextArea = findComponentByName(mainFrame,
191                 "xpathTextArea", JTextArea.class);
192         findNodeButton.doClick();
193         assertWithMessage("Unexpected XPath text area text")
194                 .that(xpathTextArea.getText())
195                 .isEqualTo("No elements matching XPath query 'Xpath' found.");
196     }
197 
198 }