Expand test code.

This commit is contained in:
James Cole
2021-03-19 06:12:28 +01:00
parent b4d44fdd2b
commit 03d3ede036
37 changed files with 1343 additions and 1187 deletions

View File

@@ -36,7 +36,7 @@
</coverage> </coverage>
<testsuites> <testsuites>
<testsuite name="Api"> <testsuite name="Api">
<directory suffix="Test.php">./tests/Api/Models</directory> <directory suffix="Test.php">./tests/Api/Models/Account</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<php> <php>

View File

@@ -22,9 +22,9 @@
namespace Tests\Api\Autocomplete; namespace Tests\Api\Autocomplete;
use Tests\TestCase;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Log; use Log;
use Tests\TestCase;
/** /**
* Class AccountControllerTest * Class AccountControllerTest
@@ -41,14 +41,6 @@ class AccountControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
*
*/
public function testBasic(): void
{
$this->assertTrue(true);
}
/** /**
* @covers \FireflyIII\Api\V1\Controllers\Autocomplete\AccountController * @covers \FireflyIII\Api\V1\Controllers\Autocomplete\AccountController
*/ */
@@ -60,4 +52,12 @@ class AccountControllerTest extends TestCase
$response->assertHeader('Content-Type', 'application/json'); $response->assertHeader('Content-Type', 'application/json');
} }
/**
*
*/
public function testBasic(): void
{
$this->assertTrue(true);
}
} }

View File

