diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d861b00206010f8f96215ac030dd448e54f0886b --- /dev/null +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java @@ -0,0 +1,265 @@ +package de.deadlocker8.budgetmaster.unit.database; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.accounts.AccountRepository; +import de.deadlocker8.budgetmaster.accounts.AccountService; +import de.deadlocker8.budgetmaster.accounts.AccountType; +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.categories.CategoryService; +import de.deadlocker8.budgetmaster.categories.CategoryType; +import de.deadlocker8.budgetmaster.charts.Chart; +import de.deadlocker8.budgetmaster.charts.ChartRepository; +import de.deadlocker8.budgetmaster.charts.ChartService; +import de.deadlocker8.budgetmaster.charts.ChartType; +import de.deadlocker8.budgetmaster.database.DatabaseParser; +import de.deadlocker8.budgetmaster.database.DatabaseService; +import de.deadlocker8.budgetmaster.database.InternalDatabase; +import de.deadlocker8.budgetmaster.database.JSONIdentifier; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.images.ImageFileExtension; +import de.deadlocker8.budgetmaster.images.ImageRepository; +import de.deadlocker8.budgetmaster.images.ImageService; +import de.deadlocker8.budgetmaster.repeating.RepeatingOption; +import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; +import de.deadlocker8.budgetmaster.settings.SettingsService; +import de.deadlocker8.budgetmaster.tags.Tag; +import de.deadlocker8.budgetmaster.tags.TagService; +import de.deadlocker8.budgetmaster.templates.Template; +import de.deadlocker8.budgetmaster.templates.TemplateRepository; +import de.deadlocker8.budgetmaster.templates.TemplateService; +import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.transactions.TransactionRepository; +import de.deadlocker8.budgetmaster.transactions.TransactionService; +import de.thecodelabs.utils.util.Localization; +import org.joda.time.DateTime; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +public class DatabaseExportTest +{ + @Before + public void before() + { + Localization.setDelegate(new Localization.LocalizationDelegate() + { + @Override + public Locale getLocale() + { + return Locale.ENGLISH; + } + + @Override + public String getBaseResource() + { + return "languages/base"; + } + }); + Localization.load(); + } + + @Mock + private AccountService accountService; + + @Mock + private CategoryService categoryService; + + @Mock + private TransactionService transactionService; + + @Mock + private TagService tagService; + + @Mock + private TemplateService templateService; + + @Mock + private ChartService chartService; + + @Mock + private SettingsService settingsService; + + @Mock + private ImageService imageService; + + @InjectMocks + private DatabaseService databaseService; + + @Rule + public final TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test + public void test_specialFields() throws IOException + { + // categories + Mockito.when(categoryService.getAllEntitiesAsc()).thenReturn(List.of()); + + // accounts + AccountRepository accountRepositoryMock = Mockito.mock(AccountRepository.class); + Mockito.when(accountRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(accountService.getRepository()).thenReturn(accountRepositoryMock); + + // transactions + TransactionRepository transactionRepositoryMock = Mockito.mock(TransactionRepository.class); + Mockito.when(transactionRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(transactionService.getRepository()).thenReturn(transactionRepositoryMock); + + // templates + TemplateRepository templateRepositoryMock = Mockito.mock(TemplateRepository.class); + Mockito.when(templateRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(templateService.getRepository()).thenReturn(templateRepositoryMock); + + // charts + ChartRepository chartRepositoryMock = Mockito.mock(ChartRepository.class); + Mockito.when(chartRepositoryMock.findAllByType(Mockito.any())).thenReturn(List.of()); + Mockito.when(chartService.getRepository()).thenReturn(chartRepositoryMock); + + // images + ImageRepository imageRepositoryMock = Mockito.mock(ImageRepository.class); + Mockito.when(imageRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(imageService.getRepository()).thenReturn(imageRepositoryMock); + + + // act + Path exportPath = tempFolder.newFile("exportTest.json").toPath(); + databaseService.exportDatabase(exportPath); + + + // assert + String fileContent = Files.readString(exportPath, StandardCharsets.UTF_8); + JsonObject root = JsonParser.parseString(fileContent).getAsJsonObject(); + + assertThat(root.get("TYPE").getAsString()).isEqualTo(JSONIdentifier.BUDGETMASTER_DATABASE.toString()); + assertThat(root.get("VERSION").getAsInt()).isEqualTo(5); + } + + @Test + public void test_exportDatabase() throws IOException + { + // categories + Category categoryNone = new Category("NONE", "#000000", CategoryType.NONE); + Category categoryCustom = new Category("my First Category", "#FF0000", CategoryType.CUSTOM); + Mockito.when(categoryService.getAllEntitiesAsc()).thenReturn(List.of(categoryNone, categoryCustom)); + + // accounts + Account account1 = new Account("Source_Account_1", AccountType.CUSTOM); + account1.setID(2); + Account account2 = new Account("Source_Account_2", AccountType.CUSTOM); + account2.setID(3); + + AccountRepository accountRepositoryMock = Mockito.mock(AccountRepository.class); + Mockito.when(accountRepositoryMock.findAll()).thenReturn(List.of(account1, account2)); + Mockito.when(accountService.getRepository()).thenReturn(accountRepositoryMock); + + // tags + Tag tag1 = new Tag("Car"); + List<Tag> tags = new ArrayList<>(); + tags.add(tag1); + + // transactions + Transaction transaction1 = new Transaction(); + transaction1.setAccount(account1); + transaction1.setCategory(categoryNone); + transaction1.setName("ShouldGoInAccount_1"); + transaction1.setAmount(200); + transaction1.setIsExpenditure(false); + transaction1.setDate(new DateTime(2018, 10, 3, 12, 0, 0, 0)); + transaction1.setTags(tags); + + Transaction transaction2 = new Transaction(); + transaction2.setAccount(account2); + transaction2.setCategory(categoryCustom); + transaction2.setName("ImPartOfAccount_2"); + transaction2.setAmount(-525); + transaction2.setIsExpenditure(true); + DateTime transaction2Date = new DateTime(2018, 10, 3, 12, 0, 0, 0); + transaction2.setDate(transaction2Date); + transaction2.setTags(new ArrayList<>()); + RepeatingOption repeatingOption = new RepeatingOption(transaction2Date, + new RepeatingModifierDays(3), + new RepeatingEndAfterXTimes(3)); + transaction2.setRepeatingOption(repeatingOption); + + TransactionRepository transactionRepositoryMock = Mockito.mock(TransactionRepository.class); + Mockito.when(transactionRepositoryMock.findAll()).thenReturn(List.of(transaction1, transaction2)); + Mockito.when(transactionService.getRepository()).thenReturn(transactionRepositoryMock); + + // templates + Template template1 = new Template(); + template1.setTemplateName("MyTemplate"); + template1.setAmount(1500); + template1.setIsExpenditure(false); + template1.setAccount(account1); + template1.setName("Transaction from Template"); + List<Tag> tags2 = new ArrayList<>(); + tags2.add(tag1); + template1.setTags(tags2); + + Template template2 = new Template(); + template2.setTemplateName("MyTemplate2"); + template2.setTransferAccount(account2); + template2.setIsExpenditure(true); + template2.setTags(new ArrayList<>()); + + TemplateRepository templateRepositoryMock = Mockito.mock(TemplateRepository.class); + Mockito.when(templateRepositoryMock.findAll()).thenReturn(List.of(template1, template2)); + Mockito.when(templateService.getRepository()).thenReturn(templateRepositoryMock); + + // charts + Chart chart = new Chart(); + chart.setID(9); + chart.setName("The best chart"); + chart.setType(ChartType.CUSTOM); + chart.setVersion(7); + chart.setScript("/* This list will be dynamically filled with all the transactions between\r\n* the start and and date you select on the \"Show Chart\" page\r\n* and filtered according to your specified filter.\r\n* An example entry for this list and tutorial about how to create custom charts ca be found in the BudgetMaster wiki:\r\n* https://github.com/deadlocker8/BudgetMaster/wiki/How-to-create-custom-charts\r\n*/\r\nvar transactionData \u003d [];\r\n\r\n// Prepare your chart settings here (mandatory)\r\nvar plotlyData \u003d [{\r\n x: [],\r\n y: [],\r\n type: \u0027bar\u0027\r\n}];\r\n\r\n// Add your Plotly layout settings here (optional)\r\nvar plotlyLayout \u003d {};\r\n\r\n// Add your Plotly configuration settings here (optional)\r\nvar plotlyConfig \u003d {\r\n showSendToCloud: false,\r\n displaylogo: false,\r\n showLink: false,\r\n responsive: true\r\n};\r\n\r\n// Don\u0027t touch this line\r\nPlotly.newPlot(\"containerID\", plotlyData, plotlyLayout, plotlyConfig);\r\n"); + + ChartRepository chartRepositoryMock = Mockito.mock(ChartRepository.class); + Mockito.when(chartRepositoryMock.findAllByType(Mockito.any())).thenReturn(List.of(chart)); + Mockito.when(chartService.getRepository()).thenReturn(chartRepositoryMock); + + // images + final Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + image.setID(12); + + ImageRepository imageRepositoryMock = Mockito.mock(ImageRepository.class); + Mockito.when(imageRepositoryMock.findAll()).thenReturn(List.of(image)); + Mockito.when(imageService.getRepository()).thenReturn(imageRepositoryMock); + + + // act + Path exportPath = tempFolder.newFile("exportTest.json").toPath(); + databaseService.exportDatabase(exportPath); + + // assert + String fileContent = Files.readString(exportPath, StandardCharsets.UTF_8); + DatabaseParser importer = new DatabaseParser(fileContent); + InternalDatabase importedDatabase = importer.parseDatabaseFromJSON(); + + assertThat(importedDatabase.getCategories()).containsExactly(categoryNone, categoryCustom); + assertThat(importedDatabase.getAccounts()).containsExactly(account1, account2); + assertThat(importedDatabase.getTransactions()).containsExactly(transaction1, transaction2); + assertThat(importedDatabase.getTemplates()).containsExactly(template1, template2); + assertThat(importedDatabase.getCharts()).containsExactly(chart); + assertThat(importedDatabase.getImages()).containsExactly(image); + } +}