diff --git a/app/Import/JobConfiguration/FileJobConfiguration.php b/app/Import/JobConfiguration/FileJobConfiguration.php index 27eaa21e0a..75b97c8aaf 100644 --- a/app/Import/JobConfiguration/FileJobConfiguration.php +++ b/app/Import/JobConfiguration/FileJobConfiguration.php @@ -48,6 +48,7 @@ class FileJobConfiguration implements JobConfigurationInterface */ public function __construct() { + $this->repository = app(ImportJobRepositoryInterface::class); } /** @@ -57,11 +58,7 @@ class FileJobConfiguration implements JobConfigurationInterface */ public function configurationComplete(): bool { - if ($this->importJob->stage === 'ready_to_run') { - return true; - } - - return false; + return $this->importJob->stage === 'ready_to_run'; } /** @@ -129,8 +126,7 @@ class FileJobConfiguration implements JobConfigurationInterface */ public function setJob(ImportJob $job): void { - $this->importJob = $job; - $this->repository = app(ImportJobRepositoryInterface::class); + $this->importJob = $job; $this->repository->setUser($job->user); } @@ -156,17 +152,6 @@ class FileJobConfiguration implements JobConfigurationInterface case 'map': $class = ConfigureMappingHandler::class; break; - // case 'upload-config': // has file, needs file config. - // $class = UploadConfig::class; - // break; - // case 'roles': // has configured file, needs roles. - // $class = Roles::class; - // break; - // case 'map': // has roles, needs mapping. - // $class = Map::class; - // break; - // default: - // break; } if (!class_exists($class)) { throw new FireflyException(sprintf('Class %s does not exist in getConfigurationClass().', $class)); // @codeCoverageIgnore diff --git a/app/Import/Routine/FileRoutine.php b/app/Import/Routine/FileRoutine.php index d6237568a5..d626d83754 100644 --- a/app/Import/Routine/FileRoutine.php +++ b/app/Import/Routine/FileRoutine.php @@ -43,7 +43,6 @@ class FileRoutine implements RoutineInterface * * The final status of the routine must be "provider_finished". * - * @return bool * @throws FireflyException */ public function run(): void @@ -52,22 +51,20 @@ class FileRoutine implements RoutineInterface if ($this->importJob->status !== 'running') { throw new FireflyException('This file import job should not be started.'); // @codeCoverageIgnore } + if ($this->importJob->stage === 'ready_to_run') { + // get processor, depending on file type + // is just CSV for now. + $processor = $this->getProcessor(); + $processor->setJob($this->importJob); + $transactions = $processor->run(); - switch ($this->importJob->stage) { - case 'ready_to_run': - // get processor, depending on file type - // is just CSV for now. - $processor = $this->getProcessor(); - $processor->setJob($this->importJob); - $transactions = $processor->run(); + $this->repository->setStatus($this->importJob, 'provider_finished'); + $this->repository->setStage($this->importJob, 'final'); + $this->repository->setTransactions($this->importJob, $transactions); - $this->repository->setStatus($this->importJob, 'provider_finished'); - $this->repository->setStage($this->importJob, 'final'); - $this->repository->setTransactions($this->importJob, $transactions); - break; - default: - throw new FireflyException(sprintf('Import routine cannot handle stage "%s"', $this->importJob->stage)); + return; } + throw new FireflyException(sprintf('Import routine cannot handle stage "%s"', $this->importJob->stage)); // @codeCoverageIgnore } /** @@ -93,284 +90,7 @@ class FileRoutine implements RoutineInterface $config = $this->repository->getConfiguration($this->importJob); $type = $config['file-type'] ?? 'csv'; $class = config(sprintf('import.options.file.processors.%s', $type)); - /** @var FileProcessorInterface $object */ - $object = app($class); - return $object; + return app($class); } - - - - - - - - - // /** @var Collection */ - // public $errors; - // /** @var Collection */ - // public $journals; - // /** @var int */ - // public $lines = 0; - // /** @var ImportJob */ - // private $job; - // - // /** @var ImportJobRepositoryInterface */ - // private $repository; - // - // /** - // * ImportRoutine constructor. - // */ - // public function __construct() - // { - // $this->journals = new Collection; - // $this->errors = new Collection; - // } - // - // /** - // * @return Collection - // */ - // public function getErrors(): Collection - // { - // return $this->errors; - // } - // - // /** - // * @return Collection - // */ - // public function getJournals(): Collection - // { - // return $this->journals; - // } - // - // /** - // * @return int - // */ - // public function getLines(): int - // { - // return $this->lines; - // } - // - // /** - // * - // */ - // public function run(): bool - // { - // if ('configured' !== $this->getStatus()) { - // Log::error(sprintf('Job %s is in state "%s" so it cannot be started.', $this->job->key, $this->getStatus())); - // - // return false; - // } - // set_time_limit(0); - // Log::info(sprintf('Start with import job %s', $this->job->key)); - // - // // total steps: 6 - // $this->setTotalSteps(6); - // - // $importObjects = $this->getImportObjects(); - // $this->lines = $importObjects->count(); - // $this->addStep(); - // - // // total steps can now be extended. File has been scanned. 7 steps per line: - // $this->addTotalSteps(7 * $this->lines); - // - // // once done, use storage thing to actually store them: - // Log::info(sprintf('Returned %d valid objects from file processor', $this->lines)); - // - // $storage = $this->storeObjects($importObjects); - // $this->addStep(); - // Log::debug('Back in run()'); - // - // Log::debug('Updated job...'); - // Log::debug(sprintf('%d journals in $storage->journals', $storage->journals->count())); - // $this->journals = $storage->journals; - // $this->errors = $storage->errors; - // - // Log::debug('Going to call createImportTag()'); - // - // // create tag, link tag to all journals: - // $this->createImportTag(); - // $this->addStep(); - // - // // update job: - // $this->setStatus('finished'); - // - // Log::info(sprintf('Done with import job %s', $this->job->key)); - // - // return true; - // } - // - // /** - // * @param ImportJob $job - // */ - // public function setJob(ImportJob $job) - // { - // $this->job = $job; - // $this->repository = app(ImportJobRepositoryInterface::class); - // $this->repository->setUser($job->user); - // } - // - // /** - // * @return Collection - // */ - // protected function getImportObjects(): Collection - // { - // $objects = new Collection; - // $fileType = $this->getConfig()['file-type'] ?? 'csv'; - // // will only respond to "file" - // $class = config(sprintf('import.options.file.processors.%s', $fileType)); - // /** @var FileProcessorInterface $processor */ - // $processor = app($class); - // $processor->setJob($this->job); - // - // if ('configured' === $this->getStatus()) { - // // set job as "running"... - // $this->setStatus('running'); - // - // Log::debug('Job is configured, start with run()'); - // $processor->run(); - // $objects = $processor->getObjects(); - // } - // - // return $objects; - // } - // - // /** - // * Shorthand method. - // */ - // private function addStep() - // { - // $this->repository->addStepsDone($this->job, 1); - // } - // - // /** - // * Shorthand - // * - // * @param int $steps - // */ - // private function addTotalSteps(int $steps) - // { - // $this->repository->addTotalSteps($this->job, $steps); - // } - // - // /** - // * - // */ - // private function createImportTag(): Tag - // { - // Log::debug('Now in createImportTag()'); - // - // if ($this->journals->count() < 1) { - // Log::info(sprintf('Will not create tag, %d journals imported.', $this->journals->count())); - // - // return new Tag; - // } - // $this->addTotalSteps($this->journals->count() + 2); - // - // /** @var TagRepositoryInterface $repository */ - // $repository = app(TagRepositoryInterface::class); - // $repository->setUser($this->job->user); - // $data = [ - // 'tag' => trans('import.import_with_key', ['key' => $this->job->key]), - // 'date' => new Carbon, - // 'description' => null, - // 'latitude' => null, - // 'longitude' => null, - // 'zoomLevel' => null, - // 'tagMode' => 'nothing', - // ]; - // $tag = $repository->store($data); - // $this->addStep(); - // $extended = $this->getExtendedStatus(); - // $extended['tag'] = $tag->id; - // $this->setExtendedStatus($extended); - // - // Log::debug(sprintf('Created tag #%d ("%s")', $tag->id, $tag->tag)); - // Log::debug('Looping journals...'); - // $journalIds = $this->journals->pluck('id')->toArray(); - // $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]); - // $this->addStep(); - // } - // Log::info(sprintf('Linked %d journals to tag #%d ("%s")', $this->journals->count(), $tag->id, $tag->tag)); - // $this->addStep(); - // - // return $tag; - // } - // - // /** - // * Shorthand method - // * - // * @return array - // */ - // private function getConfig(): array - // { - // return $this->repository->getConfiguration($this->job); - // } - // - // /** - // * @return array - // */ - // private function getExtendedStatus(): array - // { - // return $this->repository->getExtendedStatus($this->job); - // } - // - // /** - // * Shorthand method. - // * - // * @return string - // */ - // private function getStatus(): string - // { - // return $this->repository->getStatus($this->job); - // } - // - // /** - // * @param array $extended - // */ - // private function setExtendedStatus(array $extended): void - // { - // $this->repository->setExtendedStatus($this->job, $extended); - // } - // - // /** - // * Shorthand - // * - // * @param string $status - // */ - // private function setStatus(string $status): void - // { - // $this->repository->setStatus($this->job, $status); - // } - // - // /** - // * Shorthand - // * - // * @param int $steps - // */ - // private function setTotalSteps(int $steps) - // { - // $this->repository->setTotalSteps($this->job, $steps); - // } - // - // /** - // * @param Collection $objects - // * - // * @return ImportStorage - // */ - // private function storeObjects(Collection $objects): ImportStorage - // { - // $config = $this->getConfig(); - // $storage = new ImportStorage; - // $storage->setJob($this->job); - // $storage->setDateFormat($config['date-format']); - // $storage->setObjects($objects); - // $storage->store(); - // Log::info('Back in storeObjects()'); - // - // return $storage; - // } } diff --git a/app/Import/Routine/RoutineInterface.php b/app/Import/Routine/RoutineInterface.php index 51c0b69737..f1f967460d 100644 --- a/app/Import/Routine/RoutineInterface.php +++ b/app/Import/Routine/RoutineInterface.php @@ -35,7 +35,6 @@ interface RoutineInterface * * The final status of the routine must be "provider_finished". * - * @return bool * @throws FireflyException */ public function run(): void; diff --git a/app/Support/Import/Configuration/File/NewFileJobHandler.php b/app/Support/Import/Configuration/File/NewFileJobHandler.php index de4cb070cf..a6f42e9d2f 100644 --- a/app/Support/Import/Configuration/File/NewFileJobHandler.php +++ b/app/Support/Import/Configuration/File/NewFileJobHandler.php @@ -32,6 +32,7 @@ use FireflyIII\Models\ImportJob; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Filesystem\FileNotFoundException; +use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; use Log; use Storage; @@ -61,7 +62,108 @@ class NewFileJobHandler implements ConfigurationInterface { // nothing to store, validate upload // and push to next stage. - $messages = new MessageBag; + $messages = $this->validateAttachments(); + + if ($messages->count() > 0) { + return $messages; + } + + // store config if it's in one of the attachments. + $this->storeConfiguration(); + + // set file type in config: + $config = $this->repository->getConfiguration($this->importJob); + $config['file-type'] = $data['import_file_type']; + $this->repository->setConfiguration($this->importJob, $config); + $this->repository->setStage($this->importJob, 'configure-upload'); + + return new MessageBag(); + + } + + /** + * Get the data necessary to show the configuration screen. + * + * @return array + */ + public function getNextData(): array + { + /** @var array $allowedTypes */ + $allowedTypes = config('import.options.file.import_formats'); + $importFileTypes = []; + $defaultImportType = config('import.options.file.default_import_format'); + foreach ($allowedTypes as $type) { + $importFileTypes[$type] = trans('import.import_file_type_' . $type); + } + + return [ + 'default_type' => $defaultImportType, + 'file_types' => $importFileTypes, + ]; + } + + /** + * @param ImportJob $job + */ + public function setJob(ImportJob $job): void + { + $this->importJob = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); + + } + + /** + * Take attachment, extract config, and put in job.\ + * + * @param Attachment $attachment + * + * @throws FireflyException + */ + public function storeConfig(Attachment $attachment): void + { + $disk = Storage::disk('upload'); + try { + $content = $disk->get(sprintf('at-%d.data', $attachment->id)); + $content = Crypt::decrypt($content); + } catch (FileNotFoundException $e) { + Log::error($e->getMessage()); + throw new FireflyException($e->getMessage()); + } + $json = json_decode($content, true); + if (null !== $json) { + $this->repository->setConfiguration($this->importJob, $json); + } + } + + /** + * Store config from job. + * + * @throws FireflyException + */ + public function storeConfiguration(): void + { + /** @var Collection $attachments */ + $attachments = $this->importJob->attachments; + /** @var Attachment $attachment */ + foreach ($attachments as $attachment) { + // if file is configuration file, store it into the job. + if ($attachment->filename === 'configuration_file') { + $this->storeConfig($attachment); + } + } + } + + /** + * Check if all attachments are UTF8. + * + * @return MessageBag + * @throws FireflyException + */ + public function validateAttachments(): MessageBag + { + $messages = new MessageBag; + /** @var Collection $attachments */ $attachments = $this->importJob->attachments; /** @var Attachment $attachment */ foreach ($attachments as $attachment) { @@ -86,45 +188,8 @@ class NewFileJobHandler implements ConfigurationInterface $this->storeConfig($attachment); } } - // set file type in config: - $config = $this->repository->getConfiguration($this->importJob); - $config['file-type'] = $data['import_file_type']; - $this->repository->setConfiguration($this->importJob, $config); - $this->repository->setStage($this->importJob, 'configure-upload'); - - return new MessageBag(); - - } - - /** - * Get the data necessary to show the configuration screen. - * - * @return array - */ - public function getNextData(): array - { - $importFileTypes = []; - $defaultImportType = config('import.options.file.default_import_format'); - - foreach (config('import.options.file.import_formats') as $type) { - $importFileTypes[$type] = trans('import.import_file_type_' . $type); - } - - return [ - 'default_type' => $defaultImportType, - 'file_types' => $importFileTypes, - ]; - } - - /** - * @param ImportJob $job - */ - public function setJob(ImportJob $job): void - { - $this->importJob = $job; - $this->repository = app(ImportJobRepositoryInterface::class); - $this->repository->setUser($job->user); + return $messages; } /** @@ -154,25 +219,4 @@ class NewFileJobHandler implements ConfigurationInterface return true; } - - /** - * @param Attachment $attachment - * - * @throws FireflyException - */ - private function storeConfig(Attachment $attachment): void - { - $disk = Storage::disk('upload'); - try { - $content = $disk->get(sprintf('at-%d.data', $attachment->id)); - $content = Crypt::decrypt($content); - } catch (FileNotFoundException $e) { - Log::error($e->getMessage()); - throw new FireflyException($e->getMessage()); - } - $json = json_decode($content, true); - if (null !== $json) { - $this->repository->setConfiguration($this->importJob, $json); - } - } } \ No newline at end of file diff --git a/tests/Feature/Controllers/Import/JobConfigurationControllerTest.php b/tests/Feature/Controllers/Import/JobConfigurationControllerTest.php index dd04607562..f9fb5b9950 100644 --- a/tests/Feature/Controllers/Import/JobConfigurationControllerTest.php +++ b/tests/Feature/Controllers/Import/JobConfigurationControllerTest.php @@ -26,6 +26,7 @@ namespace Tests\Feature\Controllers\Import; use FireflyIII\Import\JobConfiguration\FakeJobConfiguration; use FireflyIII\Models\ImportJob; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use Illuminate\Http\UploadedFile; use Illuminate\Support\MessageBag; use Log; use Mockery; @@ -165,6 +166,35 @@ class JobConfigurationControllerTest extends TestCase $response->assertSessionHas('warning', $messages->first()); } + /** + * @covers \FireflyIII\Http\Controllers\Import\JobConfigurationController + */ + public function testPostBadState(): void + { + + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'Ffake_job_' . random_int(1, 1000); + $job->status = 'some_bad_state'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->save(); + + $messages = new MessageBag; + $messages->add('some', 'srrange message'); + + // mock repositories and configuration handling classes: + $repository = $this->mock(ImportJobRepositoryInterface::class); + $configurator = $this->mock(FakeJobConfiguration::class); + + // call thing. + $this->be($this->user()); + $response = $this->post(route('import.job.configuration.post', [$job->key])); + $response->assertStatus(302); + $response->assertRedirect(route('import.index')); + $response->assertSessionHas('error', 'To access this page, your import job cannot have status "some_bad_state".'); + } + /** * @covers \FireflyIII\Http\Controllers\Import\JobConfigurationController */ @@ -198,13 +228,13 @@ class JobConfigurationControllerTest extends TestCase /** * @covers \FireflyIII\Http\Controllers\Import\JobConfigurationController */ - public function testPostBadState(): void + public function testPostWithUpload(): void { - + $file = UploadedFile::fake()->image('avatar.jpg'); $job = new ImportJob; $job->user_id = $this->user()->id; - $job->key = 'Ffake_job_' . random_int(1, 1000); - $job->status = 'some_bad_state'; + $job->key = 'Dfake_job_' . random_int(1, 1000); + $job->status = 'has_prereq'; $job->provider = 'fake'; $job->file_type = ''; $job->save(); @@ -216,12 +246,18 @@ class JobConfigurationControllerTest extends TestCase $repository = $this->mock(ImportJobRepositoryInterface::class); $configurator = $this->mock(FakeJobConfiguration::class); + // mock calls: + $configurator->shouldReceive('setJob')->once(); + $configurator->shouldReceive('configurationComplete')->once()->andReturn(false); + $configurator->shouldReceive('configureJob')->once()->andReturn($messages); + $repository->shouldReceive('storeFileUpload')->once()->andReturn(new MessageBag); + // call thing. $this->be($this->user()); - $response = $this->post(route('import.job.configuration.post', [$job->key])); + $response = $this->post(route('import.job.configuration.post', [$job->key]), ['import_file' => $file]); $response->assertStatus(302); - $response->assertRedirect(route('import.index')); - $response->assertSessionHas('error', 'To access this page, your import job cannot have status "some_bad_state".'); + $response->assertRedirect(route('import.job.configuration.index', [$job->key])); + $response->assertSessionHas('warning', $messages->first()); } diff --git a/tests/Unit/Import/Converter/RabobankDebitCreditTest.php b/tests/Unit/Import/Converter/RabobankDebitCreditTest.php index fd330b1041..5961b46318 100644 --- a/tests/Unit/Import/Converter/RabobankDebitCreditTest.php +++ b/tests/Unit/Import/Converter/RabobankDebitCreditTest.php @@ -34,17 +34,7 @@ class RabobankDebitCreditTest extends TestCase /** * @covers \FireflyIII\Import\Converter\RabobankDebitCredit::convert() */ - public function testConvertAf() - { - $converter = new RabobankDebitCredit; - $result = $converter->convert('D'); - $this->assertEquals(-1, $result); - } - - /** - * @covers \FireflyIII\Import\Converter\RabobankDebitCredit::convert() - */ - public function testConvertAnything() + public function testConvertAnything(): void { $converter = new RabobankDebitCredit; $result = $converter->convert('9083jkdkj'); @@ -54,10 +44,40 @@ class RabobankDebitCreditTest extends TestCase /** * @covers \FireflyIII\Import\Converter\RabobankDebitCredit::convert() */ - public function testConvertBij() + public function testConvertCredit(): void { $converter = new RabobankDebitCredit; $result = $converter->convert('C'); $this->assertEquals(1, $result); } + + /** + * @covers \FireflyIII\Import\Converter\RabobankDebitCredit::convert() + */ + public function testConvertCreditOld(): void + { + $converter = new RabobankDebitCredit; + $result = $converter->convert('B'); + $this->assertEquals(1, $result); + } + + /** + * @covers \FireflyIII\Import\Converter\RabobankDebitCredit::convert() + */ + public function testConvertDebit(): void + { + $converter = new RabobankDebitCredit; + $result = $converter->convert('D'); + $this->assertEquals(-1, $result); + } + + /** + * @covers \FireflyIII\Import\Converter\RabobankDebitCredit::convert() + */ + public function testConvertDebitOld(): void + { + $converter = new RabobankDebitCredit; + $result = $converter->convert('A'); + $this->assertEquals(-1, $result); + } } diff --git a/tests/Unit/Import/JobConfiguration/FileJobConfigurationTest.php b/tests/Unit/Import/JobConfiguration/FileJobConfigurationTest.php new file mode 100644 index 0000000000..12e90c7f2a --- /dev/null +++ b/tests/Unit/Import/JobConfiguration/FileJobConfigurationTest.php @@ -0,0 +1,367 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Unit\Import\JobConfiguration; + + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Import\JobConfiguration\FileJobConfiguration; +use FireflyIII\Models\ImportJob; +use FireflyIII\Support\Import\Configuration\File\ConfigureMappingHandler; +use FireflyIII\Support\Import\Configuration\File\ConfigureRolesHandler; +use FireflyIII\Support\Import\Configuration\File\ConfigureUploadHandler; +use FireflyIII\Support\Import\Configuration\File\NewFileJobHandler; +use Illuminate\Support\MessageBag; +use Mockery; +use Tests\TestCase; + +/** + * Class FileJobConfigurationTest + */ +class FileJobConfigurationTest extends TestCase +{ + /** + * No config, job is new. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testCCFalse(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'File_A_unit_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + // should be false: + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + $this->assertFalse($configurator->configurationComplete()); + } + + /** + * Job is ready to run. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testCCTrue(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'File_B_unit_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'ready_to_run'; + $job->provider = 'fake'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + // should be false: + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + $this->assertTrue($configurator->configurationComplete()); + } + + /** + * Configure the job when the stage is "map". Won't test other combo's because they're covered by other tests. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testConfigureJob(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'I-file_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'map'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $bag = new MessageBag; + $result = null; + + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + + $handler = $this->mock(ConfigureMappingHandler::class); + $handler->shouldReceive('setJob')->once()->withArgs([Mockery::any()]); + $handler->shouldReceive('configureJob')->withArgs([['c' => 'd']])->andReturn($bag)->once(); + + try { + $result = $configurator->configureJob(['c' => 'd']); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals($bag, $result); + } + + /** + * Get next data when stage is "configure-upload". Expect a certain class to be called. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextDataCU(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'G-file_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'configure-upload'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + + $handler = $this->mock(ConfigureUploadHandler::class); + $handler->shouldReceive('setJob')->once()->withArgs([Mockery::any()]); + $handler->shouldReceive('getNextData')->andReturn(['a' => 'b'])->withNoArgs()->once(); + + try { + $result = $configurator->getNextData(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals(['a' => 'b'], $result); + } + + /** + * Get next data when stage is "map". Expect a certain class to be called. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextDataMap(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'H-file_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'map'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + + $handler = $this->mock(ConfigureMappingHandler::class); + $handler->shouldReceive('setJob')->once()->withArgs([Mockery::any()]); + $handler->shouldReceive('getNextData')->andReturn(['a' => 'b'])->withNoArgs()->once(); + + try { + $result = $configurator->getNextData(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals(['a' => 'b'], $result); + } + + /** + * Get next data when stage is "new". Expect a certain class to be called. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextDataNew(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'F-file_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + + $handler = $this->mock(NewFileJobHandler::class); + $handler->shouldReceive('setJob')->once()->withArgs([Mockery::any()]); + $handler->shouldReceive('getNextData')->andReturn(['a' => 'b'])->withNoArgs()->once(); + + try { + $result = $configurator->getNextData(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals(['a' => 'b'], $result); + } + + /** + * Get next data when stage is "roles". Expect a certain class to be called. + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextDataRoles(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'H-file_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'roles'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + + $handler = $this->mock(ConfigureRolesHandler::class); + $handler->shouldReceive('setJob')->once()->withArgs([Mockery::any()]); + $handler->shouldReceive('getNextData')->andReturn(['a' => 'b'])->withNoArgs()->once(); + + try { + $result = $configurator->getNextData(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals(['a' => 'b'], $result); + } + + /** + * Get view when stage is "configure-upload". + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextViewCU(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'Dfile_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'configure-upload'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + try { + $result = $configurator->getNextView(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals('import.file.configure-upload', $result); + } + + /** + * Get view when stage is "map". + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextViewMap(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'Ffile_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'map'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + try { + $result = $configurator->getNextView(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals('import.file.map', $result); + } + + /** + * Get view when stage is "new". + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextViewNew(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'Cfile_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'new'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + try { + $result = $configurator->getNextView(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals('import.file.new', $result); + } + + /** + * Get view when stage is "roles". + * + * @covers \FireflyIII\Import\JobConfiguration\FileJobConfiguration + */ + public function testGetNextViewRoles(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'Efile_' . random_int(1, 1000); + $job->status = 'new'; + $job->stage = 'roles'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + $result = 'x'; + $configurator = new FileJobConfiguration; + $configurator->setJob($job); + try { + $result = $configurator->getNextView(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + $this->assertEquals('import.file.roles', $result); + } +} \ No newline at end of file diff --git a/tests/Unit/Import/Routine/FakeRoutineTest.php b/tests/Unit/Import/Routine/FakeRoutineTest.php index 9f2abdc9f3..b8b2511b36 100644 --- a/tests/Unit/Import/Routine/FakeRoutineTest.php +++ b/tests/Unit/Import/Routine/FakeRoutineTest.php @@ -41,7 +41,7 @@ class FakeRoutineTest extends TestCase /** * @covers \FireflyIII\Import\Routine\FakeRoutine */ - public function testRunAhoy() + public function testRunAhoy(): void { $job = new ImportJob; $job->user_id = $this->user()->id; @@ -76,7 +76,7 @@ class FakeRoutineTest extends TestCase /** * @covers \FireflyIII\Import\Routine\FakeRoutine */ - public function testRunFinal() + public function testRunFinal(): void { $job = new ImportJob; $job->user_id = $this->user()->id; @@ -112,7 +112,7 @@ class FakeRoutineTest extends TestCase /** * @covers \FireflyIII\Import\Routine\FakeRoutine */ - public function testRunNew() + public function testRunNew(): void { $job = new ImportJob; $job->user_id = $this->user()->id; diff --git a/tests/Unit/Import/Routine/FileRoutineTest.php b/tests/Unit/Import/Routine/FileRoutineTest.php new file mode 100644 index 0000000000..3d48bf98c2 --- /dev/null +++ b/tests/Unit/Import/Routine/FileRoutineTest.php @@ -0,0 +1,78 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Unit\Import\Routine; + + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Import\Routine\FileRoutine; +use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use FireflyIII\Support\Import\Routine\File\CSVProcessor; +use Mockery; +use Tests\TestCase; + +/** + * Class FileRoutineTest + */ +class FileRoutineTest extends TestCase +{ + + /** + * @covers \FireflyIII\Import\Routine\FileRoutine + */ + public function testRunDefault(): void + { + $job = new ImportJob; + $job->user_id = $this->user()->id; + $job->key = 'a_fr_' . random_int(1, 1000); + $job->status = 'running'; + $job->stage = 'ready_to_run'; + $job->provider = 'file'; + $job->file_type = ''; + $job->configuration = []; + $job->save(); + + // mock + $processor = $this->mock(CSVProcessor::class); + $repository = $this->mock(ImportJobRepositoryInterface::class); + + // calls + $repository->shouldReceive('setUser')->once(); + $repository->shouldReceive('setStatus')->withArgs([Mockery::any(), 'provider_finished'])->once(); + $repository->shouldReceive('setStage')->withArgs([Mockery::any(), 'final'])->once(); + $repository->shouldReceive('setTransactions')->withArgs([Mockery::any(), ['a' => 'b']])->once(); + $repository->shouldReceive('getConfiguration')->withArgs([Mockery::any()])->once()->andReturn([]); + $processor->shouldReceive('setJob')->once(); + $processor->shouldReceive('run')->once()->andReturn(['a' => 'b']); + + + $routine = new FileRoutine; + $routine->setJob($job); + try { + $routine->run(); + } catch (FireflyException $e) { + $this->assertTrue(false, $e->getMessage()); + } + } +} \ No newline at end of file diff --git a/tests/Unit/TransactionRules/Triggers/HasAnyCategoryTest.php b/tests/Unit/TransactionRules/Triggers/HasAnyCategoryTest.php index d1b0081bd2..0c6d828515 100644 --- a/tests/Unit/TransactionRules/Triggers/HasAnyCategoryTest.php +++ b/tests/Unit/TransactionRules/Triggers/HasAnyCategoryTest.php @@ -35,7 +35,7 @@ class HasAnyCategoryTest extends TestCase /** * @covers \FireflyIII\TransactionRules\Triggers\HasAnyCategory::triggered */ - public function testTriggered() + public function testTriggered(): void { $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); $category = $journal->user->categories()->first(); @@ -51,14 +51,14 @@ class HasAnyCategoryTest extends TestCase /** * @covers \FireflyIII\TransactionRules\Triggers\HasAnyCategory::triggered */ - public function testTriggeredNot() + public function testTriggeredNot(): void { $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); $journal->categories()->detach(); // also detach transactions: /** @var Transaction $transaction */ - foreach($journal->transactions as $transaction) { + foreach ($journal->transactions as $transaction) { $transaction->categories()->detach(); } @@ -71,10 +71,16 @@ class HasAnyCategoryTest extends TestCase /** * @covers \FireflyIII\TransactionRules\Triggers\HasAnyCategory::triggered */ - public function testTriggeredTransactions() + public function testTriggeredTransactions(): void { - /** @var TransactionJournal $journal */ - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + $count = 0; + $journal = null; + while ($count === 0) { + /** @var TransactionJournal $journal */ + $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + $count = $journal->transactions()->count(); + } + $category = $journal->user->categories()->first(); $journal->categories()->detach(); $this->assertEquals(0, $journal->categories()->count()); @@ -94,7 +100,7 @@ class HasAnyCategoryTest extends TestCase /** * @covers \FireflyIII\TransactionRules\Triggers\HasAnyCategory::willMatchEverything */ - public function testWillMatchEverything() + public function testWillMatchEverything(): void { $value = ''; $result = HasAnyCategory::willMatchEverything($value);