package org.jabref.gui.journals; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import org.jabref.CatchExceptionsFromThread; import org.jabref.JabRefException; import org.jabref.gui.DialogService; import org.jabref.gui.util.CurrentThreadTaskExecutor; import org.jabref.gui.util.TaskExecutor; import org.jabref.logic.journals.Abbreviation; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.logic.journals.JournalAbbreviationPreferences; import org.jabref.preferences.PreferencesService; import org.assertj.core.util.Files; import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import static org.jabref.logic.util.OS.NEWLINE; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ManageJournalAbbreviationsViewModelTest { @ClassRule public static CatchExceptionsFromThread catchExceptions = new CatchExceptionsFromThread(); @Rule public TemporaryFolder tempFolder = new TemporaryFolder(); private ManageJournalAbbreviationsViewModel viewModel; private Path emptyTestFile; private Path testFile1Entries; private Path testFile3Entries; private Path testFile4Entries; private Path testFile5EntriesWithDuplicate; private JournalAbbreviationPreferences abbreviationPreferences; private DialogService dialogService; @Before public void setUpViewModel() throws Exception { abbreviationPreferences = mock(JournalAbbreviationPreferences.class); PreferencesService preferences = mock(PreferencesService.class); when(preferences.getJournalAbbreviationPreferences()).thenReturn(abbreviationPreferences); dialogService = mock(DialogService.class); TaskExecutor taskExecutor = new CurrentThreadTaskExecutor(); JournalAbbreviationLoader journalAbbreviationLoader = mock(JournalAbbreviationLoader.class); viewModel = new ManageJournalAbbreviationsViewModel(preferences, dialogService, taskExecutor, journalAbbreviationLoader); emptyTestFile = createTemporaryTestFile("emptyTestFile.txt", ""); testFile1Entries = createTemporaryTestFile("testFile1Entries.txt", "Test Entry = TE" + NEWLINE + ""); testFile3Entries = createTemporaryTestFile("testFile3Entries.txt", "Abbreviations = Abb" + NEWLINE + "Test Entry = TE" + NEWLINE + "MoreEntries = ME" + NEWLINE + ""); testFile4Entries = createTemporaryTestFile("testFile4Entries.txt", "Abbreviations = Abb" + NEWLINE + "Test Entry = TE" + NEWLINE + "MoreEntries = ME" + NEWLINE + "Entry = E" + NEWLINE + ""); testFile5EntriesWithDuplicate = createTemporaryTestFile("testFile5Entries.txt", "Abbreviations = Abb" + NEWLINE + "Test Entry = TE" + NEWLINE + "Test Entry = TE" + NEWLINE + "MoreEntries = ME" + NEWLINE + "EntryEntry = EE" + NEWLINE + ""); } @Test public void testInitialHasNoFilesAndNoAbbreviations() { Assert.assertEquals(viewModel.journalFilesProperty().size(), 0); Assert.assertEquals(viewModel.abbreviationsProperty().size(), 0); } @Test public void testInitialWithSavedFilesIncrementsFilesCounter() throws Exception { addFourTestFileToViewModelAndPreferences(); viewModel.createFileObjects(); Assert.assertEquals(4, viewModel.journalFilesProperty().size()); } @Test public void testRemoveDuplicatesWhenReadingFiles() throws Exception { addFourTestFileToViewModelAndPreferences(); viewModel.createFileObjects(); viewModel.selectLastJournalFile(); // should result in 4 real abbreviations and one pseudo abbreviation Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); } @Test public void addFileIncreasesCounterOfOpenFilesAndHasNoAbbreviations() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(emptyTestFile)); viewModel.addNewFile(); Assert.assertEquals(1, viewModel.journalFilesProperty().size()); Assert.assertEquals(1, viewModel.abbreviationsProperty().size()); } @Test public void addDuplicatedFileResultsInErrorDialog() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.addNewFile(); viewModel.addNewFile(); verify(dialogService).showErrorDialogAndWait(anyString(), anyString()); } @Test public void testOpenDuplicatedFileResultsInAnException() throws Exception { when(dialogService.showFileOpenDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.openFile(); viewModel.openFile(); verify(dialogService).showErrorDialogAndWait(anyString(), anyString()); } @Test public void testSelectLastJournalFileSwitchesFilesAndTheirAbbreviations() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(emptyTestFile)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Assert.assertEquals(1, viewModel.abbreviationsCountProperty().get()); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Assert.assertEquals(2, viewModel.abbreviationsCountProperty().get()); } @Test public void testOpenValidFileContainsTheSpecificEntryAndEnoughAbbreviations() throws Exception { Abbreviation testAbbreviation = new Abbreviation("Test Entry", "TE"); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Assert.assertEquals(1, viewModel.journalFilesProperty().size()); // our test file has 3 abbreviations and one pseudo abbreviation Assert.assertEquals(4, viewModel.abbreviationsProperty().size()); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); } @Test public void testRemoveLastListSetsCurrentFileAndCurrentAbbreviationToNull() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.addNewFile(); viewModel.removeCurrentFile(); Assert.assertEquals(0, viewModel.journalFilesProperty().size()); Assert.assertEquals(0, viewModel.abbreviationsProperty().size()); Assert.assertNull(viewModel.currentFileProperty().get()); Assert.assertNull(viewModel.currentAbbreviationProperty().get()); } @Test public void testMixedFileUsage() throws Exception { Abbreviation testAbbreviation = new Abbreviation("Entry", "E"); Abbreviation testAbbreviation2 = new Abbreviation("EntryEntry", "EE"); // simulate open file button twice when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); viewModel.currentFileProperty().set(viewModel.journalFilesProperty().get(1)); // size of the list of journal files should be incremented by two Assert.assertEquals(2, viewModel.journalFilesProperty().size()); // our second test file has 4 abbreviations Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); // check some abbreviation Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); // simulate add new file button when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(emptyTestFile)); viewModel.addNewFile(); viewModel.currentFileProperty().set(viewModel.journalFilesProperty().get(2)); // size of the list of journal files should be incremented by one Assert.assertEquals(3, viewModel.journalFilesProperty().size()); // a new file has zero abbreviations Assert.assertEquals(1, viewModel.abbreviationsProperty().size()); // simulate open file button when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.currentFileProperty().set(viewModel.journalFilesProperty().get(3)); // size of the list of journal files should be incremented by one Assert.assertEquals(4, viewModel.journalFilesProperty().size()); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); // check some abbreviation Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation2))); } @Test public void testBuiltInListsIncludeAllBuiltInAbbreviations() { when(abbreviationPreferences.useIEEEAbbreviations()).thenReturn(false); viewModel.addBuiltInLists(); Assert.assertEquals(2, viewModel.journalFilesProperty().getSize()); viewModel.currentFileProperty().set(viewModel.journalFilesProperty().get(0)); ObservableList<Abbreviation> expected = FXCollections .observableArrayList(JournalAbbreviationLoader.getBuiltInAbbreviations()); ObservableList<Abbreviation> actualAbbreviations = FXCollections .observableArrayList(viewModel.abbreviationsProperty().stream() .map(AbbreviationViewModel::getAbbreviationObject).collect(Collectors.toList())); Assert.assertEquals(expected, actualAbbreviations); } @Test public void testBuiltInListsStandardIEEEIncludesAllBuiltIEEEAbbreviations() throws Exception { when(abbreviationPreferences.useIEEEAbbreviations()).thenReturn(true); viewModel.addBuiltInLists(); viewModel.selectLastJournalFile(); Assert.assertEquals(2, viewModel.journalFilesProperty().getSize()); ObservableList<Abbreviation> expected = FXCollections .observableArrayList(JournalAbbreviationLoader.getOfficialIEEEAbbreviations()); ObservableList<Abbreviation> actualAbbreviations = FXCollections .observableArrayList(viewModel.abbreviationsProperty().stream() .map(AbbreviationViewModel::getAbbreviationObject).collect(Collectors.toList())); Assert.assertEquals(expected, actualAbbreviations); } @Test public void testcurrentFilePropertyChangeActiveFile() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); AbbreviationsFileViewModel test1 = viewModel.journalFilesProperty().get(0); AbbreviationsFileViewModel test3 = viewModel.journalFilesProperty().get(1); AbbreviationsFileViewModel test4 = viewModel.journalFilesProperty().get(2); AbbreviationsFileViewModel test5 = viewModel.journalFilesProperty().get(3); // test if the last opened file is active, but duplicated entry has been removed Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); viewModel.currentFileProperty().set(test1); // test if the current abbreviations matches with the ones in testFile1Entries Assert.assertEquals(2, viewModel.abbreviationsProperty().size()); viewModel.currentFileProperty().set(test3); Assert.assertEquals(4, viewModel.abbreviationsProperty().size()); viewModel.currentFileProperty().set(test1); Assert.assertEquals(2, viewModel.abbreviationsProperty().size()); viewModel.currentFileProperty().set(test4); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); viewModel.currentFileProperty().set(test5); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); } @Test public void testAddAbbreviationIncludesAbbreviationsInAbbreviationList() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Abbreviation testAbbreviation = new Abbreviation("YetAnotherEntry", "YAE"); addAbbrevaition(testAbbreviation); Assert.assertEquals(6, viewModel.abbreviationsProperty().size()); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); } @Test public void testAddDuplicatedAbbreviationResultsInException() throws JabRefException { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); viewModel.addAbbreviation("YetAnotherEntry", "YAE"); viewModel.addAbbreviation("YetAnotherEntry", "YAE"); verify(dialogService).showErrorDialogAndWait(anyString(), anyString()); } @Test public void testEditSameAbbreviationWithNoChangeDoesNotResultInException() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(emptyTestFile)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Abbreviation testAbbreviation = new Abbreviation("YetAnotherEntry", "YAE"); addAbbrevaition(testAbbreviation); editAbbreviation(testAbbreviation); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); } @Test public void testEditAbbreviationIncludesNewAbbreviationInAbbreviationsList() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); selectLastAbbreviation(); Abbreviation testAbbreviation = new Abbreviation("YetAnotherEntry", "YAE"); editAbbreviation(testAbbreviation); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(emptyTestFile)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); editAbbreviation(testAbbreviation); Assert.assertEquals(1, viewModel.abbreviationsProperty().size()); Assert.assertFalse(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); } @Test public void testEditAbbreviationToExistingOneResultsInException() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); selectLastAbbreviation(); Assert.assertEquals(4, viewModel.abbreviationsProperty().size()); viewModel.editAbbreviation("YetAnotherEntry", "YAE"); viewModel.currentAbbreviationProperty().set(viewModel.abbreviationsProperty().get(2)); viewModel.editAbbreviation("YetAnotherEntry", "YAE"); verify(dialogService).showErrorDialogAndWait(anyString(), anyString()); } @Test public void testEditAbbreviationToEmptyNameResultsInException() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); selectLastAbbreviation(); Assert.assertEquals(4, viewModel.abbreviationsProperty().size()); viewModel.editAbbreviation("", "YAE"); verify(dialogService).showErrorDialogAndWait(anyString()); } @Test public void testEditAbbreviationToEmptyAbbreviationResultsInException() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); selectLastAbbreviation(); Assert.assertEquals(4, viewModel.abbreviationsProperty().size()); viewModel.editAbbreviation("YetAnotherEntry", ""); verify(dialogService).showErrorDialogAndWait(anyString()); } @Test public void testDeleteAbbreviationSelectsPreviousOne() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Abbreviation testAbbreviation = new Abbreviation("YetAnotherEntry", "YAE"); addAbbrevaition(testAbbreviation); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); Assert.assertEquals(new AbbreviationViewModel(testAbbreviation), viewModel.currentAbbreviationProperty().get()); viewModel.deleteAbbreviation(); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); // check if the previous (the last) element is the current abbreviation Assert.assertEquals(viewModel.currentAbbreviationProperty().get(), viewModel.abbreviationsProperty().get(4)); } @Test public void testDeleteAbbreviationSelectsNextOne() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); Abbreviation testAbbreviation = new Abbreviation("YetAnotherEntry", "YAE"); addAbbrevaition(testAbbreviation); viewModel.currentAbbreviationProperty().set(viewModel.abbreviationsProperty().get(1)); viewModel.deleteAbbreviation(); Assert.assertEquals(new AbbreviationViewModel(testAbbreviation), viewModel.currentAbbreviationProperty().get()); } @Test public void testSaveAbbreviationsToFilesCreatesNewFilesWithWrittenAbbreviations() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); selectLastAbbreviation(); Abbreviation testAbbreviation = new Abbreviation("JabRefTestEntry", "JTE"); editAbbreviation(testAbbreviation); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation))); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.selectLastJournalFile(); selectLastAbbreviation(); viewModel.deleteAbbreviation(); Abbreviation testAbbreviation1 = new Abbreviation("SomeOtherEntry", "SOE"); addAbbrevaition(testAbbreviation1); Assert.assertEquals(5, viewModel.abbreviationsProperty().size()); Assert.assertTrue(viewModel.abbreviationsProperty().contains(new AbbreviationViewModel(testAbbreviation1))); viewModel.saveJournalAbbreviationFiles(); String expected = "Abbreviations = Abb" + NEWLINE + "Test Entry = TE" + NEWLINE + "MoreEntries = ME" + NEWLINE + "JabRefTestEntry = JTE" + NEWLINE + ""; String actual = Files.contentOf(testFile4Entries.toFile(), StandardCharsets.UTF_8); Assert.assertEquals(expected, actual); expected = "Abbreviations = Abb" + NEWLINE + "Test Entry = TE" + NEWLINE + "MoreEntries = ME" + NEWLINE + "SomeOtherEntry = SOE" + NEWLINE + ""; actual = Files.contentOf(testFile5EntriesWithDuplicate.toFile(), StandardCharsets.UTF_8); Assert.assertEquals(expected, actual); } @Test public void testSaveExternalFilesListToPreferences() throws Exception { addFourTestFileToViewModelAndPreferences(); List<String> expected = Stream.of(testFile1Entries, testFile3Entries, testFile4Entries, testFile5EntriesWithDuplicate) .map(Path::toString).collect(Collectors.toList()); verify(abbreviationPreferences).setExternalJournalLists(expected); } private Path createTemporaryTestFile(String name, String content) throws Exception { File testFile = tempFolder.newFile(name); try (OutputStream outputStream = new FileOutputStream(testFile)) { outputStream.write(content.getBytes(StandardCharsets.UTF_8)); } return testFile.toPath(); } private void addAbbrevaition(Abbreviation testAbbreviation) throws Exception { viewModel.addAbbreviation(testAbbreviation.getName(), testAbbreviation.getAbbreviation()); } private void editAbbreviation(Abbreviation testAbbreviation) throws Exception { viewModel.editAbbreviation(testAbbreviation.getName(), testAbbreviation.getAbbreviation()); } private void addFourTestFileToViewModelAndPreferences() throws Exception { when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile1Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile3Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile4Entries)); viewModel.addNewFile(); when(dialogService.showFileSaveDialog(any())).thenReturn(Optional.of(testFile5EntriesWithDuplicate)); viewModel.addNewFile(); viewModel.saveEverythingAndUpdateAutoCompleter(); } /** * Select the last abbreviation in the list of abbreviations */ private void selectLastAbbreviation() { viewModel.currentAbbreviationProperty() .set(viewModel.abbreviationsProperty().get(viewModel.abbreviationsCountProperty().get() - 1)); } }