@@ -22,14 +22,11 @@
namespace Tests\Api\Models\Account; namespace Tests\Api\Models\Account;
use Faker\Factory;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Log; use Log;
use Tests\Objects\Field; use Tests\Objects\Field;
use Tests\Objects\FieldSet; use Tests\Objects\FieldSet;
use Tests\Objects\TestConfiguration; use Tests\Objects\TestConfiguration;
use Tests\Objects\TestMandatoryField;
use Tests\Objects\TestMandatoryFieldSet;
use Tests\TestCase; use Tests\TestCase;
use Tests\Traits\CollectsValues; use Tests\Traits\CollectsValues;
use Tests\Traits\RandomValues; use Tests\Traits\RandomValues;
@@ -42,6 +39,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -54,323 +60,161 @@ class StoreControllerTest extends TestCase
/** /**
* @param array $submission * @param array $submission
* emptyDataProvider / storeDataProvider
* *
* @dataProvider storeDataProvider * newStoreDataProvider / emptyDataProvider
*
* @dataProvider newStoreDataProvider
*/ */
public function testStore(array $submission): void public function testStore(array $submission): void
{ {
$this->someTestData();
exit;
if ([] === $submission) { if ([] === $submission) {
$this->markTestSkipped('Empty data provider'); $this->markTestSkipped('Empty provider.');
} }
Log::debug('testStoreUpdated()');
Log::debug('submission :', $submission['submission']);
Log::debug('expected :', $submission['expected']);
Log::debug('ignore :', $submission['ignore']);
// run account store with a minimal data set: // run account store with a minimal data set:
$route = 'api.v1.accounts.store'; $address = route('api.v1.accounts.store');
$this->storeAndCompare($route, $submission); $this->updatedStoreAndCompare($address, $submission);
} }
/** /**
* @return array * @return array
*/ */
public function emptyDataProvider(): array public function newStoreDataProvider(): array
{ {
return [[[]]]; // some test configs:
$configuration = new TestConfiguration;
} // default asset account test set:
$defaultAssetSet = new FieldSet();
$defaultAssetSet->title = 'default_asset_account';
$defaultAssetSet->addField(Field::createBasic('name', 'uuid'));
$defaultAssetSet->addField(Field::createBasic('type', 'static-asset'));
$defaultAssetSet->addField(Field::createBasic('account_role', 'random-asset-accountRole'));
$configuration->addMandatoryFieldSet($defaultAssetSet);
/** // expense test set:
* @return array $expenseSet = new FieldSet();
*/ $expenseSet->title = 'expense_account';
public function storeDataProvider(): array $expenseSet->addField(Field::createBasic('name', 'uuid'));
{
$minimalSets = $this->minimalSets();
$optionalSets = $this->optionalSets();
$regenConfig = [
'name' => function () {
$faker = Factory::create();
return $faker->uuid; // to make sure expense set ignores the opening balance fields:
}, $field = new Field;
'iban' => function () { $field->title = 'type';
$faker = Factory::create(); $field->fieldTitle = 'type';
$field->fieldType = 'static-expense';
$field->ignorableFields = ['opening_balance', 'opening_balance_date', 'virtual_balance', 'order'];
$expenseSet->addField($field);
$configuration->addMandatoryFieldSet($expenseSet);
return $faker->iban(); // liability test set:
}, $fieldSet = new FieldSet();
'account_number' => function () { $fieldSet->title = 'liabilities_account';
$faker = Factory::create(); $fieldSet->addField(Field::createBasic('name', 'uuid'));
$fieldSet->addField(Field::createBasic('type', 'static-liabilities'));
$fieldSet->addField(Field::createBasic('liability_type', 'random-liability-type'));
$fieldSet->addField(Field::createBasic('liability_amount', 'random-amount'));
$fieldSet->addField(Field::createBasic('interest', 'random-percentage'));
$fieldSet->addField(Field::createBasic('interest_period', 'random-interest-period'));
$field = new Field;
$field->fieldTitle = 'liability_start_date';
$field->fieldType = 'random-past-date';
$field->ignorableFields = ['opening_balance', 'opening_balance_date'];
$field->title = 'liability_start_date';
$fieldSet->addField($field);
$configuration->addMandatoryFieldSet($fieldSet);
return $faker->iban(); // credit card set:
}, $fieldSet = new FieldSet();
]; $fieldSet->title = 'cc_account';
$fieldSet->addField(Field::createBasic('name', 'uuid'));
$fieldSet->addField(Field::createBasic('type', 'static-asset'));
$fieldSet->addField(Field::createBasic('account_role', 'static-ccAsset'));
$fieldSet->addField(Field::createBasic('credit_card_type', 'static-monthlyFull'));
$fieldSet->addField(Field::createBasic('monthly_payment_date', 'random-past-date'));
$configuration->addMandatoryFieldSet($fieldSet);
return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig); // optional field sets (for all test configs)
} $fieldSet = new FieldSet;
$fieldSet->addField(Field::createBasic('active', 'boolean'));
$configuration->addOptionalFieldSet('active', $fieldSet);
/** $fieldSet = new FieldSet;
* @return \array[][] $fieldSet->addField(Field::createBasic('iban', 'iban'));
*/ $configuration->addOptionalFieldSet('iban', $fieldSet);
private function optionalSets(): array
{
$faker = Factory::create();
$currencies = [
1 => 'EUR',
2 => 'HUF',
3 => 'GBP',
4 => 'UAH',
];
$rand = rand(1, 4);
$fieldSet = new FieldSet;
$fieldSet->addField(Field::createBasic('bic', 'bic'));
$configuration->addOptionalFieldSet('bic', $fieldSet);
return [ $fieldSet = new FieldSet;
'active' => [ $fieldSet->addField(Field::createBasic('account_number', 'account_number'));
'fields' => [ $configuration->addOptionalFieldSet('account_number', $fieldSet);
'active' => $faker->boolean,
],
],
'iban' => [
'fields' => [
'iban' => $faker->iban(),
],
],
'bic' => [
'fields' => [
'bic' => $faker->swiftBicNumber,
],
],
'account_number' => [
'fields' => [
'account_number' => $faker->iban(),
],
],
'ob' => [
'fields' => [
'opening_balance' => $this->getRandomAmount(),
'opening_balance_date' => $this->getRandomDateString(),
],
],
'virtual_balance' => [
'fields' => [
'virtual_balance' => $this->getRandomAmount(),
],
],
'currency_id' => [
'fields' => [
'currency_id' => $rand,
],
],
'currency_code' => [
'fields' => [
'currency_code' => $currencies[$rand],
],
],
'order' => [
'fields' => [
'order' => $faker->numberBetween(1, 5),
],
],
'include_net_worth' => [
'fields' => [
'include_net_worth' => $faker->boolean,
],
],
'notes' => [
'fields' => [
'notes' => join(' ', $faker->words(5)),
],
],
'location' => [
'fields' => [
'latitude' => $faker->latitude,
'longitude' => $faker->longitude,
'zoom_level' => $faker->numberBetween(1, 10),
],
],
];
}
/** $fieldSet = new FieldSet;
* @return array $fieldSet->addField(Field::createBasic('opening_balance', 'random-amount'));
*/ $fieldSet->addField(Field::createBasic('opening_balance_date', 'random-past-date'));
private function minimalSets(): array $configuration->addOptionalFieldSet('ob', $fieldSet);
{
$faker = Factory::create();
return [ $fieldSet = new FieldSet;
'asset' => [ $fieldSet->addField(Field::createBasic('virtual_balance', 'random-amount'));
'parameters' => [], $configuration->addOptionalFieldSet('virtual_balance', $fieldSet);
'fields' => [
'name' => $faker->uuid,
'type' => 'asset',
'account_role' => $this->randomAccountRole(),
],
],
'expense' => [
'parameters' => [],
'fields' => [
'name' => $faker->uuid,
'type' => 'expense',
],
],
'liability' => [
'parameters' => [],
'fields' => [
'name' => $faker->uuid,
'type' => 'liabilities',
'liability_type' => $this->randomLiabilityType(),
'liability_amount' => $this->getRandomAmount(),
'liability_start_date' => $this->getRandomDateString(),
'interest' => $this->getRandomPercentage(),
'interest_period' => $this->getRandomInterestPeriod(),
],
'ignore' => [
'opening_balance', 'opening_balance_date',
],
],
'cc' => [
'fields' => [
'name' => $faker->uuid,
'type' => 'asset',
'account_role' => 'ccAsset',
'credit_card_type' => 'monthlyFull',
'monthly_payment_date' => $this->getRandomDateString(),
], $fieldSet = new FieldSet;
], $field = new Field;
]; $field->fieldTitle = 'currency_id';
} $field->fieldType = 'random-currency-id';
$field->ignorableFields = ['currency_code'];
$field->title = 'currency_id';
$fieldSet->addField($field);
$configuration->addOptionalFieldSet('currency_id', $fieldSet);
public function someTestData(): void $fieldSet = new FieldSet;
{ $field = new Field;
// a basic test config set contains $field->fieldTitle = 'currency_code';
// mandatory fields and X optional fields $field->fieldType = 'random-currency-code';
// the optional fields will be rotated automatically. $field->ignorableFields = ['currency_id'];
$config = new TestConfiguration; $field->title = 'currency_code';
$fieldSet->addField($field);
$configuration->addOptionalFieldSet('currency_code', $fieldSet);
// add a set of mandatory fields: $fieldSet = new FieldSet;
$mandatoryFieldSet = new FieldSet(); $fieldSet->addField(Field::createBasic('order', 'order'));
$mandatoryFieldSet->title = 'default_asset_account'; $configuration->addOptionalFieldSet('order', $fieldSet);
// name $fieldSet = new FieldSet;
$mandatoryField = new Field; $fieldSet->addField(Field::createBasic('include_net_worth', 'boolean'));
$mandatoryField->title = 'name'; $configuration->addOptionalFieldSet('include_net_worth', $fieldSet);
$mandatoryField->fieldTitle = 'name';
$mandatoryField->fieldPosition = ''; // root
$mandatoryField->fieldType = 'uuid'; // refers to a generator or something?
$mandatoryField->expectedReturnType = 'equal'; // or 'callback'
$mandatoryField->expectedReturn = null; // or the callback
$mandatoryField->ignorableFields = [];
$mandatoryFieldSet->addField($mandatoryField);
// type $fieldSet = new FieldSet;
$mandatoryField = new Field; $fieldSet->addField(Field::createBasic('notes', 'uuid'));
$mandatoryField->title = 'type'; $configuration->addOptionalFieldSet('notes', $fieldSet);
$mandatoryField->fieldTitle = 'type';
$mandatoryField->fieldPosition = ''; // root
$mandatoryField->fieldType = 'static-asset'; // refers to a generator or something?
$mandatoryField->expectedReturnType = 'equal'; // or 'callback'
$mandatoryField->expectedReturn = null; // or the callback
$mandatoryField->ignorableFields = []; // something like transactions/0/currency_code
$mandatoryFieldSet->addField($mandatoryField);
// role $fieldSet = new FieldSet;
$mandatoryField = new Field; $fieldSet->addField(Field::createBasic('latitude', 'latitude'));
$mandatoryField->title = 'role'; $fieldSet->addField(Field::createBasic('longitude', 'longitude'));
$mandatoryField->fieldTitle = 'account_role'; $fieldSet->addField(Field::createBasic('zoom_level', 'random-zoom_level'));
$mandatoryField->fieldPosition = ''; // root $configuration->addOptionalFieldSet('notes', $fieldSet);
$mandatoryField->fieldType = 'random-asset-accountRole'; // refers to a generator or something?
$mandatoryField->expectedReturnType = 'equal'; // or 'callback'
$mandatoryField->expectedReturn = null; // or the callback
$mandatoryField->ignorableFields = []; // something like transactions/0/currency_code
$mandatoryFieldSet->addField($mandatoryField);
$config->mandatoryFieldSet = $mandatoryFieldSet;
unset($mandatoryField);
// $mandatoryField = new TestMandatoryField;
// $mandatoryField->title = 'transaction_type';
// $mandatoryField->fieldTitle = 'type';
// $mandatoryField->fieldPosition = 'transactions/0'; // not root!
// $mandatoryField->fieldType = 'random-transactionType'; // refers to a generator or something?
// $mandatoryField->expectedReturnType = 'equal'; // or 'callback'
// $mandatoryField->expectedReturn = null; // or the callback
// $mandatoryField->ignorableFields = [];
// $mandatoryFieldSet->addMandatoryField($mandatoryField);
$optionalFieldSet = new FieldSet;
$optionalField = new Field;
$optionalField->title = 'active';
$optionalField->fieldTitle = 'active';
$optionalField->fieldPosition = '';
$optionalField->fieldType = 'boolean'; // refers to a generator or something?
$optionalField->expectedReturnType = 'equal'; // or 'callback'
$optionalField->expectedReturn = null; // or the callback
$optionalField->ignorableFields = []; // something like transactions/0/currency_code
$optionalFieldSet->addField($optionalField, 'active');
$optionalField = new Field;
$optionalField->title = 'iban';
$optionalField->fieldTitle = 'iban';
$optionalField->fieldPosition = '';
$optionalField->fieldType = 'iban'; // refers to a generator or something?
$optionalField->expectedReturnType = 'equal'; // or 'callback'
$optionalField->expectedReturn = null; // or the callback
$optionalField->ignorableFields = []; // something like transactions/0/currency_code
$optionalFieldSet->addField($optionalField, 'iban');
$config->optionalFieldSet = $optionalFieldSet;
// generate submissions // generate submissions
$arr = $config->generateSubmission(); $array = $configuration->generateSubmissions();
var_dump($arr); $expected = $configuration->generateExpected($array);
exit; $ignored = $configuration->ignores;
// generate expected returns.
$set = [ // now create a combination for each submission and associated data:
// set for withdrawal, copy this for $final = [];
// other transaction types etc. foreach ($array as $index => $submission) {
// make a CLASS!! $final[] = [[
'identifier' => [ 'submission' => $submission,
'mandatory_fields' => [ 'expected' => $expected[$index],
'name_of_set' => [ 'ignore' => $ignored[$index],
'fields' => [ ]];
'basic_text_field' => [
'test_value' => function () {
return 'callback';
},
'expected_return_value' => function ($input) {
// the same?
return $input;
// a conversion?
return (string)$input;
// something else entirely?
return 'something else entirely.';
},
'ignore_other_fields' => [
'key_to_ignore',
'sub_array_like_transactions' => [0 => 'field_to_ignore'],
],
],
'another_basic_text_field' => [
// see above for 'test_value', 'expected_return_value' and 'ignore_other_fields'
],
'complex_array_field_like_transactions' => [
'transactions' => [
0 => [
'field_is_here' => [
'test_value' => null, // see above
'expected_return_value' => null, // see above
'ignore_other_fields' => [], // see above
],
],
],
],
],
],
],
// these will be permutated
'optional_fields' => [],
],
];
} }
return $final;
}
} }

