From 19fff681d2b7965df9dd25513d01fa7eee5013a9 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 5 May 2018 13:53:12 +0200 Subject: [PATCH] Improve test coverage, mark as deprecated. --- app/Import/Specifics/RabobankDescription.php | 2 + app/Import/Specifics/SnsDescription.php | 2 + app/Import/Storage/ImportArrayStorage.php | 58 +-- app/Import/Storage/ImportStorage.php | 2 + app/Import/Storage/ImportSupport.php | 2 + .../Journal/JournalRepository.php | 17 + .../Journal/JournalRepositoryInterface.php | 9 + app/Repositories/Rule/RuleRepository.php | 21 + .../Rule/RuleRepositoryInterface.php | 9 + .../Configuration/Bunq/HaveAccounts.php | 1 + .../Configuration/ConfigurationInterface.php | 1 + .../Import/Configuration/File/Initial.php | 1 + app/Support/Import/Configuration/File/Map.php | 1 + .../Import/Configuration/File/Roles.php | 1 + .../Configuration/File/UploadConfig.php | 1 + .../Configuration/Spectre/HaveAccounts.php | 1 + .../Import/Information/BunqInformation.php | 1 + .../Information/InformationInterface.php | 1 + .../Import/FileProcessor/CsvProcessorTest.php | 346 ------------ .../Specifics/RabobankDescriptionTest.php | 38 +- .../Import/Specifics/SnsDescriptionTest.php | 72 +++ .../Import/Storage/ImportArrayStorageTest.php | 493 ++++++++++++++++++ 22 files changed, 701 insertions(+), 379 deletions(-) delete mode 100644 tests/Unit/Import/FileProcessor/CsvProcessorTest.php create mode 100644 tests/Unit/Import/Specifics/SnsDescriptionTest.php create mode 100644 tests/Unit/Import/Storage/ImportArrayStorageTest.php diff --git a/app/Import/Specifics/RabobankDescription.php b/app/Import/Specifics/RabobankDescription.php index b940239f2f..257d4ad719 100644 --- a/app/Import/Specifics/RabobankDescription.php +++ b/app/Import/Specifics/RabobankDescription.php @@ -30,6 +30,7 @@ use Log; class RabobankDescription implements SpecificInterface { /** + * @codeCoverageIgnore * @return string */ public static function getDescription(): string @@ -38,6 +39,7 @@ class RabobankDescription implements SpecificInterface } /** + * @codeCoverageIgnore * @return string */ public static function getName(): string diff --git a/app/Import/Specifics/SnsDescription.php b/app/Import/Specifics/SnsDescription.php index b79d16b9f5..56da5be773 100644 --- a/app/Import/Specifics/SnsDescription.php +++ b/app/Import/Specifics/SnsDescription.php @@ -28,6 +28,7 @@ namespace FireflyIII\Import\Specifics; class SnsDescription implements SpecificInterface { /** + * @codeCoverageIgnore * @return string */ public static function getDescription(): string @@ -36,6 +37,7 @@ class SnsDescription implements SpecificInterface } /** + * @codeCoverageIgnore * @return string */ public static function getName(): string diff --git a/app/Import/Storage/ImportArrayStorage.php b/app/Import/Storage/ImportArrayStorage.php index ac4c0d153c..040e6ca848 100644 --- a/app/Import/Storage/ImportArrayStorage.php +++ b/app/Import/Storage/ImportArrayStorage.php @@ -5,17 +5,18 @@ namespace FireflyIII\Import\Storage; use Carbon\Carbon; use DB; use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Factory\TransactionJournalFactory; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Helpers\Filter\InternalTransferFilter; use FireflyIII\Models\ImportJob; use FireflyIII\Models\Rule; use FireflyIII\Models\Transaction; -use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\TransactionRules\Processor; +use Illuminate\Database\QueryException; use Illuminate\Support\Collection; use Log; @@ -32,10 +33,10 @@ class ImportArrayStorage private $checkForTransfers = false; /** @var ImportJob */ private $importJob; - + /** @var JournalRepositoryInterface */ + private $journalRepos; /** @var ImportJobRepositoryInterface */ private $repository; - /** @var Collection */ private $transfers; @@ -52,6 +53,9 @@ class ImportArrayStorage $this->repository = app(ImportJobRepositoryInterface::class); $this->repository->setUser($importJob->user); + $this->journalRepos = app(JournalRepositoryInterface::class); + $this->journalRepos->setUser($importJob->user); + Log::debug('Constructed ImportArrayStorage()'); } @@ -128,7 +132,6 @@ class ImportArrayStorage $count++; } } - $count = 1; if ($count > 0) { $this->checkForTransfers = true; @@ -145,18 +148,10 @@ class ImportArrayStorage */ private function getRules(): Collection { - /** @var Collection $set */ - $set = Rule::distinct() - ->where('rules.user_id', $this->importJob->user_id) - ->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id') - ->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id') - ->where('rule_groups.active', 1) - ->where('rule_triggers.trigger_type', 'user_action') - ->where('rule_triggers.trigger_value', 'store-journal') - ->where('rules.active', 1) - ->orderBy('rule_groups.order', 'ASC') - ->orderBy('rules.order', 'ASC') - ->get(['rules.*', 'rule_groups.order']); + /** @var RuleRepositoryInterface $repository */ + $repository = app(RuleRepositoryInterface::class); + $repository->setUser($this->importJob->user); + $set = $repository->getForImport(); Log::debug(sprintf('Found %d user rules.', $set->count())); @@ -190,17 +185,12 @@ class ImportArrayStorage { $json = json_encode($transaction); if ($json === false) { - throw new FireflyException('Could not encode import array. Please see the logs.', $transaction); + throw new FireflyException('Could not encode import array. Please see the logs.', $transaction); // @codeCoverageIgnore } $hash = hash('sha256', $json, false); // find it! - /** @var TransactionJournalMeta $entry */ - $entry = TransactionJournalMeta - ::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') - ->where('data', $hash) - ->where('name', 'importHashV2') - ->first(['journal_meta.*']); + $entry = $this->journalRepos->findByHash($hash); if (null === $entry) { return null; } @@ -216,6 +206,9 @@ class ImportArrayStorage */ private function linkToTag(Collection $collection): void { + if ($collection->count() === 0) { + return; + } /** @var TagRepositoryInterface $repository */ $repository = app(TagRepositoryInterface::class); $repository->setUser($this->importJob->user); @@ -236,7 +229,12 @@ class ImportArrayStorage $tagId = $tag->id; foreach ($journalIds as $journalId) { Log::debug(sprintf('Linking journal #%d to tag #%d...', $journalId, $tagId)); - DB::table('tag_transaction_journal')->insert(['transaction_journal_id' => $journalId, 'tag_id' => $tagId]); + try { + DB::table('tag_transaction_journal')->insert(['transaction_journal_id' => $journalId, 'tag_id' => $tagId]); + } catch (QueryException $e) { + Log::error('Could not link journal #%d to tag #%d because: %s', $journalIds, $tagId, $e->getMessage()); + Log::error($e->getTraceAsString()); + } } Log::info(sprintf('Linked %d journals to tag #%d ("%s")', $collection->count(), $tag->id, $tag->tag)); @@ -344,15 +342,12 @@ class ImportArrayStorage Log::debug('Going to store...'); // now actually store them: $collection = new Collection; - /** @var TransactionJournalFactory $factory */ - $factory = app(TransactionJournalFactory::class); - $factory->setUser($this->importJob->user); foreach ($toStore as $store) { // convert the date to an object: $store['date'] = Carbon::createFromFormat('Y-m-d', $store['date']); // store the journal. - $collection->push($factory->create($store)); + $collection->push($this->journalRepos->store($store)); } Log::debug('DONE storing!'); @@ -374,7 +369,6 @@ class ImportArrayStorage return false; } - // how many hits do we need? $requiredHits = count($transaction['transactions']) * 4; $totalHits = 0; @@ -386,11 +380,11 @@ class ImportArrayStorage // get the amount: $amount = (string)($current['amount'] ?? '0'); if (bccomp($amount, '0') === -1) { - $amount = bcmul($amount, '-1'); + $amount = bcmul($amount, '-1'); // @codeCoverageIgnore } // get the description: - $description = strlen((string)$current['description']) === 0 ? $transaction['description'] : $current['description']; + $description = '' === (string)$current['description'] ? $transaction['description'] : $current['description']; // get the source and destination ID's: $currentSourceIDs = [(int)$current['source_id'], (int)$current['destination_id']]; diff --git a/app/Import/Storage/ImportStorage.php b/app/Import/Storage/ImportStorage.php index 116431f3bc..c1d307f7b8 100644 --- a/app/Import/Storage/ImportStorage.php +++ b/app/Import/Storage/ImportStorage.php @@ -35,6 +35,8 @@ use Log; use Preferences; /** + * @codeCoverageIgnore + * @deprecated * Is capable of storing individual ImportJournal objects. * Adds 7 steps per object stored: * 1. get all import data from import journal diff --git a/app/Import/Storage/ImportSupport.php b/app/Import/Storage/ImportSupport.php index 1affa15731..f7a52914a7 100644 --- a/app/Import/Storage/ImportSupport.php +++ b/app/Import/Storage/ImportSupport.php @@ -40,6 +40,8 @@ use Illuminate\Support\Collection; use Log; /** + * @codeCoverageIgnore + * @deprecated * Trait ImportSupport. * * @property int $defaultCurrencyId diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 43081d4058..58ca7cf4be 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -32,6 +32,7 @@ use FireflyIII\Models\Note; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; use FireflyIII\Services\Internal\Destroy\JournalDestroyService; use FireflyIII\Services\Internal\Update\JournalUpdateService; @@ -147,6 +148,22 @@ class JournalRepository implements JournalRepositoryInterface return $journal; } + /** + * Find a journal by its hash. + * + * @param string $hash + * + * @return TransactionJournalMeta|null + */ + public function findByHash(string $hash): ?TransactionJournalMeta + { + return TransactionJournalMeta + ::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') + ->where('data', $hash) + ->where('name', 'importHashV2') + ->first(['journal_meta.*']); + } + /** * Find a specific journal. * diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 70011c6106..33ea68806d 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -27,6 +27,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Note; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; use FireflyIII\User; use Illuminate\Support\Collection; @@ -37,6 +38,14 @@ use Illuminate\Support\MessageBag; */ interface JournalRepositoryInterface { + /** + * Find a journal by its hash. + * + * @param string $hash + * + * @return TransactionJournalMeta|null + */ + public function findByHash(string $hash): ?TransactionJournalMeta; /** * @param TransactionJournal $journal diff --git a/app/Repositories/Rule/RuleRepository.php b/app/Repositories/Rule/RuleRepository.php index f6cd24e1c0..3375d38cad 100644 --- a/app/Repositories/Rule/RuleRepository.php +++ b/app/Repositories/Rule/RuleRepository.php @@ -28,6 +28,7 @@ use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleTrigger; use FireflyIII\User; +use Illuminate\Support\Collection; /** * Class RuleRepository. @@ -89,6 +90,26 @@ class RuleRepository implements RuleRepositoryInterface return $this->user->ruleGroups()->first(); } + /** + * Get the rules for a user tailored to the import process. + * + * @return Collection + */ + public function getForImport(): Collection + { + return Rule::distinct() + ->where('rules.user_id', $this->user->user_id) + ->leftJoin('rule_groups', 'rule_groups.id', '=', 'rules.rule_group_id') + ->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id') + ->where('rule_groups.active', 1) + ->where('rule_triggers.trigger_type', 'user_action') + ->where('rule_triggers.trigger_value', 'store-journal') + ->where('rules.active', 1) + ->orderBy('rule_groups.order', 'ASC') + ->orderBy('rules.order', 'ASC') + ->get(['rules.*', 'rule_groups.order']); + } + /** * @param RuleGroup $ruleGroup * diff --git a/app/Repositories/Rule/RuleRepositoryInterface.php b/app/Repositories/Rule/RuleRepositoryInterface.php index b3c1215e40..5fcdd4c89d 100644 --- a/app/Repositories/Rule/RuleRepositoryInterface.php +++ b/app/Repositories/Rule/RuleRepositoryInterface.php @@ -27,12 +27,14 @@ use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleGroup; use FireflyIII\Models\RuleTrigger; use FireflyIII\User; +use Illuminate\Support\Collection; /** * Interface RuleRepositoryInterface. */ interface RuleRepositoryInterface { + /** * @return int */ @@ -57,6 +59,13 @@ interface RuleRepositoryInterface */ public function getFirstRuleGroup(): RuleGroup; + /** + * Get the rules for a user tailored to the import process. + * + * @return Collection + */ + public function getForImport(): Collection; + /** * @param RuleGroup $ruleGroup * diff --git a/app/Support/Import/Configuration/Bunq/HaveAccounts.php b/app/Support/Import/Configuration/Bunq/HaveAccounts.php index 35ec5eae55..33128731ba 100644 --- a/app/Support/Import/Configuration/Bunq/HaveAccounts.php +++ b/app/Support/Import/Configuration/Bunq/HaveAccounts.php @@ -31,6 +31,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; /** + * @deprecated * Class HaveAccounts */ class HaveAccounts implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/ConfigurationInterface.php b/app/Support/Import/Configuration/ConfigurationInterface.php index 40c53c4a5b..effff5a098 100644 --- a/app/Support/Import/Configuration/ConfigurationInterface.php +++ b/app/Support/Import/Configuration/ConfigurationInterface.php @@ -25,6 +25,7 @@ namespace FireflyIII\Support\Import\Configuration; use FireflyIII\Models\ImportJob; /** + * @deprecated * Class ConfigurationInterface. */ interface ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/Initial.php b/app/Support/Import/Configuration/File/Initial.php index e9232c12a5..b573de01af 100644 --- a/app/Support/Import/Configuration/File/Initial.php +++ b/app/Support/Import/Configuration/File/Initial.php @@ -28,6 +28,7 @@ use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use Log; /** + * @deprecated * Class Initial. */ class Initial implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/Map.php b/app/Support/Import/Configuration/File/Map.php index 3072d88e9f..8ea9bd423b 100644 --- a/app/Support/Import/Configuration/File/Map.php +++ b/app/Support/Import/Configuration/File/Map.php @@ -34,6 +34,7 @@ use League\Csv\Statement; use Log; /** + * @deprecated * Class Mapping. */ class Map implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/Roles.php b/app/Support/Import/Configuration/File/Roles.php index 9b5b786a6c..35c69148f6 100644 --- a/app/Support/Import/Configuration/File/Roles.php +++ b/app/Support/Import/Configuration/File/Roles.php @@ -31,6 +31,7 @@ use League\Csv\Statement; use Log; /** + * @deprecated * Class Roles. */ class Roles implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/File/UploadConfig.php b/app/Support/Import/Configuration/File/UploadConfig.php index 3a699c76d4..6bf84df511 100644 --- a/app/Support/Import/Configuration/File/UploadConfig.php +++ b/app/Support/Import/Configuration/File/UploadConfig.php @@ -30,6 +30,7 @@ use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use Log; /** + * @deprecated * Class UploadConfig. */ class UploadConfig implements ConfigurationInterface diff --git a/app/Support/Import/Configuration/Spectre/HaveAccounts.php b/app/Support/Import/Configuration/Spectre/HaveAccounts.php index 2219748065..96752061ae 100644 --- a/app/Support/Import/Configuration/Spectre/HaveAccounts.php +++ b/app/Support/Import/Configuration/Spectre/HaveAccounts.php @@ -33,6 +33,7 @@ use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use Illuminate\Support\Collection; /** + * @deprecated * Class HaveAccounts */ class HaveAccounts implements ConfigurationInterface diff --git a/app/Support/Import/Information/BunqInformation.php b/app/Support/Import/Information/BunqInformation.php index 9b180baca9..e73673059b 100644 --- a/app/Support/Import/Information/BunqInformation.php +++ b/app/Support/Import/Information/BunqInformation.php @@ -37,6 +37,7 @@ use Log; use Preferences; /** + * @deprecated * Class BunqInformation. */ class BunqInformation implements InformationInterface diff --git a/app/Support/Import/Information/InformationInterface.php b/app/Support/Import/Information/InformationInterface.php index 69181c651d..0e23f7df70 100644 --- a/app/Support/Import/Information/InformationInterface.php +++ b/app/Support/Import/Information/InformationInterface.php @@ -25,6 +25,7 @@ namespace FireflyIII\Support\Import\Information; use FireflyIII\User; /** + * @deprecated * Interface InformationInterface. */ interface InformationInterface diff --git a/tests/Unit/Import/FileProcessor/CsvProcessorTest.php b/tests/Unit/Import/FileProcessor/CsvProcessorTest.php deleted file mode 100644 index f98d0b7692..0000000000 --- a/tests/Unit/Import/FileProcessor/CsvProcessorTest.php +++ /dev/null @@ -1,346 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace Tests\Unit\Import\FileProcessor; - -use FireflyIII\Import\FileProcessor\CsvProcessor; -use FireflyIII\Import\Specifics\AbnAmroDescription; -use FireflyIII\Models\ImportJob; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Repositories\Category\CategoryRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; -use Mockery; -use Tests\TestCase; - -/** - * Class CsvProcessorTest - */ -class CsvProcessorTest extends TestCase -{ - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::__construct - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @expectedException \FireflyIII\Exceptions\FireflyException - * @expectedExceptionMessage Cannot call getObjects() without a job. - */ - public function testGetObjectsNoJob() - { - $processor = new CsvProcessor(); - $processor->getObjects(); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getImportArray - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::setJob - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::importRow - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::specifics - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getRowHash - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::annotateValue - * @expectedException \FireflyIII\Exceptions\FireflyException - * @expectedExceptionMessage "bad-role" is not a valid role. - */ - public function testRunBadRole() - { - $accountRepos = $this->mock(AccountRepositoryInterface::class); - $budRepos = $this->mock(BudgetRepositoryInterface::class); - $jobRepos = $this->mock(ImportJobRepositoryInterface::class); - $catRepos = $this->mock(CategoryRepositoryInterface::class); - $billRepos = $this->mock(BillRepositoryInterface::class); - $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); - - $accountRepos->shouldReceive('setUser'); - $budRepos->shouldReceive('setUser'); - $catRepos->shouldReceive('setUser'); - $billRepos->shouldReceive('setUser'); - - // data - $config = [ - 'column-roles' => [ - 0 => 'bad-role', - ], - ]; - $extended = ['steps' => 0, 'done' => 0]; - $job = $this->getJob($config); - $csvFile = '20170101,-12.34,"Some description"'; - - // mock stuff - - $jobRepos->shouldReceive('setUser')->withArgs([Mockery::any()])->once(); - $jobRepos->shouldReceive('getConfiguration')->andReturn($config); - $jobRepos->shouldReceive('uploadFileContents')->withArgs([Mockery::any()])->andReturn($csvFile)->once(); - $jobRepos->shouldReceive('addStepsDone')->twice(); - - // mock stuff for this single row: - $jobRepos->shouldReceive('countByHash')->once()->withArgs([Mockery::any()])->andReturn(0); - - $processor = new CsvProcessor(); - $processor->setJob($job); - $processor->run(); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getImportArray - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::setJob - */ - public function testRunBasic() - { - // data - $config = []; - $job = $this->getJob($config); - $csvFile = ''; - $extended = ['steps' => 0, 'done' => 0]; - - // mock stuff - $repository = $this->mock(ImportJobRepositoryInterface::class); - $repository->shouldReceive('setUser')->withArgs([Mockery::any()])->once(); - $repository->shouldReceive('getConfiguration')->andReturn($config); - $repository->shouldReceive('uploadFileContents')->withArgs([Mockery::any()])->andReturn($csvFile)->once(); - // $repository->shouldReceive('getExtendedStatus')->once()->andReturn([]); - // $repository->shouldReceive('setExtendedStatus')->once()->andReturn($job); - $repository->shouldReceive('addStepsDone')->times(3); - - $processor = new CsvProcessor(); - $processor->setJob($job); - $processor->run(); - - $objects = $processor->getObjects(); - $this->assertCount(0, $objects); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getImportArray - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::setJob - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::importRow - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::specifics - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getRowHash - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::annotateValue - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::rowAlreadyImported - */ - public function testRunExisting() - { - // data - $config = []; - $job = $this->getJob($config); - $csvFile = '20170101,-12.34,"Some description"'; - $extended = ['steps' => 0, 'done' => 0]; - - // mock stuff - $repository = $this->mock(ImportJobRepositoryInterface::class); - $repository->shouldReceive('setUser')->withArgs([Mockery::any()])->once(); - $repository->shouldReceive('getConfiguration')->andReturn($config); - $repository->shouldReceive('uploadFileContents')->withArgs([Mockery::any()])->andReturn($csvFile)->once(); - // $repository->shouldReceive('getExtendedStatus')->once()->andReturn([]); // twice for update errors. - // $repository->shouldReceive('setExtendedStatus')->once()->andReturn($job); - //$repository->shouldReceive('addStepsDone')->times(3); - - // mock stuff for this single row: - $repository->shouldReceive('countByHash')->once()->withArgs([Mockery::any()])->andReturn(1); - $repository->shouldReceive('addStepsDone')->times(3)->withArgs([Mockery::any(), 1]); - $repository->shouldReceive('addError')->once()->withArgs([Mockery::any(), 0, 'Row #0 has already been imported.']); - $processor = new CsvProcessor(); - $processor->setJob($job); - $processor->run(); - - $objects = $processor->getObjects(); - $this->assertCount(0, $objects); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getImportArray - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::setJob - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::importRow - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::specifics - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getRowHash - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::annotateValue - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::rowAlreadyImported - * @expectedException \FireflyIII\Exceptions\FireflyException - * @expectedExceptionMessage "GoodBankDescription" is not a valid class name - */ - public function testRunInvalidSpecific() - { - // data - $config = [ - 'specifics' => ['GoodBankDescription' => 1], - ]; - $job = $this->getJob($config); - $csvFile = '20170101,-12.34,descr'; - $extended = ['steps' => 0, 'done' => 0]; - - // mock stuff - $repository = $this->mock(ImportJobRepositoryInterface::class); - $repository->shouldReceive('setUser')->withArgs([Mockery::any()])->once(); - $repository->shouldReceive('getConfiguration')->andReturn($config); - $repository->shouldReceive('uploadFileContents')->withArgs([Mockery::any()])->andReturn($csvFile)->once(); - // $repository->shouldReceive('getExtendedStatus')->once()->andReturn([]); - // $repository->shouldReceive('setExtendedStatus')->once()->andReturn($job); - // mock stuff for this single row: - $repository->shouldReceive('countByHash')->once()->withArgs([Mockery::any()])->andReturn(0); - $repository->shouldReceive('addStepsDone')->times(2)->withArgs([Mockery::any(), 1]); - - // mock specific: - $processor = new CsvProcessor(); - $processor->setJob($job); - $processor->run(); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @expectedException \FireflyIII\Exceptions\FireflyException - * @expectedExceptionMessage Cannot call run() without a job. - */ - public function testRunNoJob() - { - - $processor = new CsvProcessor(); - $processor->run(); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getImportArray - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::setJob - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::importRow - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::specifics - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getRowHash - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::annotateValue - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::rowAlreadyImported - */ - public function testRunSingle() - { - $accountRepos = $this->mock(AccountRepositoryInterface::class); - $budRepos = $this->mock(BudgetRepositoryInterface::class); - $jobRepos = $this->mock(ImportJobRepositoryInterface::class); - $catRepos = $this->mock(CategoryRepositoryInterface::class); - $billRepos = $this->mock(BillRepositoryInterface::class); - $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); - - $accountRepos->shouldReceive('setUser'); - $budRepos->shouldReceive('setUser'); - $catRepos->shouldReceive('setUser'); - $billRepos->shouldReceive('setUser'); - - // data - $config = []; - $job = $this->getJob($config); - $csvFile = '20170101,-12.34,"Some description"'; - $extended = ['steps' => 0, 'done' => 0]; - - // mock stuff - $jobRepos->shouldReceive('setUser')->withArgs([Mockery::any()])->once(); - $jobRepos->shouldReceive('getConfiguration')->andReturn($config); - $jobRepos->shouldReceive('uploadFileContents')->withArgs([Mockery::any()])->andReturn($csvFile)->once(); - - // mock stuff for this single row: - $jobRepos->shouldReceive('countByHash')->once()->withArgs([Mockery::any()])->andReturn(0); - $jobRepos->shouldReceive('addStepsDone')->times(3)->withArgs([Mockery::any(), 1]); - $processor = new CsvProcessor(); - $processor->setJob($job); - $processor->run(); - - $objects = $processor->getObjects(); - $this->assertCount(1, $objects); - } - - /** - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::run - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getImportArray - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getObjects - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::setJob - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::importRow - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::specifics - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::getRowHash - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::annotateValue - * @covers \FireflyIII\Import\FileProcessor\CsvProcessor::rowAlreadyImported - */ - public function testRunSpecific() - { - $accountRepos = $this->mock(AccountRepositoryInterface::class); - $budRepos = $this->mock(BudgetRepositoryInterface::class); - $jobRepos = $this->mock(ImportJobRepositoryInterface::class); - $catRepos = $this->mock(CategoryRepositoryInterface::class); - $billRepos = $this->mock(BillRepositoryInterface::class); - $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); - - $accountRepos->shouldReceive('setUser'); - $budRepos->shouldReceive('setUser'); - $catRepos->shouldReceive('setUser'); - $billRepos->shouldReceive('setUser'); - - // data - $config = [ - 'specifics' => ['AbnAmroDescription' => 1], - ]; - $job = $this->getJob($config); - $csvFile = '20170101,-12.34,descr'; - $row = explode(',', $csvFile); - $extended = ['steps' => 0, 'done' => 0]; - - // mock stuff - $jobRepos->shouldReceive('setUser')->withArgs([Mockery::any()])->once(); - $jobRepos->shouldReceive('getConfiguration')->andReturn($config); - $jobRepos->shouldReceive('uploadFileContents')->withArgs([Mockery::any()])->andReturn($csvFile)->once(); - // mock stuff for this single row: - $jobRepos->shouldReceive('countByHash')->once()->withArgs([Mockery::any()])->andReturn(0); - $jobRepos->shouldReceive('addStepsDone')->times(3)->withArgs([Mockery::any(), 1]); - - // mock specific: - $specific = $this->mock(AbnAmroDescription::class); - $specific->shouldReceive('run')->once()->andReturn($row); - - $processor = new CsvProcessor(); - $processor->setJob($job); - $processor->run(); - - $objects = $processor->getObjects(); - $this->assertCount(1, $objects); - } - - /** - * @param array $config - * - * @return ImportJob - */ - protected function getJob(array $config): ImportJob - { - $job = new ImportJob; - $job->file_type = 'file'; - $job->status = 'new'; - $job->key = 'x' . random_int(1, 100000); - $job->user()->associate($this->user()); - $job->configuration = $config; - - return $job; - } -} diff --git a/tests/Unit/Import/Specifics/RabobankDescriptionTest.php b/tests/Unit/Import/Specifics/RabobankDescriptionTest.php index fd5d07af19..b3f437b030 100644 --- a/tests/Unit/Import/Specifics/RabobankDescriptionTest.php +++ b/tests/Unit/Import/Specifics/RabobankDescriptionTest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace tests\Unit\Import\Specifics; +use FireflyIII\Import\Specifics\RabobankDescription; use Tests\TestCase; /** @@ -31,9 +32,44 @@ use Tests\TestCase; */ class RabobankDescriptionTest extends TestCase { + /** + * Default behaviour + * @covers \FireflyIII\Import\Specifics\RabobankDescription + */ public function testRunBasic(): void { - $this->assertTrue(true); + $row = ['','','','','','','','','','','']; + + $parser = new RabobankDescription; + $result = $parser->run($row); + $this->assertEquals($row, $result); + } + + /** + * No opposite name or iban + * @covers \FireflyIII\Import\Specifics\RabobankDescription + */ + public function testRunUseDescription(): void + { + $row = ['','','','','','','','','','','Hello']; + + $parser = new RabobankDescription; + $result = $parser->run($row); + $this->assertEquals('Hello', $result[6]); + $this->assertEquals('', $result[10]); + } + + /** + * Has opposite name or iban + * @covers \FireflyIII\Import\Specifics\RabobankDescription + */ + public function testRunUseFilledIn(): void + { + $row = ['','','','','','ABC','','','','','']; + + $parser = new RabobankDescription; + $result = $parser->run($row); + $this->assertEquals($row, $result); } } \ No newline at end of file diff --git a/tests/Unit/Import/Specifics/SnsDescriptionTest.php b/tests/Unit/Import/Specifics/SnsDescriptionTest.php new file mode 100644 index 0000000000..9069784627 --- /dev/null +++ b/tests/Unit/Import/Specifics/SnsDescriptionTest.php @@ -0,0 +1,72 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Unit\Import\Specifics; + + +use FireflyIII\Import\Specifics\SnsDescription; +use Tests\TestCase; + +/** + * Class SnsDescriptionTest + */ +class SnsDescriptionTest extends TestCase +{ + /** + * @covers \FireflyIII\Import\Specifics\SnsDescription + */ + public function testRunBasic(): void + { + $row = ['a', 'b', 'c']; + + $parser = new SnsDescription; + $result = $parser->run($row); + $this->assertEquals($row, $result); + } + + /** + * @covers \FireflyIII\Import\Specifics\SnsDescription + */ + public function testRunNoQuotes(): void + { + $row = ['a', 'b', 'c', 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 'Some text']; + + $parser = new SnsDescription; + $result = $parser->run($row); + $this->assertEquals($row, $result); + $this->assertEquals('Some text', $result[17]); + } + + /** + * @covers \FireflyIII\Import\Specifics\SnsDescription + */ + public function testRunQuotes(): void + { + $row = ['a', 'b', 'c', 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, '\'Some text\'']; + + $parser = new SnsDescription; + $result = $parser->run($row); + $this->assertEquals('Some text', $result[17]); + } + +} \ No newline at end of file diff --git a/tests/Unit/Import/Storage/ImportArrayStorageTest.php b/tests/Unit/Import/Storage/ImportArrayStorageTest.php new file mode 100644 index 0000000000..05cc146b84 --- /dev/null +++ b/tests/Unit/Import/Storage/ImportArrayStorageTest.php @@ -0,0 +1,493 @@ +. + */ + +declare(strict_types=1); + +namespace tests\Unit\Import\Storage; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Helpers\Filter\InternalTransferFilter; +use FireflyIII\Import\Storage\ImportArrayStorage; +use FireflyIII\Models\ImportJob; +use FireflyIII\Models\Rule; +use FireflyIII\Models\TransactionJournalMeta; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Rule\RuleRepositoryInterface; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; +use Illuminate\Support\Collection; +use Mockery; +use Tests\TestCase; + +/** + * Class ImportArrayStorageTest + */ +class ImportArrayStorageTest extends TestCase +{ + + /** + * Very basic storage routine. Doesn't call store() + * + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasic(): void + { + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = []; + $job->transactions = []; + $job->save(); + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $journalRepos->shouldReceive('setUser')->once(); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + } + + /** + * Two withdrawals, one of which is duplicated. + * + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreIsDouble(): void + { + // make fake job + $transactions = [$this->singleWithdrawal(), $this->singleWithdrawal()]; + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = ['apply-rules' => true]; + $job->transactions = $transactions; + $job->save(); + + // get some stuff: + $tag = $this->user()->tags()->inRandomOrder()->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + $ruleOne = new Rule; + $ruleOne->stop_processing = false; + $ruleTwo = new Rule; + $ruleTwo->stop_processing = true; + $meta = new TransactionJournalMeta; + $meta->transaction_journal_id = 3; + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $tagRepos = $this->mock(TagRepositoryInterface::class); + $ruleRepos = $this->mock(RuleRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $ruleRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('store')->once()->andReturn($tag); + $repository->shouldReceive('setTag')->once(); + $ruleRepos->shouldReceive('getForImport')->andReturn(new Collection([$ruleOne, $ruleTwo])); + $journalRepos->shouldReceive('setUser')->once(); + $journalRepos->shouldReceive('store')->once()->andReturn($journal); + $journalRepos->shouldReceive('findByHash')->andReturn(null, $meta)->twice(); + $repository->shouldReceive('addErrorMessage')->once() + ->withArgs([Mockery::any(), 'Entry #1 ("' . $transactions[1]['description'] . '") could not be imported. It already exists.']); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(1, $result); + } + + /** + * Very basic storage routine. Call store with no data. + * + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreNothing(): void + { + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = []; + $job->transactions = []; + $job->save(); + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $journalRepos->shouldReceive('setUser')->once(); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(0, $result); + } + + /** + * Call store with no data, also assume rules. + * + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreNothingWithRules(): void + { + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = ['apply-rules' => true]; + $job->transactions = []; + $job->save(); + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $tagRepos = $this->mock(TagRepositoryInterface::class); + $ruleRepos = $this->mock(RuleRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $ruleRepos->shouldReceive('setUser')->once(); + $ruleRepos->shouldReceive('getForImport')->andReturn(new Collection); + $journalRepos->shouldReceive('setUser')->once(); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(0, $result); + } + + /** + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreSingleWithNoRules(): void + { + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = ['apply-rules' => true]; + $job->transactions = [$this->singleWithdrawal()]; + $job->save(); + + // get some stuff: + $tag = $this->user()->tags()->inRandomOrder()->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $tagRepos = $this->mock(TagRepositoryInterface::class); + $ruleRepos = $this->mock(RuleRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $ruleRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('store')->once()->andReturn($tag); + $repository->shouldReceive('setTag')->once(); + $ruleRepos->shouldReceive('getForImport')->andReturn(new Collection); + $journalRepos->shouldReceive('setUser')->once(); + $journalRepos->shouldReceive('store')->once()->andReturn($journal); + $journalRepos->shouldReceive('findByHash')->andReturn(null)->once(); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(1, $result); + } + + /** + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreSingleWithRules(): void + { + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = ['apply-rules' => true]; + $job->transactions = [$this->singleWithdrawal()]; + $job->save(); + + // get some stuff: + $tag = $this->user()->tags()->inRandomOrder()->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + $ruleOne = new Rule; + $ruleOne->stop_processing = false; + $ruleTwo = new Rule; + $ruleTwo->stop_processing = true; + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $tagRepos = $this->mock(TagRepositoryInterface::class); + $ruleRepos = $this->mock(RuleRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $ruleRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('store')->once()->andReturn($tag); + $repository->shouldReceive('setTag')->once(); + $ruleRepos->shouldReceive('getForImport')->andReturn(new Collection([$ruleOne, $ruleTwo])); + $journalRepos->shouldReceive('setUser')->once(); + $journalRepos->shouldReceive('store')->once()->andReturn($journal); + $journalRepos->shouldReceive('findByHash')->andReturn(null)->once(); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(1, $result); + } + + /** + * @covers \FireflyIII\Import\Storage\ImportArrayStorage + */ + public function testBasicStoreTransferWithRules(): void + { + // make fake job + $job = new ImportJob; + $job->user()->associate($this->user()); + $job->key = 'a_storage' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = ['apply-rules' => true]; + $job->transactions = [$this->singleTransfer(), $this->singleWithdrawal()]; + $job->save(); + + // get a transfer: + $transfer = $this->user()->transactionJournals() + ->inRandomOrder()->where('transaction_type_id', 3) + ->first(); + + // get some stuff: + $tag = $this->user()->tags()->inRandomOrder()->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->first(); + $ruleOne = new Rule; + $ruleOne->stop_processing = false; + $ruleTwo = new Rule; + $ruleTwo->stop_processing = true; + + // mock stuff + $repository = $this->mock(ImportJobRepositoryInterface::class); + $collector = $this->mock(JournalCollectorInterface::class); + $tagRepos = $this->mock(TagRepositoryInterface::class); + $ruleRepos = $this->mock(RuleRepositoryInterface::class); + $journalRepos = $this->mock(JournalRepositoryInterface::class); + + // mock calls: + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withAnyArgs(); + $ruleRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('setUser')->once(); + $tagRepos->shouldReceive('store')->once()->andReturn($tag); + $repository->shouldReceive('setTag')->once(); + $ruleRepos->shouldReceive('getForImport')->andReturn(new Collection([$ruleOne, $ruleTwo])); + $journalRepos->shouldReceive('setUser')->once(); + $journalRepos->shouldReceive('store')->twice()->andReturn($journal); + $journalRepos->shouldReceive('findByHash')->andReturn(null)->twice(); + + // mock collector so it will return some transfers: + $collector->shouldReceive('setAllAssetAccounts')->once()->andReturnSelf(); + $collector->shouldReceive('setTypes')->withArgs([[TransactionType::TRANSFER]])->once()->andReturnSelf(); + $collector->shouldReceive('withOpposingAccount')->once()->andReturnSelf(); + $collector->shouldReceive('removeFilter')->withArgs([InternalTransferFilter::class])->once()->andReturnSelf(); + $collector->shouldReceive('getJournals')->andReturn(new Collection([$transfer])); + + $storage = new ImportArrayStorage; + $storage->setJob($job); + $result = new Collection; + try { + $result = $storage->store(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertCount(2, $result); + } + + /** + * @return array + */ + private function singleTransfer(): array + { + return + [ + 'type' => 'transfer', + 'date' => Carbon::create()->format('Y-m-d'), + 'tags' => '', + 'user' => $this->user()->id, + + // all custom fields: + 'internal_reference' => null, + 'notes' => null, + + // journal data: + 'description' => 'Some TEST transfer #' . random_int(1, 10000), + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'bill_id' => null, + 'bill_name' => null, + + // transaction data: + 'transactions' => [ + [ + 'currency_id' => null, + 'currency_code' => 'EUR', + 'description' => null, + 'amount' => random_int(500, 5000) / 100, + 'budget_id' => null, + 'budget_name' => null, + 'category_id' => null, + 'category_name' => null, + 'source_id' => 1, + 'source_name' => null, + 'destination_id' => 2, + 'destination_name' => null, + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'foreign_amount' => null, + 'reconciled' => false, + 'identifier' => 0, + ], + ], + ]; + } + + /** + * @return array + */ + private function singleWithdrawal(): array + { + return + [ + 'type' => 'withdrawal', + 'date' => Carbon::create()->format('Y-m-d'), + 'tags' => '', + 'user' => $this->user()->id, + + // all custom fields: + 'internal_reference' => null, + 'notes' => null, + + // journal data: + 'description' => 'Some TEST withdrawal #' . random_int(1, 10000), + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'bill_id' => null, + 'bill_name' => null, + + // transaction data: + 'transactions' => [ + [ + 'currency_id' => null, + 'currency_code' => 'EUR', + 'description' => null, + 'amount' => random_int(500, 5000) / 100, + 'budget_id' => null, + 'budget_name' => null, + 'category_id' => null, + 'category_name' => null, + 'source_id' => null, + 'source_name' => 'Checking Account', + 'destination_id' => null, + 'destination_name' => 'Random TEST expense account #' . random_int(1, 10000), + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'foreign_amount' => null, + 'reconciled' => false, + 'identifier' => 0, + ], + ], + ]; + } +} \ No newline at end of file