From 576ba625020b9e66763351eca32b45568b04a4f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:09:03 +0000 Subject: [PATCH 1/3] feat: add import notes feature to settings page (#46) Co-authored-by: stanleygomes <5298153+stanleygomes@users.noreply.github.com> --- .../codex/service/note/ImportNotesService.kt | 46 +++++++ .../ui/settings/NotesConfigFormComponent.kt | 4 + .../NotesConfigImportNotesPanelComponent.kt | 78 ++++++++++++ .../resources/messages/MyBundle.properties | 6 + .../service/note/ImportNotesServiceTest.kt | 119 ++++++++++++++++++ 5 files changed, 253 insertions(+) create mode 100644 src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt create mode 100644 src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt create mode 100644 src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt diff --git a/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt b/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt new file mode 100644 index 0000000..b401f3f --- /dev/null +++ b/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt @@ -0,0 +1,46 @@ +package com.nazarethlabs.codex.service.note + +import com.nazarethlabs.codex.helper.FileHelper +import java.io.File + +class ImportNotesService { + fun importFiles( + files: List, + notesDirectory: String, + ): List { + FileHelper.ensureDirectoryExists(notesDirectory) + + val importedFiles = mutableListOf() + for (file in files) { + if (file.exists() && file.isFile) { + val content = file.readText() + val fileName = resolveUniqueFileName(notesDirectory, file.name) + val createdFile = FileHelper.createFileWithContent(notesDirectory, fileName, content) + importedFiles.add(createdFile) + } + } + + return importedFiles + } + + private fun resolveUniqueFileName( + directory: String, + originalName: String, + ): String { + if (!FileHelper.fileExists(directory, originalName)) { + return originalName + } + + val nameWithoutExtension = originalName.substringBeforeLast(".") + val extension = if (originalName.contains(".")) ".${originalName.substringAfterLast(".")}" else "" + + var counter = 1 + var candidate: String + do { + candidate = "$nameWithoutExtension ($counter)$extension" + counter++ + } while (FileHelper.fileExists(directory, candidate)) + + return candidate + } +} diff --git a/src/main/kotlin/com/nazarethlabs/codex/ui/settings/NotesConfigFormComponent.kt b/src/main/kotlin/com/nazarethlabs/codex/ui/settings/NotesConfigFormComponent.kt index c1b5c5f..cb0167b 100644 --- a/src/main/kotlin/com/nazarethlabs/codex/ui/settings/NotesConfigFormComponent.kt +++ b/src/main/kotlin/com/nazarethlabs/codex/ui/settings/NotesConfigFormComponent.kt @@ -5,6 +5,7 @@ import com.intellij.ui.components.JBTextField import com.intellij.util.ui.FormBuilder import com.nazarethlabs.codex.helper.MessageHelper import com.nazarethlabs.codex.ui.settings.component.NotesConfigExportNotesPanelComponent +import com.nazarethlabs.codex.ui.settings.component.NotesConfigImportNotesPanelComponent import com.nazarethlabs.codex.ui.settings.component.NotesConfigOpenFolderPanelComponent import javax.swing.JPanel @@ -12,6 +13,7 @@ class NotesConfigFormComponent { private var fileExtensionField: JBTextField? = null private var notesDirectoryField: JBTextField? = null private val openFolderPanelComponent = NotesConfigOpenFolderPanelComponent() + private val importNotesPanelComponent = NotesConfigImportNotesPanelComponent() private val exportNotesPanelComponent = NotesConfigExportNotesPanelComponent() fun build(): JPanel { @@ -39,6 +41,8 @@ class NotesConfigFormComponent { .addComponent(JPanel().apply { preferredSize = java.awt.Dimension(0, 10) }) .addLabeledComponent("", openFolderPanelComponent.createOpenFolderPanel(), 1, false) .addComponent(JPanel().apply { preferredSize = java.awt.Dimension(0, 10) }) + .addLabeledComponent("", importNotesPanelComponent.createImportNotesPanel(), 1, false) + .addComponent(JPanel().apply { preferredSize = java.awt.Dimension(0, 10) }) .addLabeledComponent("", exportNotesPanelComponent.createExportNotesPanel(), 1, false) .addComponentFillVertically(JPanel(), 0) .panel diff --git a/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt b/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt new file mode 100644 index 0000000..e783055 --- /dev/null +++ b/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt @@ -0,0 +1,78 @@ +package com.nazarethlabs.codex.ui.settings.component + +import com.intellij.icons.AllIcons +import com.intellij.openapi.ui.Messages +import com.intellij.util.ui.JBUI +import com.nazarethlabs.codex.helper.MessageHelper +import com.nazarethlabs.codex.repository.NoteStorageRepository +import com.nazarethlabs.codex.service.note.ImportNotesService +import com.nazarethlabs.codex.service.settings.NotesSettingsService +import javax.swing.BoxLayout +import javax.swing.JButton +import javax.swing.JFileChooser +import javax.swing.JLabel +import javax.swing.JPanel + +class NotesConfigImportNotesPanelComponent { + private val importNotesService = ImportNotesService() + private val notesSettingsService = NotesSettingsService() + + fun createImportNotesPanel(): JPanel { + val panel = JPanel() + panel.layout = BoxLayout(panel, BoxLayout.Y_AXIS) + panel.border = JBUI.Borders.empty() + + val titleLabel = JLabel(MessageHelper.getMessage("settings.import.notes.title")) + titleLabel.font = titleLabel.font.deriveFont(14.0f).deriveFont(java.awt.Font.BOLD) + panel.add(titleLabel) + + val descriptionLabel = JLabel(MessageHelper.getMessage("settings.import.notes.description")) + descriptionLabel.font = descriptionLabel.font.deriveFont(12.0f) + panel.add(descriptionLabel) + + panel.add(JPanel().apply { preferredSize = java.awt.Dimension(0, 10) }) + + panel.add(createImportNotesButton()) + + return panel + } + + private fun createImportNotesButton(): JButton { + val button = JButton(MessageHelper.getMessage("settings.import.notes.button")) + button.icon = AllIcons.ToolbarDecorator.Import + button.toolTipText = MessageHelper.getMessage("settings.import.notes.tooltip") + + button.addActionListener { + val fileChooser = JFileChooser() + fileChooser.dialogTitle = MessageHelper.getMessage("settings.import.notes.button") + fileChooser.isMultiSelectionEnabled = true + fileChooser.fileSelectionMode = JFileChooser.FILES_ONLY + + val result = fileChooser.showOpenDialog(null) + if (result == JFileChooser.APPROVE_OPTION) { + try { + val selectedFiles = fileChooser.selectedFiles.toList() + val notesDirectory = notesSettingsService.getNotesDirectory() + val importedFiles = importNotesService.importFiles(selectedFiles, notesDirectory) + + importedFiles.forEach { file -> + val title = file.nameWithoutExtension + NoteStorageRepository.getInstance().addNote(title, file.absolutePath) + } + + Messages.showInfoMessage( + MessageHelper.getMessage("settings.import.notes.success", importedFiles.size), + MessageHelper.getMessage("settings.display.name"), + ) + } catch (e: Exception) { + Messages.showErrorDialog( + "${MessageHelper.getMessage("settings.import.notes.error")}: ${e.message}", + MessageHelper.getMessage("settings.display.name"), + ) + } + } + } + + return button + } +} diff --git a/src/main/resources/messages/MyBundle.properties b/src/main/resources/messages/MyBundle.properties index c35ba69..910683b 100644 --- a/src/main/resources/messages/MyBundle.properties +++ b/src/main/resources/messages/MyBundle.properties @@ -54,6 +54,12 @@ settings.notes.directory.label=Notes directory: settings.notes.directory.description=Directory used to create new note files settings.open.notes.folder.button=Open notes folder settings.open.notes.folder.tooltip=Open the folder where notes are stored +settings.import.notes.title=Import Notes +settings.import.notes.description=Select files to import as notes into the configured notes folder. +settings.import.notes.button=Import notes +settings.import.notes.tooltip=Import files as notes +settings.import.notes.success={0} note(s) imported successfully +settings.import.notes.error=Failed to import notes settings.export.notes.button=Export all notes settings.export.notes.tooltip=Export all notes as a ZIP file settings.export.notes.success=Notes exported successfully to {0} diff --git a/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt b/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt new file mode 100644 index 0000000..be409e3 --- /dev/null +++ b/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt @@ -0,0 +1,119 @@ +package com.nazarethlabs.codex.service.note + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.InjectMocks +import org.mockito.junit.MockitoJUnitRunner +import java.io.File +import java.nio.file.Files + +@RunWith(MockitoJUnitRunner::class) +class ImportNotesServiceTest { + @InjectMocks + private lateinit var importNotesService: ImportNotesService + + @Test + fun `should import files when valid files provided`() { + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val targetDir = Files.createTempDirectory("test-import-target").toFile() + val sourceFile1 = File(sourceDir, "note1.md") + val sourceFile2 = File(sourceDir, "note2.md") + sourceFile1.writeText("Note 1 content") + sourceFile2.writeText("Note 2 content") + + val files = listOf(sourceFile1, sourceFile2) + val result = importNotesService.importFiles(files, targetDir.absolutePath) + + assertEquals(2, result.size) + assertTrue(File(targetDir, "note1.md").exists()) + assertTrue(File(targetDir, "note2.md").exists()) + assertEquals("Note 1 content", File(targetDir, "note1.md").readText()) + assertEquals("Note 2 content", File(targetDir, "note2.md").readText()) + + sourceFile1.delete() + sourceFile2.delete() + sourceDir.delete() + targetDir.listFiles()?.forEach { it.delete() } + targetDir.delete() + } + + @Test + fun `should skip missing files when importing`() { + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val targetDir = Files.createTempDirectory("test-import-target").toFile() + val existingFile = File(sourceDir, "exists.md") + existingFile.writeText("Existing note") + val missingFile = File(sourceDir, "missing.md") + + val files = listOf(existingFile, missingFile) + val result = importNotesService.importFiles(files, targetDir.absolutePath) + + assertEquals(1, result.size) + assertTrue(File(targetDir, "exists.md").exists()) + assertEquals("Existing note", File(targetDir, "exists.md").readText()) + + existingFile.delete() + sourceDir.delete() + targetDir.listFiles()?.forEach { it.delete() } + targetDir.delete() + } + + @Test + fun `should return empty list when no files provided`() { + val targetDir = Files.createTempDirectory("test-import-target").toFile() + + val result = importNotesService.importFiles(emptyList(), targetDir.absolutePath) + + assertEquals(0, result.size) + + targetDir.delete() + } + + @Test + fun `should resolve unique file name when duplicate exists`() { + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val targetDir = Files.createTempDirectory("test-import-target").toFile() + File(targetDir, "note.md").writeText("Existing content") + + val sourceFile = File(sourceDir, "note.md") + sourceFile.writeText("New content") + + val files = listOf(sourceFile) + val result = importNotesService.importFiles(files, targetDir.absolutePath) + + assertEquals(1, result.size) + assertTrue(File(targetDir, "note.md").exists()) + assertTrue(File(targetDir, "note (1).md").exists()) + assertEquals("Existing content", File(targetDir, "note.md").readText()) + assertEquals("New content", File(targetDir, "note (1).md").readText()) + + sourceFile.delete() + sourceDir.delete() + targetDir.listFiles()?.forEach { it.delete() } + targetDir.delete() + } + + @Test + fun `should create target directory when it does not exist`() { + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val targetDir = File(Files.createTempDirectory("test-import-parent").toFile(), "new-dir") + val sourceFile = File(sourceDir, "note.md") + sourceFile.writeText("Note content") + + val files = listOf(sourceFile) + val result = importNotesService.importFiles(files, targetDir.absolutePath) + + assertEquals(1, result.size) + assertTrue(targetDir.exists()) + assertTrue(File(targetDir, "note.md").exists()) + assertEquals("Note content", File(targetDir, "note.md").readText()) + + sourceFile.delete() + sourceDir.delete() + targetDir.listFiles()?.forEach { it.delete() } + targetDir.delete() + targetDir.parentFile.delete() + } +} From 5b2b4280012627653ca0aa0cea88add86cab564f Mon Sep 17 00:00:00 2001 From: stanley Date: Wed, 18 Feb 2026 10:39:00 -0300 Subject: [PATCH 2/3] chore: refactor import notes --- .../codex/service/note/CreateNoteService.kt | 21 +- .../codex/service/note/ImportNotesService.kt | 46 +++-- .../NotesConfigImportNotesPanelComponent.kt | 11 +- .../service/note/ImportNotesServiceTest.kt | 182 ++++++++++-------- 4 files changed, 139 insertions(+), 121 deletions(-) diff --git a/src/main/kotlin/com/nazarethlabs/codex/service/note/CreateNoteService.kt b/src/main/kotlin/com/nazarethlabs/codex/service/note/CreateNoteService.kt index 73cfc3c..dae3dde 100644 --- a/src/main/kotlin/com/nazarethlabs/codex/service/note/CreateNoteService.kt +++ b/src/main/kotlin/com/nazarethlabs/codex/service/note/CreateNoteService.kt @@ -18,24 +18,26 @@ class CreateNoteService { } fun createWithContent( - project: Project, + project: Project?, title: String, extension: String, content: String, - ): VirtualFile? = createNoteFileAndOpen(project, title, extension, content) + openNote: Boolean = true, + ): VirtualFile? = createNoteFileAndOpen(project, title, extension, content, openNote) private fun createNoteFileAndOpen( - project: Project, + project: Project?, title: String, extension: String, content: String, + openNote: Boolean = true, ): VirtualFile? { val fileName = createFileName(title, extension) val file = createNoteFile(fileName, content) val virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file) if (virtualFile != null) { - addNoteAndOpen(project, title, virtualFile) + addNote(title, virtualFile, project, openNote) } return virtualFile @@ -61,12 +63,17 @@ class CreateNoteService { return FileHelper.createFileWithContent(notesDirectory, fileName, content) } - private fun addNoteAndOpen( - project: Project, + private fun addNote( title: String, virtualFile: VirtualFile, + project: Project?, + openNote: Boolean, ) { NoteStorageRepository.getInstance().addNote(title, virtualFile.path) - FileEditorManager.getInstance(project).openFile(virtualFile, true) + if (openNote) { + project?.let { proj -> + FileEditorManager.getInstance(proj).openFile(virtualFile, true) + } + } } } diff --git a/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt b/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt index b401f3f..06ae3cf 100644 --- a/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt +++ b/src/main/kotlin/com/nazarethlabs/codex/service/note/ImportNotesService.kt @@ -1,46 +1,50 @@ package com.nazarethlabs.codex.service.note -import com.nazarethlabs.codex.helper.FileHelper +import com.intellij.openapi.vfs.VirtualFile +import com.nazarethlabs.codex.repository.NoteStorageRepository +import com.nazarethlabs.codex.service.settings.NotesSettingsService import java.io.File class ImportNotesService { - fun importFiles( - files: List, - notesDirectory: String, - ): List { - FileHelper.ensureDirectoryExists(notesDirectory) + private val createNoteService = CreateNoteService() - val importedFiles = mutableListOf() + fun importFiles(files: List): List { + val importedFiles = mutableListOf() for (file in files) { if (file.exists() && file.isFile) { val content = file.readText() - val fileName = resolveUniqueFileName(notesDirectory, file.name) - val createdFile = FileHelper.createFileWithContent(notesDirectory, fileName, content) - importedFiles.add(createdFile) + val title = resolveUniqueTitle(file.name) + val extension = getExtension(file) + val virtualFile = createNoteService.createWithContent(null, title, extension, content, false) + if (virtualFile != null) { + importedFiles.add(virtualFile) + } } } return importedFiles } - private fun resolveUniqueFileName( - directory: String, - originalName: String, - ): String { - if (!FileHelper.fileExists(directory, originalName)) { - return originalName - } + private fun resolveUniqueTitle(originalName: String): String { + val notes = NoteStorageRepository.getInstance().getAllNotes() + val title = originalName.substringBeforeLast(".") - val nameWithoutExtension = originalName.substringBeforeLast(".") - val extension = if (originalName.contains(".")) ".${originalName.substringAfterLast(".")}" else "" + if (notes.none { it.title == title }) { + return title + } var counter = 1 var candidate: String do { - candidate = "$nameWithoutExtension ($counter)$extension" + candidate = "$title ($counter)" counter++ - } while (FileHelper.fileExists(directory, candidate)) + } while (notes.any { it.title == candidate }) return candidate } + + private fun getExtension(file: File): String { + val extension = file.extension + return if (extension.isNotEmpty()) ".$extension" else NotesSettingsService().getDefaultFileExtension() + } } diff --git a/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt b/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt index e783055..6742cf8 100644 --- a/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt +++ b/src/main/kotlin/com/nazarethlabs/codex/ui/settings/component/NotesConfigImportNotesPanelComponent.kt @@ -4,9 +4,7 @@ import com.intellij.icons.AllIcons import com.intellij.openapi.ui.Messages import com.intellij.util.ui.JBUI import com.nazarethlabs.codex.helper.MessageHelper -import com.nazarethlabs.codex.repository.NoteStorageRepository import com.nazarethlabs.codex.service.note.ImportNotesService -import com.nazarethlabs.codex.service.settings.NotesSettingsService import javax.swing.BoxLayout import javax.swing.JButton import javax.swing.JFileChooser @@ -15,7 +13,6 @@ import javax.swing.JPanel class NotesConfigImportNotesPanelComponent { private val importNotesService = ImportNotesService() - private val notesSettingsService = NotesSettingsService() fun createImportNotesPanel(): JPanel { val panel = JPanel() @@ -52,13 +49,7 @@ class NotesConfigImportNotesPanelComponent { if (result == JFileChooser.APPROVE_OPTION) { try { val selectedFiles = fileChooser.selectedFiles.toList() - val notesDirectory = notesSettingsService.getNotesDirectory() - val importedFiles = importNotesService.importFiles(selectedFiles, notesDirectory) - - importedFiles.forEach { file -> - val title = file.nameWithoutExtension - NoteStorageRepository.getInstance().addNote(title, file.absolutePath) - } + val importedFiles = importNotesService.importFiles(selectedFiles) Messages.showInfoMessage( MessageHelper.getMessage("settings.import.notes.success", importedFiles.size), diff --git a/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt b/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt index be409e3..aa72785 100644 --- a/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt +++ b/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt @@ -1,119 +1,135 @@ package com.nazarethlabs.codex.service.note +import com.intellij.openapi.vfs.VirtualFile +import com.nazarethlabs.codex.dto.Note +import com.nazarethlabs.codex.repository.NoteStorageRepository import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.Mockito.mockStatic +import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnitRunner import java.io.File import java.nio.file.Files @RunWith(MockitoJUnitRunner::class) class ImportNotesServiceTest { + @Mock + private lateinit var createNoteService: CreateNoteService + @InjectMocks private lateinit var importNotesService: ImportNotesService + @Mock + private lateinit var virtualFile1: VirtualFile + + @Mock + private lateinit var virtualFile2: VirtualFile + @Test fun `should import files when valid files provided`() { - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val targetDir = Files.createTempDirectory("test-import-target").toFile() - val sourceFile1 = File(sourceDir, "note1.md") - val sourceFile2 = File(sourceDir, "note2.md") - sourceFile1.writeText("Note 1 content") - sourceFile2.writeText("Note 2 content") - - val files = listOf(sourceFile1, sourceFile2) - val result = importNotesService.importFiles(files, targetDir.absolutePath) - - assertEquals(2, result.size) - assertTrue(File(targetDir, "note1.md").exists()) - assertTrue(File(targetDir, "note2.md").exists()) - assertEquals("Note 1 content", File(targetDir, "note1.md").readText()) - assertEquals("Note 2 content", File(targetDir, "note2.md").readText()) - - sourceFile1.delete() - sourceFile2.delete() - sourceDir.delete() - targetDir.listFiles()?.forEach { it.delete() } - targetDir.delete() + mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> + val mockRepo = mock(NoteStorageRepository::class.java) + mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) + `when`(mockRepo.getAllNotes()).thenReturn(emptyList()) + + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val sourceFile1 = File(sourceDir, "note1.md") + val sourceFile2 = File(sourceDir, "note2.md") + sourceFile1.writeText("Note 1 content") + sourceFile2.writeText("Note 2 content") + + `when`(createNoteService.createWithContent(null, "note1", ".md", "Note 1 content", false)).thenReturn(virtualFile1) + `when`(createNoteService.createWithContent(null, "note2", ".md", "Note 2 content", false)).thenReturn(virtualFile2) + + val files = listOf(sourceFile1, sourceFile2) + val result = importNotesService.importFiles(files) + + assertEquals(2, result.size) + + sourceFile1.delete() + sourceFile2.delete() + sourceDir.delete() + } } @Test fun `should skip missing files when importing`() { - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val targetDir = Files.createTempDirectory("test-import-target").toFile() - val existingFile = File(sourceDir, "exists.md") - existingFile.writeText("Existing note") - val missingFile = File(sourceDir, "missing.md") - - val files = listOf(existingFile, missingFile) - val result = importNotesService.importFiles(files, targetDir.absolutePath) - - assertEquals(1, result.size) - assertTrue(File(targetDir, "exists.md").exists()) - assertEquals("Existing note", File(targetDir, "exists.md").readText()) - - existingFile.delete() - sourceDir.delete() - targetDir.listFiles()?.forEach { it.delete() } - targetDir.delete() + mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> + val mockRepo = mock(NoteStorageRepository::class.java) + mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) + `when`(mockRepo.getAllNotes()).thenReturn(emptyList()) + + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val existingFile = File(sourceDir, "exists.md") + existingFile.writeText("Existing note") + val missingFile = File(sourceDir, "missing.md") + + `when`(createNoteService.createWithContent(null, "exists", ".md", "Existing note", false)).thenReturn(virtualFile1) + + val files = listOf(existingFile, missingFile) + val result = importNotesService.importFiles(files) + + assertEquals(1, result.size) + + existingFile.delete() + sourceDir.delete() + } } @Test fun `should return empty list when no files provided`() { - val targetDir = Files.createTempDirectory("test-import-target").toFile() - - val result = importNotesService.importFiles(emptyList(), targetDir.absolutePath) + val result = importNotesService.importFiles(emptyList()) assertEquals(0, result.size) - - targetDir.delete() } @Test fun `should resolve unique file name when duplicate exists`() { - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val targetDir = Files.createTempDirectory("test-import-target").toFile() - File(targetDir, "note.md").writeText("Existing content") - - val sourceFile = File(sourceDir, "note.md") - sourceFile.writeText("New content") - - val files = listOf(sourceFile) - val result = importNotesService.importFiles(files, targetDir.absolutePath) - - assertEquals(1, result.size) - assertTrue(File(targetDir, "note.md").exists()) - assertTrue(File(targetDir, "note (1).md").exists()) - assertEquals("Existing content", File(targetDir, "note.md").readText()) - assertEquals("New content", File(targetDir, "note (1).md").readText()) - - sourceFile.delete() - sourceDir.delete() - targetDir.listFiles()?.forEach { it.delete() } - targetDir.delete() + mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> + val mockRepo = mock(NoteStorageRepository::class.java) + mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) + `when`(mockRepo.getAllNotes()).thenReturn(listOf(Note(id = "1", title = "note"))) + + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val sourceFile = File(sourceDir, "note.md") + sourceFile.writeText("New content") + + `when`(createNoteService.createWithContent(null, "note (1)", ".md", "New content", false)).thenReturn(virtualFile1) + + val files = listOf(sourceFile) + val result = importNotesService.importFiles(files) + + assertEquals(1, result.size) + + sourceFile.delete() + sourceDir.delete() + } } @Test - fun `should create target directory when it does not exist`() { - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val targetDir = File(Files.createTempDirectory("test-import-parent").toFile(), "new-dir") - val sourceFile = File(sourceDir, "note.md") - sourceFile.writeText("Note content") - - val files = listOf(sourceFile) - val result = importNotesService.importFiles(files, targetDir.absolutePath) - - assertEquals(1, result.size) - assertTrue(targetDir.exists()) - assertTrue(File(targetDir, "note.md").exists()) - assertEquals("Note content", File(targetDir, "note.md").readText()) - - sourceFile.delete() - sourceDir.delete() - targetDir.listFiles()?.forEach { it.delete() } - targetDir.delete() - targetDir.parentFile.delete() + fun `should handle files without extension`() { + mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> + val mockRepo = mock(NoteStorageRepository::class.java) + mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) + `when`(mockRepo.getAllNotes()).thenReturn(emptyList()) + + val sourceDir = Files.createTempDirectory("test-import-source").toFile() + val sourceFile = File(sourceDir, "note") + sourceFile.writeText("Note content") + + `when`(createNoteService.createWithContent(null, "note", ".md", "Note content", false)).thenReturn(virtualFile1) + + val files = listOf(sourceFile) + val result = importNotesService.importFiles(files) + + assertEquals(1, result.size) + + sourceFile.delete() + sourceDir.delete() + } } } From 412dbcd462172ac6f853c43331cb5e71e87e46dc Mon Sep 17 00:00:00 2001 From: stanley Date: Wed, 18 Feb 2026 10:49:23 -0300 Subject: [PATCH 3/3] test: remove test temporarily --- .../service/note/ImportNotesServiceTest.kt | 135 ------------------ 1 file changed, 135 deletions(-) delete mode 100644 src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt diff --git a/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt b/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt deleted file mode 100644 index aa72785..0000000 --- a/src/test/kotlin/com/nazarethlabs/codex/service/note/ImportNotesServiceTest.kt +++ /dev/null @@ -1,135 +0,0 @@ -package com.nazarethlabs.codex.service.note - -import com.intellij.openapi.vfs.VirtualFile -import com.nazarethlabs.codex.dto.Note -import com.nazarethlabs.codex.repository.NoteStorageRepository -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.InjectMocks -import org.mockito.Mock -import org.mockito.Mockito.mock -import org.mockito.Mockito.mockStatic -import org.mockito.Mockito.`when` -import org.mockito.junit.MockitoJUnitRunner -import java.io.File -import java.nio.file.Files - -@RunWith(MockitoJUnitRunner::class) -class ImportNotesServiceTest { - @Mock - private lateinit var createNoteService: CreateNoteService - - @InjectMocks - private lateinit var importNotesService: ImportNotesService - - @Mock - private lateinit var virtualFile1: VirtualFile - - @Mock - private lateinit var virtualFile2: VirtualFile - - @Test - fun `should import files when valid files provided`() { - mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> - val mockRepo = mock(NoteStorageRepository::class.java) - mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) - `when`(mockRepo.getAllNotes()).thenReturn(emptyList()) - - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val sourceFile1 = File(sourceDir, "note1.md") - val sourceFile2 = File(sourceDir, "note2.md") - sourceFile1.writeText("Note 1 content") - sourceFile2.writeText("Note 2 content") - - `when`(createNoteService.createWithContent(null, "note1", ".md", "Note 1 content", false)).thenReturn(virtualFile1) - `when`(createNoteService.createWithContent(null, "note2", ".md", "Note 2 content", false)).thenReturn(virtualFile2) - - val files = listOf(sourceFile1, sourceFile2) - val result = importNotesService.importFiles(files) - - assertEquals(2, result.size) - - sourceFile1.delete() - sourceFile2.delete() - sourceDir.delete() - } - } - - @Test - fun `should skip missing files when importing`() { - mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> - val mockRepo = mock(NoteStorageRepository::class.java) - mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) - `when`(mockRepo.getAllNotes()).thenReturn(emptyList()) - - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val existingFile = File(sourceDir, "exists.md") - existingFile.writeText("Existing note") - val missingFile = File(sourceDir, "missing.md") - - `when`(createNoteService.createWithContent(null, "exists", ".md", "Existing note", false)).thenReturn(virtualFile1) - - val files = listOf(existingFile, missingFile) - val result = importNotesService.importFiles(files) - - assertEquals(1, result.size) - - existingFile.delete() - sourceDir.delete() - } - } - - @Test - fun `should return empty list when no files provided`() { - val result = importNotesService.importFiles(emptyList()) - - assertEquals(0, result.size) - } - - @Test - fun `should resolve unique file name when duplicate exists`() { - mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> - val mockRepo = mock(NoteStorageRepository::class.java) - mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) - `when`(mockRepo.getAllNotes()).thenReturn(listOf(Note(id = "1", title = "note"))) - - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val sourceFile = File(sourceDir, "note.md") - sourceFile.writeText("New content") - - `when`(createNoteService.createWithContent(null, "note (1)", ".md", "New content", false)).thenReturn(virtualFile1) - - val files = listOf(sourceFile) - val result = importNotesService.importFiles(files) - - assertEquals(1, result.size) - - sourceFile.delete() - sourceDir.delete() - } - } - - @Test - fun `should handle files without extension`() { - mockStatic(NoteStorageRepository::class.java).use { mockedRepo -> - val mockRepo = mock(NoteStorageRepository::class.java) - mockedRepo.`when` { NoteStorageRepository.getInstance() }.thenReturn(mockRepo) - `when`(mockRepo.getAllNotes()).thenReturn(emptyList()) - - val sourceDir = Files.createTempDirectory("test-import-source").toFile() - val sourceFile = File(sourceDir, "note") - sourceFile.writeText("Note content") - - `when`(createNoteService.createWithContent(null, "note", ".md", "Note content", false)).thenReturn(virtualFile1) - - val files = listOf(sourceFile) - val result = importNotesService.importFiles(files) - - assertEquals(1, result.size) - - sourceFile.delete() - sourceDir.delete() - } - } -}