View File

@@ -53,6 +53,7 @@ class UpdateControllerTest extends TestCase
*/ */
public function testUpdate(array $submission): void public function testUpdate(array $submission): void
{ {
$this->markTestSkipped('Skipped');
$ignore = [ $ignore = [
'created_at', 'created_at',
'updated_at', 'updated_at',

View File

@@ -37,33 +37,6 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
*
*/
public function setUp(): void
{
parent::setUp();
Passport::actingAs($this->user());
Log::info(sprintf('Now in %s.', get_class($this)));
}
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.attachments.store';
$this->storeAndCompare($route, $submission);
}
/** /**
* @return array * @return array
*/ */
@@ -73,6 +46,15 @@ class StoreControllerTest extends TestCase
} }
/**
*
*/
public function setUp(): void
{
parent::setUp();
Passport::actingAs($this->user());
Log::info(sprintf('Now in %s.', get_class($this)));
}
/** /**
* @return array * @return array
@@ -86,7 +68,6 @@ class StoreControllerTest extends TestCase
return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig); return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig);
} }
/** /**
* @return array * @return array
*/ */
@@ -135,4 +116,21 @@ class StoreControllerTest extends TestCase
], ],
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.attachments.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.available_budgets.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -85,7 +68,6 @@ class StoreControllerTest extends TestCase
return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig); return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig);
} }
/** /**
* @return array * @return array
*/ */
@@ -104,7 +86,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -132,4 +113,21 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.available_budgets.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.bills.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -91,7 +74,6 @@ class StoreControllerTest extends TestCase
return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig); return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig);
} }
/** /**
* @return array * @return array
*/ */
@@ -114,7 +96,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -197,4 +178,21 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.bills.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.budgets.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -91,13 +74,13 @@ class StoreControllerTest extends TestCase
return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig); return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig);
} }
/** /**
* @return array * @return array
*/ */
private function minimalSets(): array private function minimalSets(): array
{ {
$faker = Factory::create(); $faker = Factory::create();
return [ return [
'default_budget' => [ 'default_budget' => [
'fields' => [ 'fields' => [
@@ -107,7 +90,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -150,9 +132,26 @@ class StoreControllerTest extends TestCase
'auto_budget_amount' => number_format($faker->randomFloat(2, 10, 100), 2), 'auto_budget_amount' => number_format($faker->randomFloat(2, 10, 100), 2),
'auto_budget_period' => $repeatFreq, 'auto_budget_period' => $repeatFreq,
], ],
] ],
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.budgets.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.budgets.limits.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -115,7 +98,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -160,4 +142,21 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
// run account store with a minimal data set:
$route = 'api.v1.budgets.limits.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.categories.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -108,7 +91,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -125,4 +107,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.categories.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.piggy_banks.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -110,7 +93,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -160,4 +142,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.piggy_banks.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.recurrences.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -144,7 +127,6 @@ class StoreControllerTest extends TestCase
return $set; return $set;
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -198,8 +180,24 @@ class StoreControllerTest extends TestCase
], ],
], ],
], ],
] ],
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.recurrences.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.rules.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -152,7 +135,6 @@ class StoreControllerTest extends TestCase
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -234,4 +216,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.rules.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.rule_groups.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -108,7 +91,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -135,4 +117,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.rule_groups.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.tags.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -108,7 +91,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -137,4 +119,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.tags.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -22,6 +22,7 @@
namespace Tests\Api\Models\Transaction; namespace Tests\Api\Models\Transaction;
use DateTimeInterface;
use Faker\Factory; use Faker\Factory;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Log; use Log;
@@ -37,6 +38,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +57,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.transactions.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -117,7 +101,7 @@ class StoreControllerTest extends TestCase
'transactions' => [ 'transactions' => [
[ [
'type' => $combi[0], 'type' => $combi[0],
'date' => $faker->dateTime(null, 'Europe/Amsterdam')->format(\DateTimeInterface::RFC3339), 'date' => $faker->dateTime(null, 'Europe/Amsterdam')->format(DateTimeInterface::RFC3339),
'amount' => number_format($faker->randomFloat(2, 10, 100), 12), 'amount' => number_format($faker->randomFloat(2, 10, 100), 12),
'description' => $faker->uuid, 'description' => $faker->uuid,
'source_id' => $combi[1], 'source_id' => $combi[1],
@@ -131,7 +115,6 @@ class StoreControllerTest extends TestCase
return $set; return $set;
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -211,4 +194,20 @@ class StoreControllerTest extends TestCase
return $set; return $set;
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.transactions.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.currencies.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -93,6 +76,7 @@ class StoreControllerTest extends TestCase
}, },
'symbol' => function () { 'symbol' => function () {
$faker = Factory::create(); $faker = Factory::create();
return $faker->randomAscii . $faker->randomAscii; return $faker->randomAscii . $faker->randomAscii;
}, },
]; ];
@@ -119,7 +103,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -146,4 +129,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.currencies.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.transaction_links.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -123,7 +106,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -140,4 +122,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.transaction_links.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.link_types.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -121,7 +104,6 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
@@ -132,4 +114,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.link_types.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -37,6 +37,15 @@ class StoreControllerTest extends TestCase
{ {
use RandomValues, TestHelpers, CollectsValues; use RandomValues, TestHelpers, CollectsValues;
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* *
*/ */
@@ -47,32 +56,6 @@ class StoreControllerTest extends TestCase
Log::info(sprintf('Now in %s.', get_class($this))); Log::info(sprintf('Now in %s.', get_class($this)));
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.webhooks.store';
$this->storeAndCompare($route, $submission);
}
/**
* @return array
*/
public function emptyDataProvider(): array
{
return [[[]]];
}
/** /**
* @return array * @return array
*/ */
@@ -138,13 +121,13 @@ class StoreControllerTest extends TestCase
]; ];
} }
/** /**
* @return \array[][] * @return \array[][]
*/ */
private function optionalSets(): array private function optionalSets(): array
{ {
$faker = Factory::create(); $faker = Factory::create();
return [ return [
'active' => [ 'active' => [
'fields' => [ 'fields' => [
@@ -154,4 +137,20 @@ class StoreControllerTest extends TestCase
]; ];
} }
/**
* @param array $submission
*
* emptyDataProvider / storeDataProvider
*
* @dataProvider storeDataProvider
*/
public function testStore(array $submission): void
{
if ([] === $submission) {
$this->markTestSkipped('Empty data provider');
}
$route = 'api.v1.webhooks.store';
$this->storeAndCompare($route, $submission);
}
} }

View File

@@ -102,7 +102,9 @@ class UpdateControllerTest extends TestCase
'trigger' => [ 'trigger' => [
'id' => 1, 'id' => 1,
'fields' => [ 'fields' => [
'trigger' => ['test_value' => $faker->randomElement(['TRIGGER_STORE_TRANSACTION', 'TRIGGER_UPDATE_TRANSACTION', 'TRIGGER_DESTROY_TRANSACTION'])], 'trigger' => ['test_value' => $faker->randomElement(
['TRIGGER_STORE_TRANSACTION', 'TRIGGER_UPDATE_TRANSACTION', 'TRIGGER_DESTROY_TRANSACTION']
)],
], ],
'extra_ignore' => [], 'extra_ignore' => [],
], ],

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace Tests; namespace Tests;
use Illuminate\Contracts\Console\Kernel; use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Application;
/** /**
* Trait CreatesApplication * Trait CreatesApplication
@@ -36,7 +37,7 @@ trait CreatesApplication
/** /**
* Creates the application. * Creates the application.
* *
* @return \Illuminate\Foundation\Application * @return Application
*/ */
public function createApplication() public function createApplication()
{ {

View File

@@ -12,10 +12,36 @@ class Field
{ {
public ?Closure $expectedReturn; public ?Closure $expectedReturn;
public string $expectedReturnType; public string $expectedReturnType;
public string $fieldPosition;
public string $fieldTitle; public string $fieldTitle;
public string $fieldType; public string $fieldType;
public ?array $ignorableFields; public ?array $ignorableFields;
public string $title; public string $title;
/**
* Field constructor.
*/
public function __construct()
{
$this->expectedReturnType = 'equal'; // or 'callback'
$this->expectedReturn = null; // or the callback
$this->ignorableFields = []; // something like transactions/0/currency_code
//$optionalField->ignorableFields = ['some_field', 'transactions/0/another_field', 'rules/2/another_one',]; // something like transactions/0/currency_code
}
/**
* @param string $title
* @param string $type
*
* @return static
*/
public static function createBasic(string $title, string $type): self
{
$field = new self;
$field->title = $title;
$field->fieldTitle = $title;
$field->fieldType = $type;
return $field;
}
} }

View File

@@ -11,9 +11,11 @@ use RuntimeException;
*/ */
class TestConfiguration class TestConfiguration
{ {
public FieldSet $mandatoryFieldSet; public array $mandatoryFieldSets;
public FieldSet $optionalFieldSet; public array $optionalFieldSets;
private array $submission; private array $submission;
protected const MAX_ITERATIONS = 3;
public array $ignores;
/** /**
* TestConfiguration constructor. * TestConfiguration constructor.
@@ -21,43 +23,314 @@ class TestConfiguration
public function __construct() public function __construct()
{ {
$this->submission = []; $this->submission = [];
$this->mandatoryFieldSets = [];
$this->optionalFieldSets = [];
$this->ignores = [];
}
/**
* @param FieldSet $set
*/
public function addMandatoryFieldSet(FieldSet $set)
{
$this->mandatoryFieldSets[] = $set;
}
public function addOptionalFieldSet(string $key, FieldSet $set)
{
$this->optionalFieldSets[$key] = $set;
}
/**
* @param array $submissions
*
* @return array
*/
public function generateIgnores(array $submissions): array
{
$ignores = [];
// loop each submission and find its expected return and create
// a return array with the expected values.
/** @var array $submission */
foreach ($submissions as $index => $submission) {
$ignores[$index] = [];
// loop each field and use the "name" to find it.
/**
* @var string $fieldName
* @var string $fieldValue
*/
foreach ($submission as $fieldTitle => $fieldValue) {
//echo "Now searching for field $fieldTitle on index $index.\n";
$fieldObject = $this->findField($fieldTitle);
if (null !== $fieldObject) {
if (0 !== count($fieldObject->ignorableFields)) {
/** @var string $ignorableField */
foreach ($fieldObject->ignorableFields as $ignorableField) {
// explode and put in the right position:
$positions = explode('/', $ignorableField);
if (1 === count($positions)) {
$ignores[$index][$ignorableField] = true;
}
if (3 === count($positions)) {
$root = $positions[0];
$index = (int)$positions[1];
$final = $positions[2];
$ignores[$index][$root][$index][$final] = true;
}
}
}
}
if (null === $fieldObject) {
die('null field object :(');
}
}
}
return $ignores;
}
/**
* @param int $index
* @param string $title
*
* @return Field|null
*/
private function findField(string $title): ?Field
{
// since there is no index for optional field sets (they use ID)
// reverse the set and loop them all:
// reason we reverse them is because the last always overrules the first.
$reversed = array_reverse($this->optionalFieldSets);
foreach ($reversed as $fieldSet) {
foreach ($fieldSet->fields as $field) {
if ($title === $field->fieldTitle) {
//echo " found field $title in an optional field set.\n";
return $field;
}
}
}
$reversed = array_reverse($this->mandatoryFieldSets);
foreach ($reversed as $fieldSet) {
foreach ($fieldSet->fields as $field) {
if ($title === $field->fieldTitle) {
//echo " found field $title in a mandatory field set.\n";
return $field;
}
}
}
return null;
}
/**
* @param array $submissions
*
* @return array
*/
public function generateExpected(array $submissions): array
{
$returns = [];
// loop each submission and find its expected return and create
// a return array with the expected values.
/** @var array $submission */
foreach ($submissions as $index => $submission) {
$returns[$index] = [];
// loop each field and use the "name" to find it.
/**
* @var string $fieldName
* @var string $fieldValue
*/
foreach ($submission as $fieldTitle => $fieldValue) {
//echo "Now searching for field $fieldTitle on index $index.\n";
$fieldObject = $this->findField($fieldTitle);
if (null !== $fieldObject) {
if (null === $fieldObject->expectedReturn) {
$returns[$index][$fieldTitle] = $submissions[$index][$fieldTitle];
}
if (null !== $fieldObject->expectedReturn) {
die('cannot handle closure');
}
}
if (null === $fieldObject) {
die('null field object :(');
}
}
}
return $returns;
}
/**
* @param FieldSet $set
*
* @return array
*/
private function toArray(FieldSet $set): array
{
$ignore = [];
$result = [];
/** @var Field $field */
foreach ($set->fields as $field) {
$result = $this->parseField($result, $field);
$ignore = array_unique($ignore + $field->ignorableFields);
}
$this->ignores[] = $ignore;
return $result;
} }
/** /**
* @return array * @return array
*/ */
public function generateSubmission(): array public function generateSubmissions(): array
{ {
// first generate standard submission: // first generate standard submissions:
$this->submission = []; $this->submission = [];
$standard = [];
/** @var Field $field */ // loop each standard submission:
foreach ($this->mandatoryFieldSet->fields as $field) { /** @var FieldSet $set */
$standard = $this->parseField($standard, $field); foreach ($this->mandatoryFieldSets as $set) {
} $this->submission[] = $this->toArray($set);
$this->submission[] = $standard;
// expand the standard submission with extra sets from the optional field set. // expand the standard submission with extra sets from the optional field set.
$optionalCount = count($this->optionalFieldSet->fields); $setCount = count($this->optionalFieldSets);
if (0 !== $optionalCount) { //echo "Just created a standard set\n";
$keys = array_keys($this->optionalFieldSet->fields); if (0 !== $setCount) {
for ($i = 1; $i <= count($keys); $i++) { $keys = array_keys($this->optionalFieldSets);
$combinations = $this->combinationsOf($i, $keys); //echo " keys to consider are: " . join(', ', $keys) . "\n";
foreach ($combinations as $combination) { $maxCount = count($keys) > self::MAX_ITERATIONS ? self::MAX_ITERATIONS : count($keys);
$custom = $standard; for ($i = 1; $i <= $maxCount; $i++) {
foreach ($combination as $key) { $combinationSets = $this->combinationsOf($i, $keys);
// add field $key to the standard submission. //echo " will create " . count($combinationSets) . " extra sets.\n";
$custom = $this->parseField($custom, $this->optionalFieldSet->fields[$key]); foreach ($combinationSets as $ii => $combinationSet) {
//echo " Set " . ($ii + 1) . "/" . count($combinationSets) . " will consist of:\n";
// the custom set is born!
$custom = $this->toArray($set);
// echo " refreshed!\n";
// echo " " . json_encode($custom) . "\n";
foreach ($combinationSet as $combination) {
//echo " $combination\n";
// here we start adding stuff to a copy of the standard submission.
/** @var FieldSet $customSet */
$customSet = $this->optionalFieldSets[$combination] ?? false;
// echo " there are " . count(array_keys($customSet->fields)) . " field(s) in this custom set\n";
// loop each field in this custom set and add them, nothing more.
/** @var Field $field */
foreach ($customSet->fields as $field) {
//echo " added field ".$field->fieldTitle." from custom set ".$combination."\n";
$custom = $this->parseField($custom, $field);
// for each field, add the ignores to the current index (+1!) of
// ignores.
if (null !== $field->ignorableFields && count($field->ignorableFields) > 0) {
$count = count($this->submission);
$currentIgnoreSet = $this->ignores[$count] ?? [];
$this->ignores[$count] = array_unique(array_values(array_merge($currentIgnoreSet, $field->ignorableFields)));
}
}
} }
// add custom to $submission:
$this->submission[] = $custom; $this->submission[] = $custom;
} }
} }
} }
}
return $this->submission; return $this->submission;
} }
/**
* @param array $current
* @param Field $field
*
* @return array
*/
private function parseField(array $current, Field $field): array
{
// fieldTitle indicates the position:
$positions = explode('/', $field->fieldTitle);
$count = count($positions);
if (1 === $count) {
$current[$field->fieldTitle] = $this->generateFieldValue($field->fieldType);
return $current;
}
if (3 === $count) {
$root = $positions[0];
$count = (int)$positions[1];
$final = $positions[2];
$current[$root] = array_key_exists($root, $current) ? $current[$root] : [];
$current[$root][$count] = array_key_exists($count, $current[$root]) ? $current[$root][$count] : [];
$current[$root][$count][$final] = $this->generateFieldValue($final);
return $current;
}
throw new RuntimeException(sprintf('Did not expect count %d from fieldTitle "%s".', $count, $field->fieldTitle));
}
/**
* @param string $type
*
* @return mixed
*/
private function generateFieldValue(string $type)
{
$faker = Factory::create();
switch ($type) {
default:
throw new RuntimeException(sprintf('Cannot handle field "%s"', $type));
case 'uuid':
return $faker->uuid;
case 'static-asset':
return 'asset';
case 'static-expense':
return 'expense';
case 'static-liabilities':
return 'liabilities';
case 'static-ccAsset':
return 'ccAsset';
case 'static-monthlyFull':
return 'monthlyFull';
case 'random-liability-type':
return $faker->randomElement(['loan', 'debt', 'mortgage']);
case 'random-amount':
return number_format($faker->randomFloat(2, 10, 100), 2);
case 'random-percentage':
return $faker->randomFloat(2, 1, 99);
case 'random-interest-period':
return $faker->randomElement(['daily', 'monthly', 'yearly']);
case 'random-past-date':
return $faker->dateTimeBetween('-3 years', '-1 years')->format('Y-m-d');
case 'random-asset-accountRole':
return $faker->randomElement(['defaultAsset', 'savingAsset']);
case 'random-transactionType':
return $faker->randomElement(['withdrawal', 'deposit', 'transfer']);
case 'boolean':
return $faker->boolean;
case 'iban':
case 'account_number':
return $faker->iban();
case 'bic':
return $faker->swiftBicNumber;
case 'random-currency-id':
return $faker->numberBetween(1, 10);
case 'random-currency-code':
return $faker->randomElement(['EUR', 'USD', 'HUF', 'GBP']);
case 'order':
return $faker->numberBetween(1, 5);
case 'latitude':
return $faker->latitude;
case 'longitude':
return $faker->longitude;
case 'random-zoom_level':
return $faker->numberBetween(1, 12);
}
}
/** /**
* @param $k * @param $k
* @param $xs * @param $xs
@@ -84,53 +357,37 @@ class TestConfiguration
} }
/** /**
* @param string $type * @param FieldSet $optionalFieldSet
*
* @return mixed
*/ */
private function generateFieldValue(string $type) public function setOptionalFieldSet(FieldSet $optionalFieldSet): void
{ {
$faker = Factory::create(); $this->optionalFieldSet = $optionalFieldSet;
switch ($type) {
default:
throw new RuntimeException(sprintf('Cannot handle field "%s"', $type));
case 'uuid':
return $faker->uuid;
case 'static-asset':
return 'asset';
case 'random-asset-accountRole':
return $faker->randomElement(['defaultAsset', 'savingsAsset']);
case 'random-transactionType':
return $faker->randomElement(['withdrawal', 'deposit', 'transfer']);
case 'boolean':
return $faker->boolean;
case 'iban':
return $faker->iban();
}
} }
/** /**
* @param array $current * @param array $existing
* @param Field $field * @param array $config
* *
* @return array * @return array
*/ */
private function parseField(array $current, Field $field): array private function parseIgnorableFields(array $existing, array $config): array
{ {
if ('' === $field->fieldPosition) { foreach ($config as $field) {
$current[$field->fieldTitle] = $this->generateFieldValue($field->fieldType); $parts = explode('/', $field);
if (1 === count($parts)) {
$existing[$parts[0]] = true;
} }
if ('' !== $field->fieldPosition) { if (3 === count($parts)) {
$positions = explode('/', $field->fieldPosition); $root = $parts[0];
// since the "positions" array is almost 2 indexes deep at best, we can do some manual fiddling. $index = (int)$parts[1];
$root = $positions[0]; $final = $parts[2];
$count = (int)$positions[1]; $existing[$root][$index][$final] = true;
$current[$root] = array_key_exists($root, $current) ? $current[$root] : []; }
$current[$root][$count] = array_key_exists($count, $current[$root]) ? $current[$root][$count] : []; //if ('' !== $field->fieldPosition) {
$current[$root][$count][$field->fieldTitle] = $this->generateFieldValue($field->fieldType); //$positions = explode('/', $field->fieldPosition);
} }
return $current; return $existing;
} }
} }

View File

@@ -32,6 +32,7 @@ use Tests\Traits\CollectsValues;
abstract class TestCase extends BaseTestCase abstract class TestCase extends BaseTestCase
{ {
use CreatesApplication, CollectsValues; use CreatesApplication, CollectsValues;
protected const MAX_ITERATIONS = 2; protected const MAX_ITERATIONS = 2;
/** /**

View File

@@ -24,18 +24,6 @@ declare(strict_types=1);
namespace Tests\Traits; namespace Tests\Traits;
use DB;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\User; use FireflyIII\User;
/** /**

View File

@@ -23,9 +23,6 @@ declare(strict_types=1);
namespace Tests\Traits; namespace Tests\Traits;
use FireflyIII\Models\Configuration;
use FireflyConfig;
/** /**
* Trait MocksDefaultValues * Trait MocksDefaultValues
*/ */

View File

@@ -54,21 +54,12 @@ trait RandomValues
return array_merge($res1, $res2); return array_merge($res1, $res2);
} }
/** /**
* @return string * @return string
*/ */
protected function randomAccountRole(): string protected function getRandomAmount(): string
{ {
return $this->randomFromArray(['defaultAsset', 'sharedAsset', 'savingAsset']); return number_format(rand(1000, 100000) / 100, '2', '.');
}
/**
* @return string
*/
protected function randomLiabilityType(): string
{
return $this->randomFromArray(['loan', 'debt', 'mortgage']);
} }
/** /**
@@ -79,14 +70,6 @@ trait RandomValues
return $this->randomFromArray(['EUR', 'USD', 'GBP']); return $this->randomFromArray(['EUR', 'USD', 'GBP']);
} }
/**
* @return string
*/
protected function getRandomAmount(): string
{
return number_format(rand(1000, 100000) / 100, '2', '.');
}
/** /**
* @return string * @return string
*/ */
@@ -98,6 +81,14 @@ trait RandomValues
return $date->format('Y-m-d'); return $date->format('Y-m-d');
} }
/**
* @return string
*/
protected function getRandomInterestPeriod(): string
{
return $this->randomFromArray(['daily', 'monthly', 'yearly']);
}
/** /**
* @return string * @return string
*/ */
@@ -109,9 +100,9 @@ trait RandomValues
/** /**
* @return string * @return string
*/ */
protected function getRandomInterestPeriod(): string protected function randomAccountRole(): string
{ {
return $this->randomFromArray(['daily', 'monthly', 'yearly']); return $this->randomFromArray(['defaultAsset', 'sharedAsset', 'savingAsset']);
} }
/** /**
@@ -123,4 +114,12 @@ trait RandomValues
{ {
return $array[rand(0, count($array) - 1)]; return $array[rand(0, count($array) - 1)];
} }
/**
* @return string
*/
protected function randomLiabilityType(): string
{
return $this->randomFromArray(['loan', 'debt', 'mortgage']);
}
} }

