1+ /*
2+ * MIT License
3+ *
4+ * Copyright (c) 2025 Mitja Leino
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in all
14+ * copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+ package com.mituuz.fuzzier.grep
26+
27+ import com.intellij.openapi.project.Project
28+ import com.intellij.openapi.vcs.changes.ChangeListManager
29+ import com.intellij.openapi.vfs.VirtualFile
30+ import com.intellij.testFramework.TestApplicationManager
31+ import com.mituuz.fuzzier.components.FuzzyFinderComponent
32+ import com.mituuz.fuzzier.entities.CaseMode
33+ import com.mituuz.fuzzier.entities.GrepConfig
34+ import com.mituuz.fuzzier.grep.backend.BackendStrategy
35+ import io.mockk.every
36+ import io.mockk.mockk
37+ import io.mockk.unmockkAll
38+ import kotlinx.coroutines.runBlocking
39+ import org.junit.jupiter.api.AfterEach
40+ import org.junit.jupiter.api.Assertions.assertEquals
41+ import org.junit.jupiter.api.Assertions.assertNotNull
42+ import org.junit.jupiter.api.BeforeEach
43+ import org.junit.jupiter.api.Test
44+
45+ class FuzzyGrepTest {
46+ private lateinit var fGrep: FuzzyGrep
47+
48+ private data class ValidVfContext (
49+ val file : VirtualFile ,
50+ val clm : ChangeListManager
51+ )
52+
53+ private data class FindInFilesContext (
54+ val project : Project ,
55+ val component : FuzzyFinderComponent ,
56+ val backend : BackendStrategy ,
57+ val clm : ChangeListManager
58+ )
59+
60+ @BeforeEach
61+ fun setUp () {
62+ TestApplicationManager .getInstance()
63+ fGrep = FuzzyGrep ()
64+ }
65+
66+ @AfterEach
67+ fun tearDown () {
68+ unmockkAll()
69+ }
70+
71+ private fun createValidVfContext (
72+ isDirectory : Boolean = false,
73+ isBinary : Boolean = false,
74+ isIgnored : Boolean = false,
75+ extension : String? = null
76+ ): ValidVfContext {
77+ val file = mockk<VirtualFile >()
78+ val clm = mockk<ChangeListManager >()
79+
80+ every { file.isDirectory } returns isDirectory
81+ every { file.fileType.isBinary } returns isBinary
82+ every { clm.isIgnoredFile(file) } returns isIgnored
83+ if (extension != null ) {
84+ every { file.extension } returns extension
85+ }
86+
87+ return ValidVfContext (file, clm)
88+ }
89+
90+ private fun createFindInFilesContext (
91+ projectBasePath : String? = "/tmp/project",
92+ secondaryText : String = "kt"
93+ ): FindInFilesContext {
94+ val project = mockk<Project >()
95+ val component = mockk<FuzzyFinderComponent >()
96+ val backend = mockk<BackendStrategy >()
97+ val clm = mockk<ChangeListManager >()
98+
99+ every { project.basePath } returns projectBasePath
100+ every { component.getSecondaryText() } returns secondaryText
101+
102+ fGrep.component = component
103+ fGrep.updateBackend(backend)
104+ fGrep.updateGrepConfig(
105+ GrepConfig (targets = null , caseMode = CaseMode .SENSITIVE , title = " Fuzzy Grep" )
106+ )
107+
108+ return FindInFilesContext (project, component, backend, clm)
109+ }
110+
111+ @Test
112+ fun `Directories should not be valid` () {
113+ val (file1, clm) = createValidVfContext(isDirectory = true )
114+
115+ val res = fGrep.validVf(file1, null , clm)
116+ assert (! res)
117+ }
118+
119+ @Test
120+ fun `Binary files should not be valid` () {
121+ val (file1, clm) = createValidVfContext(isBinary = true )
122+
123+ val res = fGrep.validVf(file1, null , clm)
124+ assert (! res)
125+ }
126+
127+ @Test
128+ fun `Ignored files should not be valid` () {
129+ val (file1, clm) = createValidVfContext(isIgnored = true )
130+
131+ val res = fGrep.validVf(file1, null , clm)
132+ assert (! res)
133+ }
134+
135+ @Test
136+ fun `null secondary field should be valid` () {
137+ val (file1, clm) = createValidVfContext()
138+
139+ val res = fGrep.validVf(file1, null , clm)
140+ assert (res)
141+ }
142+
143+ @Test
144+ fun `Matching secondary field should be valid` () {
145+ val (file1, clm) = createValidVfContext(extension = " kt" )
146+
147+ val res = fGrep.validVf(file1, " kt" , clm)
148+ assert (res)
149+ }
150+
151+ @Test
152+ fun `Non-matching secondary field should not be valid` () {
153+ val (file1, clm) = createValidVfContext(extension = " java" )
154+
155+ val res = fGrep.validVf(file1, " kt" , clm)
156+ assert (! res)
157+ }
158+
159+ @Test
160+ fun `findInFiles should skip backend when backend is null` () = runBlocking {
161+ val (project, _, _, clm) = createFindInFilesContext()
162+
163+ val model = fGrep.findInFiles(" needle" , project, clm, null )
164+
165+ assertNotNull(model)
166+ assertEquals(0 , model.size)
167+ }
168+
169+ @Test
170+ fun `findInFiles should skip backend when project base path is null` () = runBlocking {
171+ val (project, _, backend, clm) = createFindInFilesContext(projectBasePath = null )
172+
173+ val model = fGrep.findInFiles(" needle" , project, clm, backend)
174+
175+ assertNotNull(model)
176+ assertEquals(0 , model.size)
177+ }
178+ }
0 commit comments