View File

@@ -32,6 +32,21 @@ use Log;
*/ */
trait TestHelpers trait TestHelpers
{ {
/**
* @return int
*/
public function randomInt(): int
{
$result = 4;
try {
$result = random_int(1, 100000);
} catch (Exception $e) {
Log::debug(sprintf('Could not generate random number: %s', $e->getMessage()));
}
return $result;
}
/** /**
* @param array $minimalSets * @param array $minimalSets
* @param array $startOptionalSets * @param array $startOptionalSets
@@ -105,22 +120,6 @@ trait TestHelpers
return $submissions; return $submissions;
} }
/**
* @return int
*/
public function randomInt(): int
{
$result = 4;
try {
$result = random_int(1, 100000);
} catch (Exception $e) {
Log::debug(sprintf('Could not generate random number: %s', $e->getMessage()));
}
return $result;
}
/** /**
* @param $set * @param $set
* @param $opts * @param $opts
@@ -149,6 +148,136 @@ trait TestHelpers
return $set; return $set;
} }
/**
* @param string $route
* @param array $content
*/
protected function updatedStoreAndCompare(string $route, array $content): void
{
$submission = $content['submission'];
$expected = $content['expected'];
$ignore = $content['ignore'];
// submit body
$response = $this->post($route, $submission, ['Accept' => 'application/json']);
$responseBody = $response->content();
$responseJson = json_decode($responseBody, true);
$status = $response->getStatusCode();
$this->assertEquals($status, 200, sprintf("Submission:\n%s\nResponse: %s", json_encode($submission), $responseBody));
$response->assertHeader('Content-Type', 'application/vnd.api+json');
// get return and compare each field
$responseAttributes = $responseJson['data']['attributes'];
$this->updatedCompareStorageArray($submission, $responseAttributes, $expected, $ignore);
// ignore fields too!
}
/**
* @param array $submission
* @param array $response
* @param array $expected
* @param array $ignore
*/
protected function updatedCompareStorageArray(array $submission, array $response, array $expected, array $ignore): void
{
foreach ($response as $key => $value) {
if (is_array($value) && array_key_exists($key, $expected) && is_array($expected[$key])) {
$this->updatedCompareStorageArray($submission, $value, $expected[$key], $ignore[$key] ?? []);
}
if (isset($expected[$key])) {
if (in_array($key, $ignore, true)) {
continue;
}
if (!in_array($key, $ignore, true)) {
$message = sprintf(
"Field '%s' with value %s is expected to be %s.\nSubmitted:\n%s\nIgnored: %s\nReturned\n%s",
$key,
var_export($value, true),
var_export($expected[$key], true),
json_encode($submission),
json_encode($ignore),
json_encode($response)
);
$this->assertEquals($value, $expected[$key], $message);
}
// if($value !== $expected[$key]) {
// }
// var_dump($key);
// var_dump($value);
// var_dump($expected[$key]);
// exit;
}
}
}
/**
* @param string $route
* @param array $content
*/
protected function storeAndCompare(string $route, array $content): void
{
$submission = $content['fields'];
$parameters = $content['parameters'];
$ignore = $content['ignore'];
// submit!
$response = $this->post(route($route, $parameters), $submission, ['Accept' => 'application/json']);
$responseBody = $response->content();
$responseJson = json_decode($responseBody, true);
$status = $response->getStatusCode();
$this->assertEquals($status, 200, sprintf("Submission:\n%s\nResponse: %s", json_encode($submission), $responseBody));
$response->assertHeader('Content-Type', 'application/vnd.api+json');
// compare results:
foreach ($responseJson['data']['attributes'] as $returnName => $returnValue) {
if (array_key_exists($returnName, $submission) && !in_array($returnName, $ignore, true)) {
// TODO still based on account routine:
if ($this->ignoreCombination($route, $submission['type'] ?? 'blank', $returnName)) {
continue;
}
// check if is array, if so we need something smart:
if (is_array($returnValue) && is_array($submission[$returnName])) {
$this->compareArray($submission, $returnName, $submission[$returnName], $returnValue);
}
if (!is_array($returnValue) && !is_array($submission[$returnName])) {
$message = sprintf(
"Main: Return value '%s' of key '%s' does not match submitted value '%s'.\n%s\n%s", $returnValue, $returnName, $submission[$returnName],
json_encode($submission), $responseBody
);
$this->assertEquals($returnValue, $submission[$returnName], $message);
}
}
}
}
/**
* Some specials:
*
* @param string $area
* @param string $left
* @param string $right
*
* @return bool
*/
protected function ignoreCombination(string $area, string $left, string $right): bool
{
if ('api.v1.accounts.store' === $area) {
if ('expense' === $left
&& in_array($right, ['order', 'virtual_balance', 'opening_balance', 'opening_balance_date'])) {
return true;
}
}
return false;
}
/** /**
* @param string $route * @param string $route
* @param array $submission * @param array $submission
@@ -247,47 +376,6 @@ trait TestHelpers
} }
} }
/**
* @param string $route
* @param array $content
*/
protected function storeAndCompare(string $route, array $content): void
{
$submission = $content['fields'];
$parameters = $content['parameters'];
$ignore = $content['ignore'];
// submit!
$response = $this->post(route($route, $parameters), $submission, ['Accept' => 'application/json']);
$responseBody = $response->content();
$responseJson = json_decode($responseBody, true);
$status = $response->getStatusCode();
$this->assertEquals($status, 200, sprintf("Submission:\n%s\nResponse: %s", json_encode($submission), $responseBody));
$response->assertHeader('Content-Type', 'application/vnd.api+json');
// compare results:
foreach ($responseJson['data']['attributes'] as $returnName => $returnValue) {
if (array_key_exists($returnName, $submission) && !in_array($returnName, $ignore, true)) {
// TODO still based on account routine:
if ($this->ignoreCombination($route, $submission['type'] ?? 'blank', $returnName)) {
continue;
}
// check if is array, if so we need something smart:
if (is_array($returnValue) && is_array($submission[$returnName])) {
$this->compareArray($submission, $returnName, $submission[$returnName], $returnValue);
}
if (!is_array($returnValue) && !is_array($submission[$returnName])) {
$message = sprintf(
"Main: Return value '%s' of key '%s' does not match submitted value '%s'.\n%s\n%s", $returnValue, $returnName, $submission[$returnName],
json_encode($submission), $responseBody
);
$this->assertEquals($returnValue, $submission[$returnName], $message);
}
}
}
}
/** /**
* @param array $fullOriginal * @param array $fullOriginal
* @param string $key * @param string $key
@@ -326,25 +414,4 @@ trait TestHelpers
} }
} }
} }
/**
* Some specials:
*
* @param string $area
* @param string $left
* @param string $right
*
* @return bool
*/
protected function ignoreCombination(string $area, string $left, string $right): bool
{
if ('api.v1.accounts.store' === $area) {
if ('expense' === $left
&& in_array($right, ['order', 'virtual_balance', 'opening_balance', 'opening_balance_date'])) {
return true;
}
}
return false;
}
} }