Fix tests for account

This commit is contained in:
James Cole 2021-03-20 07:02:06 +01:00
parent e32f14578c
commit 836f0ecf3f
No known key found for this signature in database
GPG Key ID: B5669F9493CDE38D
23 changed files with 399 additions and 275 deletions

View File

@ -47,47 +47,32 @@ class UpdateRequest extends FormRequest
*/
public function getUpdateData(): array
{
$active = null;
$includeNetWorth = null;
if (null !== $this->get('active')) {
$active = $this->boolean('active');
}
if (null !== $this->get('include_net_worth')) {
$includeNetWorth = $this->boolean('include_net_worth');
}
$data = [
'name' => $this->nullableString('name'),
'active' => $active,
'include_net_worth' => $includeNetWorth,
'account_type' => $this->nullableString('type'),
'account_type_id' => null,
'virtual_balance' => $this->nullableString('virtual_balance'),
'iban' => $this->nullableString('iban'),
'BIC' => $this->nullableString('bic'),
'account_number' => $this->nullableString('account_number'),
'account_role' => $this->nullableString('account_role'),
'liability_type' => $this->nullableString('liability_type'),
'opening_balance' => $this->nullableString('opening_balance'),
'opening_balance_date' => $this->date('opening_balance_date'),
'cc_type' => $this->nullableString('credit_card_type'),
'cc_monthly_payment_date' => $this->nullableString('monthly_payment_date'),
'notes' => $this->nullableNlString('notes'),
'interest' => $this->nullableString('interest'),
'interest_period' => $this->nullableString('interest_period'),
$fields = [
'name' => ['name', 'string'],
'active' => ['active', 'boolean'],
'include_net_worth' => ['include_net_worth', 'boolean'],
'account_type' => ['type', 'string'],
'virtual_balance' => ['virtual_balance', 'string'],
'iban' => ['iban', 'string'],
'BIC' => ['bic', 'string'],
'account_number' => ['account_number', 'string'],
'account_role' => ['account_role', 'string'],
'liability_type' => ['liability_type', 'string'],
'opening_balance' => ['opening_balance', 'string'],
'opening_balance_date' => ['opening_balance_date', 'date'],
'cc_type' => ['credit_card_type', 'string'],
'cc_monthly_payment_date' => ['monthly_payment_date', 'string'],
'notes' => ['notes', 'nlString'],
'interest' => ['interest', 'string'],
'interest_period' => ['interest_period', 'string'],
'order' => ['order', 'integer'],
'currency_id' => ['currency_id', 'integer'],
'currency_code' => ['currency_code', 'string'],
];
if (null !== $this->get('order')) {
$data['order'] = $this->integer('order');
}
if (null !== $this->get('currency_id')) {
$data['currency_id'] = $this->nullableInteger('currency_id');
}
if (null !== $this->get('currency_code')) {
$data['currency_code'] = $this->nullableString('currency_code');
}
$data = $this->getAllData($fields);
$data = $this->appendLocationData($data, null);
if ('liability' === $data['account_type']) {
if (array_key_exists('account_type', $data) && 'liability' === $data['account_type']) {
$data['opening_balance'] = bcmul($this->nullableString('liability_amount'), '-1');
$data['opening_balance_date'] = $this->date('liability_start_date');
$data['account_type'] = $this->nullableString('liability_type');
@ -123,9 +108,9 @@ class UpdateRequest extends FormRequest
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code',
'active' => [new IsBoolean],
'include_net_worth' => [new IsBoolean],
'account_role' => sprintf('in:%s|required_if:type,asset', $accountRoles),
'credit_card_type' => sprintf('in:%s|required_if:account_role,ccAsset', $ccPaymentTypes),
'monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles),
'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes),
'monthly_payment_date' => 'date' . '|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage',
'interest' => 'required_if:type,liability|between:0,100|numeric',
'interest_period' => 'required_if:type,liability|in:daily,monthly,yearly',

View File

@ -120,7 +120,13 @@ trait AccountServiceTrait
if (null === $data['account_role']) {
$data['account_role'] = $this->accountRepository->getMetaValue($account, 'account_role');
}
if ($account->accountType->type === AccountType::ASSET && isset($data['account_role']) && 'ccAsset' === $data['account_role']) {
// only asset account may have a role:
if ($account->accountType->type !== AccountType::ASSET) {
$data['account_role'] = '';
}
if ($account->accountType->type === AccountType::ASSET && array_key_exists('account_role', $data) && 'ccAsset' === $data['account_role']) {
$fields = $this->validCCFields; // @codeCoverageIgnore
}
/** @var AccountMetaFactory $factory */

View File

@ -119,15 +119,23 @@ class AccountUpdateService
private function updateAccount(Account $account, array $data): Account
{
// update the account itself:
$account->name = $data['name'] ?? $account->name;
$account->active = $data['active'] ?? $account->active;
$account->iban = $data['iban'] ?? $account->iban;
if(array_key_exists('name', $data)) {
$account->name = $data['name'];
}
if(array_key_exists('active', $data)) {
$account->active = $data['active'];
}
if(array_key_exists('iban', $data)) {
$account->iban = $data['iban'];
}
// liability stuff:
$liabilityType = $data['liability_type'] ?? '';
if ($this->isLiability($account) && $this->isLiabilityType($liabilityType)) {
$type = $this->getAccountType($liabilityType);
$account->account_type_id = $type->id;
// set liability, but account must already be a liability.
//$liabilityType = $data['liability_type'] ?? '';
if ($this->isLiability($account) && array_key_exists('liability_type', $data)) {
$type = $this->getAccountType($data['liability_type']);
if(null !== $type) {
$account->account_type_id = $type->id;
}
}
// update virtual balance (could be set to zero if empty string).

View File

@ -42,8 +42,8 @@
<span v-for="tr in transaction.attributes.transactions">
<a v-if="'withdrawal' === tr.type" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
<a v-if="'deposit' === tr.type" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
<a v-if="'transfer' === tr.type && tr.source_id === account_id" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
<a v-if="'transfer' === tr.type && tr.destination_id === account_id" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
<a v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
<a v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
<br/>
</span>
</td>
@ -55,10 +55,10 @@
<span v-if="'deposit' === tr.type" class="text-success">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
</span>
<span v-if="'transfer' === tr.type && tr.source_id === account_id" class="text-info">
<span v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" class="text-info">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
</span>
<span v-if="'transfer' === tr.type && tr.destination_id === account_id" class="text-info">
<span v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" class="text-info">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
</span>
</span>

View File

@ -40,8 +40,8 @@
<span v-for="tr in transaction.attributes.transactions">
<a v-if="'withdrawal' === tr.type" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
<a v-if="'deposit' === tr.type" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
<a v-if="'transfer' === tr.type && tr.source_id === account_id" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
<a v-if="'transfer' === tr.type && tr.destination_id === account_id" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
<a v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
<a v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
<br/>
</span>
</td>
@ -53,10 +53,10 @@
<span v-if="'deposit' === tr.type" class="text-success">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
</span>
<span v-if="'transfer' === tr.type && tr.source_id === account_id" class="text-info">
<span v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" class="text-info">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
</span>
<span v-if="'transfer' === tr.type && tr.destination_id === account_id" class="text-info">
<span v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" class="text-info">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
</span>
</span>

View File

@ -44,10 +44,10 @@
<span v-if="'deposit' === tr.type" class="text-success">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
</span>
<span v-if="'transfer' === tr.type && tr.source_id === account_id" class="text-info">
<span v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" class="text-info">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
</span>
<span v-if="'transfer' === tr.type && tr.destination_id === account_id" class="text-info">
<span v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" class="text-info">
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
</span>
</span>

View File

@ -81,9 +81,9 @@
"first_split_overrules_source": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0447\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430",
"first_split_overrules_destination": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0447\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f",
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">\u0422\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f #{ID} (\"{title}\")<\/a> \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0430.",
"custom_period": "Custom period",
"reset_to_current": "Reset to current period",
"select_period": "Select a period",
"custom_period": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043f\u0435\u0440\u0438\u043e\u0434",
"reset_to_current": "\u0421\u0431\u0440\u043e\u0441 \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u043f\u0435\u0440\u0438\u043e\u0434\u0443",
"select_period": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0435\u0440\u0438\u043e\u0434",
"location": "\u0420\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435",
"other_budgets": "\u0411\u044e\u0434\u0436\u0435\u0442\u044b \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0440\u0435\u0437\u043e\u043a \u0432\u0440\u0435\u043c\u0435\u043d\u0438",
"journal_links": "\u0421\u0432\u044f\u0437\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -60,7 +60,7 @@ return [
'less' => ':attribute muss kleiner als 10.000.000 sein',
'active_url' => ':attribute ist keine gültige URL.',
'after' => ':attribute muss ein Datum nach :date sein.',
'date_after' => 'End date must be before start date.',
'date_after' => 'Enddatum muss nach dem Startdatum liegen.',
'alpha' => ':attribute darf nur Buchstaben enthalten.',
'alpha_dash' => ':attribute darf nur Buchstaben, Zahlen und Bindestrichen enthalten.',
'alpha_num' => ':attribute darf nur Buchstaben und Zahlen enthalten.',
@ -183,7 +183,7 @@ return [
'withdrawal_dest_need_data' => 'Um fortzufahren, benötigen Sie eine gültige Zielkontenkennung und/oder einen gültigen Zielkontonamen.',
'withdrawal_dest_bad_data' => 'Bei der Suche nach Kennung „:id” oder Name „:name” konnte kein gültiges Zielkonto gefunden werden.',
'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".',
'generic_source_bad_data' => 'Bei der Suche nach der Kennung „:id” oder dem Namen „:name” konnte kein gültiges Quellkonto gefunden werden.',
'deposit_source_need_data' => 'Um fortzufahren, benötigen Sie eine gültige Quellkontenkennung und/oder einen gültigen Quellkontonamen.',
'deposit_source_bad_data' => 'Bei der Suche nach der Kennung „:id” oder dem Namen „:name” konnte kein gültiges Quellkonto gefunden werden.',

View File

@ -60,7 +60,7 @@ return [
'less' => ':attribute doit être inférieur à 10 000 000',
'active_url' => 'Le champ :attribute n\'est pas une URL valide.',
'after' => 'Le champ :attribute doit être une date postérieure à :date.',
'date_after' => 'End date must be before start date.',
'date_after' => 'La date de fin doit être avant la date de début.',
'alpha' => 'Le champ :attribute doit seulement contenir des lettres.',
'alpha_dash' => 'Le champ :attribute peut seulement contenir des lettres, des chiffres et des tirets.',
'alpha_num' => 'Le champ :attribute peut seulement contenir des chiffres et des lettres.',
@ -183,7 +183,7 @@ return [
'withdrawal_dest_need_data' => 'Vous devez obtenir un ID de compte de destination valide et/ou un nom de compte de destination valide pour continuer.',
'withdrawal_dest_bad_data' => 'Impossible de trouver un compte de destination valide lors de la recherche de l\'ID ":id" ou du nom ":name".',
'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".',
'generic_source_bad_data' => 'Impossible de trouver un compte source valide lors de la recherche de l\'ID ":id" ou du nom ":name".',
'deposit_source_need_data' => 'Vous devez obtenir un ID de compte source valide et/ou un nom de compte source valide pour continuer.',
'deposit_source_bad_data' => 'Impossible de trouver un compte source valide lors de la recherche de l\'ID ":id" ou du nom ":name".',

View File

@ -183,7 +183,7 @@ return [
'withdrawal_dest_need_data' => 'Aby kontynuować, musisz uzyskać prawidłowy identyfikator konta wydatków i/lub prawidłową nazwę konta wydatków.',
'withdrawal_dest_bad_data' => 'Nie można znaleźć poprawnego konta wydatków podczas wyszukiwania identyfikatora ":id" lub nazwy ":name".',
'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".',
'generic_source_bad_data' => 'Nie można znaleźć poprawnego konta źródłowego podczas wyszukiwania identyfikatora ":id" lub nazwy ":name".',
'deposit_source_need_data' => 'Aby kontynuować, musisz uzyskać prawidłowy identyfikator konta źródłowego i/lub prawidłową nazwę konta źródłowego.',
'deposit_source_bad_data' => 'Nie można znaleźć poprawnego konta źródłowego podczas wyszukiwania identyfikatora ":id" lub nazwy ":name".',

View File

@ -60,7 +60,7 @@ return [
'less' => ':attribute deve ser menor do que 10.000.000',
'active_url' => 'O campo :attribute não contém um URL válido.',
'after' => 'O campo :attribute deverá conter uma data posterior a :date.',
'date_after' => 'End date must be before start date.',
'date_after' => 'A data final deve ser anterior à data inicial.',
'alpha' => 'O campo :attribute deverá conter apenas letras.',
'alpha_dash' => 'O campo :attribute deverá conter apenas letras, números e traços.',
'alpha_num' => 'O campo :attribute deverá conter apenas letras e números .',
@ -183,7 +183,7 @@ return [
'withdrawal_dest_need_data' => 'É necessário obter um ID de uma conta de destino válida e/ou um nome de conta de destino válido para continuar.',
'withdrawal_dest_bad_data' => 'Não foi possível encontrar uma conta de destino válida ao pesquisar por ID ":id" ou nome ":name".',
'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".',
'generic_source_bad_data' => 'Não foi possível encontrar uma conta de origem válida ao pesquisar pelo ID ":id" ou pelo nome ":name".',
'deposit_source_need_data' => 'É necessário obter um ID de uma conta de origem válida e/ou um nome de conta de origem válido para continuar.',
'deposit_source_bad_data' => 'Não foi possível encontrar uma conta de origem válida ao pesquisar por ID ":id" ou nome ":name".',

View File

@ -60,7 +60,7 @@ return [
'less' => ':attribute tem de ser menor que 10,000,000',
'active_url' => 'O :attribute nao e um URL valido.',
'after' => 'I :attribute tem de ser uma data depois de :date.',
'date_after' => 'End date must be before start date.',
'date_after' => 'A data final deve ser anterior à data inicial.',
'alpha' => 'O :attribute apenas pode conter letras.',
'alpha_dash' => 'O :attribute apenas pode conter letras, numero e tracos.',
'alpha_num' => 'O :attribute apenas pode conter letras e numeros.',
@ -183,7 +183,7 @@ return [
'withdrawal_dest_need_data' => 'É necessário ter um ID de conta de destino válido e/ou um nome de conta de destino válido para continuar.',
'withdrawal_dest_bad_data' => 'Não foi possível encontrar uma conta de destino válida ao pesquisar pelo ID ":id" ou nome ":name".',
'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".',
'generic_source_bad_data' => 'Não foi possível encontrar uma conta de origem válida ao pesquisar pelo ID ":id" ou nome ":name".',
'deposit_source_need_data' => 'É preciso ter um ID de uma conta de origem válida e/ou um nome de uma conta de origem válida para continuar.',
'deposit_source_bad_data' => 'Não foi possível encontrar uma conta de origem válida ao pesquisar pelo ID ":id" ou nome ":name".',

View File

@ -678,7 +678,7 @@ return [
'pref_optional_fields_transaction' => 'Дополнительные поля для транзакций',
'pref_optional_fields_transaction_help' => 'По умолчанию при создании новой транзакции включены не все поля (чтобы не создавать беспорядок). Но вы можете включить эти поля, если лично вам они могут быть полезны. Любое поле, которое в последствии будет отключено, будет по-прежнему отображаться, если оно уже заполнено (независимо от данный настроек).',
'optional_tj_date_fields' => 'Поля с датами',
'optional_tj_other_fields' => 'Other fields',
'optional_tj_other_fields' => 'Прочие поля',
'optional_tj_attachment_fields' => 'Поля вложений',
'pref_optional_tj_interest_date' => 'Дата начисления процентов',
'pref_optional_tj_book_date' => 'Дата внесения записи',
@ -689,14 +689,14 @@ return [
'pref_optional_tj_internal_reference' => 'Внутренняя ссылка',
'pref_optional_tj_notes' => 'Заметки',
'pref_optional_tj_attachments' => 'Вложения',
'pref_optional_tj_external_uri' => 'External URL',
'pref_optional_tj_location' => 'Location',
'pref_optional_tj_links' => 'Transaction links',
'pref_optional_tj_external_uri' => 'Внешний URL',
'pref_optional_tj_location' => 'Расположение',
'pref_optional_tj_links' => 'Связи транзакции',
'optional_field_meta_dates' => 'Даты',
'optional_field_meta_business' => 'Бизнес',
'optional_field_attachments' => 'Вложения',
'optional_field_meta_data' => 'Расширенные данные',
'external_uri' => 'External URL',
'external_uri' => 'Внешний URL',
// profile:
'delete_stuff_header' => 'Удалить данные',
@ -1277,9 +1277,9 @@ return [
'per_day' => 'В день',
'left_to_spend_per_day' => 'Можно тратить в день',
'bills_paid' => 'Оплаченные счета',
'custom_period' => 'Custom period',
'reset_to_current' => 'Reset to current period',
'select_period' => 'Select a period',
'custom_period' => 'Пользовательский период',
'reset_to_current' => 'Сброс к текущему периоду',
'select_period' => 'Выберите период',
// menu and titles, should be recycled as often as possible:
'currency' => 'Валюта',

View File

@ -60,7 +60,7 @@ return [
'less' => ':attribute должен быть меньше 10,000,000',
'active_url' => ':attribute не является допустимым URL-адресом.',
'after' => ':attribute должна быть позже :date.',
'date_after' => 'End date must be before start date.',
'date_after' => 'Дата окончания должна быть после даты начала.',
'alpha' => ':attribute может содержать только буквы.',
'alpha_dash' => ':attribute может содержать только буквы, числа и дефис.',
'alpha_num' => ':attribute может содержать только буквы и числа.',
@ -183,7 +183,7 @@ return [
'withdrawal_dest_need_data' => 'Для продолжения необходим действительный ID счёта назначения и/или действительное имя счёта.',
'withdrawal_dest_bad_data' => 'Не удалось найти действительный счёт назначения при поиске ID ":id" или имени ":name".',
'generic_source_bad_data' => 'Could not find a valid source account when searching for ID ":id" or name ":name".',
'generic_source_bad_data' => 'Не удалось найти корректный счёт-источник при поиске ID ":id" или имени ":name".',
'deposit_source_need_data' => 'Для продолжения необходим действительный ID счёта-источника и/или действительное имя счёта.',
'deposit_source_bad_data' => 'Не удалось найти корректный счёт-источник при поиске ID ":id" или имени ":name".',

View File

@ -61,9 +61,9 @@ class StoreControllerTest extends TestCase
/**
* @param array $submission
*
* newStoreDataProvider / emptyDataProvider
* storeDataProvider / emptyDataProvider
*
* @dataProvider newStoreDataProvider
* @dataProvider emptyDataProvider
*/
public function testStore(array $submission): void
{
@ -82,7 +82,7 @@ class StoreControllerTest extends TestCase
/**
* @return array
*/
public function newStoreDataProvider(): array
public function storeDataProvider(): array
{
// some test configs:
$configuration = new TestConfiguration;

View File

@ -22,9 +22,11 @@
namespace Tests\Api\Models\Account;
use Faker\Factory;
use Laravel\Passport\Passport;
use Log;
use Tests\Objects\Field;
use Tests\Objects\FieldSet;
use Tests\Objects\TestConfiguration;
use Tests\TestCase;
use Tests\Traits\CollectsValues;
use Tests\Traits\RandomValues;
@ -49,192 +51,176 @@ class UpdateControllerTest extends TestCase
}
/**
* @dataProvider updateDataProvider
* @param array $submission
*
* newStoreDataProvider / emptyDataProvider
*
* @dataProvider newUpdateDataProvider
*/
public function testUpdate(array $submission): void
{
$this->markTestSkipped('Skipped');
$ignore = [
'created_at',
'updated_at',
'currency_code',
'currency_symbol',
'currency_decimal_places',
'current_balance',
];
$route = route('api.v1.accounts.update', [$submission['id']]);
if ([] === $submission) {
$this->markTestSkipped('Empty provider.');
}
Log::debug('testStoreUpdated()');
Log::debug('submission :', $submission['submission']);
Log::debug('expected :', $submission['expected']);
Log::debug('ignore :', $submission['ignore']);
Log::debug('parameters :', $submission['parameters']);
$this->updateAndCompare($route, $submission, $ignore);
$route = route('api.v1.accounts.update', $submission['parameters']);
$this->updatedUpdateAndCompare($route, $submission);
}
/**
* Only create optional sets.
*
* @return array
*/
public function updateDataProvider(): array
public function newUpdateDataProvider(): array
{
$submissions = [];
$all = $this->updateDataSet();
foreach ($all as $name => $data) {
$submissions[] = [$data];
$configuration = new TestConfiguration;
// optional field sets (for all test configs)
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('name', 'uuid'));
$configuration->addOptionalFieldSet('name', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('active', 'boolean'));
$configuration->addOptionalFieldSet('active', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('iban', 'iban'));
$configuration->addOptionalFieldSet('iban', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('bic', 'bic'));
$configuration->addOptionalFieldSet('bic', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('account_number', 'iban'));
$configuration->addOptionalFieldSet('account_number', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('order', 'order'));
$configuration->addOptionalFieldSet('order', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('include_net_worth', 'boolean'));
$configuration->addOptionalFieldSet('include_net_worth', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('virtual_balance', 'random-amount'));
$configuration->addOptionalFieldSet('virtual_balance', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('virtual_balance', 'random-amount'));
$configuration->addOptionalFieldSet('virtual_balance', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$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);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$field = new Field;
$field->fieldTitle = 'currency_code';
$field->fieldType = 'random-currency-code';
$field->ignorableFields = ['currency_id'];
$field->title = 'currency_code';
$fieldSet->addField($field);
$configuration->addOptionalFieldSet('currency_code', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('account_role', 'random-asset-accountRole'));
$configuration->addOptionalFieldSet('account_role', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('notes', 'uuid'));
$configuration->addOptionalFieldSet('notes', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('latitude', 'latitude'));
$fieldSet->addField(Field::createBasic('longitude', 'longitude'));
$fieldSet->addField(Field::createBasic('zoom_level', 'random-zoom_level'));
$configuration->addOptionalFieldSet('notes', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [1];
$fieldSet->addField(Field::createBasic('opening_balance', 'random-amount'));
$fieldSet->addField(Field::createBasic('opening_balance_date', 'random-past-date'));
$configuration->addOptionalFieldSet('ob', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [7];
$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->addOptionalFieldSet('cc1', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [13];
$field = new Field;
$field->fieldTitle = 'liability_type';
$field->fieldType = 'random-liability-type';
$field->ignorableFields = ['account_role'];
$field->title = 'liability_type';
$fieldSet->addField($field);
$fieldSet->addField(Field::createBasic('account_role', 'null'));
$fieldSet->addField(Field::createBasic('credit_card_type', 'null'));
$fieldSet->addField(Field::createBasic('monthly_payment_date', 'null'));
$configuration->addOptionalFieldSet('liability-1', $fieldSet);
$fieldSet = new FieldSet;
$fieldSet->parameters = [13];
$fieldSet->addField(Field::createBasic('interest', 'random-percentage'));
$field = new Field;
$field->fieldTitle = 'interest_period';
$field->fieldType = 'random-interest-period';
$field->ignorableFields = ['account_role'];
$field->title = 'interest_period';
$fieldSet->addField($field);
$fieldSet->addField(Field::createBasic('account_role', 'null'));
$fieldSet->addField(Field::createBasic('credit_card_type', 'null'));
$fieldSet->addField(Field::createBasic('monthly_payment_date', 'null'));
$configuration->addOptionalFieldSet('liability-2', $fieldSet);
// generate submissions
$array = $configuration->generateSubmissions();
$expected = $configuration->generateExpected($array);
$parameters = $configuration->parameters;
$ignored = $configuration->ignores;
// now create a combination for each submission and associated data:
$final = [];
foreach ($array as $index => $submission) {
$final[] = [[
'submission' => $submission,
'expected' => $expected[$index],
'ignore' => $ignored[$index] ?? [],
'parameters' => $parameters[$index],
]];
}
return $submissions;
return $final;
}
/**
* @return array
*/
public function updateDataSet(): array
{
$faker = Factory::create();
$currencies = ['EUR', 'GBP', 'USD', 'HUF'];
$currencyCode = $currencies[rand(0, count($currencies) - 1)];
$accountRoles = ['defaultAsset', 'sharedAsset', 'savingAsset'];
$accountRole = $accountRoles[rand(0, count($accountRoles) - 1)];
$liabilityRoles = ['loan', 'debt', 'mortgage'];
$liabilityRole = $liabilityRoles[rand(0, count($liabilityRoles) - 1)];
$interestPeriods = ['daily', 'monthly', 'yearly'];
$interestPeriod = $interestPeriods[rand(0, count($interestPeriods) - 1)];
$set = [
'name' => [
'id' => 1,
'fields' => [
'name' => ['test_value' => $faker->uuid],
],
'extra_ignore' => [],
],
'active' => [
'id' => 1,
'fields' => [
'active' => ['test_value' => $faker->boolean],
],
'extra_ignore' => [],
],
'iban' => [
'id' => 1,
'fields' => [
'iban' => ['test_value' => $faker->iban()],
],
'extra_ignore' => [],
],
'bic' => [
'id' => 1,
'fields' => [
'bic' => ['test_value' => $faker->swiftBicNumber],
],
'extra_ignore' => [],
],
'account_number' => [
'id' => 1,
'fields' => [
'account_number' => ['test_value' => $faker->iban()],
],
'extra_ignore' => [],
],
'order' => [
'id' => 1,
'fields' => [
'order' => ['test_value' => $faker->numberBetween(1, 10)],
],
'extra_ignore' => [],
],
'include_net_worth' => [
'id' => 1,
'fields' => [
'include_net_worth' => ['test_value' => $faker->boolean],
],
'extra_ignore' => [],
],
'virtual_balance' => [
'id' => 1,
'fields' => [
'virtual_balance' => ['test_value' => number_format($faker->randomFloat(2, 10, 100), 2)],
],
'extra_ignore' => [],
],
'currency_id' => [
'id' => 1,
'fields' => [
'currency_id' => ['test_value' => (string)$faker->numberBetween(1, 10)],
],
'extra_ignore' => ['currency_code'],
],
'currency_code' => [
'id' => 1,
'fields' => [
'currency_code' => ['test_value' => $currencyCode],
],
'extra_ignore' => ['currency_id'],
],
'account_role' => [
'id' => 1,
'fields' => [
'account_role' => ['test_value' => $accountRole],
],
'extra_ignore' => [],
],
'notes' => [
'id' => 1,
'fields' => [
'notes' => ['test_value' => join(' ', $faker->words(3))],
],
'extra_ignore' => [],
],
'location' => [
'id' => 1,
'fields' => [
'longitude' => ['test_value' => $faker->longitude],
'latitude' => ['test_value' => $faker->latitude],
'zoom_level' => ['test_value' => $faker->numberBetween(1, 10)],
],
'extra_ignore' => [],
],
'ob' => [
'id' => 1,
'fields' => [
'opening_balance' => ['test_value' => number_format($faker->randomFloat(2, 10, 100), 2)],
'opening_balance_date' => ['test_value' => $faker->date('Y-m-d')],
],
'extra_ignore' => [],
],
'cc2' => [
'id' => 7,
'fields' => [
'monthly_payment_date' => ['test_value' => $faker->date('Y-m-d')],
],
'extra_ignore' => [],
],
'cc3' => [
'id' => 7,
'fields' => [
'monthly_payment_date' => ['test_value' => $faker->date('Y-m-d')],
'credit_card_type' => ['test_value' => 'monthlyFull'],
],
'extra_ignore' => [],
],
'liabilityA' => [
'id' => 13,
'fields' => [
'liability_type' => ['test_value' => $liabilityRole],
],
'extra_ignore' => [],
],
'liabilityB' => [
'id' => 13,
'fields' => [
'interest' => ['test_value' => $faker->randomFloat(2, 1, 99)],
'interest_period' => ['test_value' => $interestPeriod],
],
'extra_ignore' => [],
],
];
return $set;
}
}

View File

@ -10,13 +10,15 @@ class FieldSet
{
public ?array $fields;
public string $title;
public ?array $parameters;
/**
* FieldSet constructor.
*/
public function __construct()
{
$this->fields = [];
$this->fields = [];
$this->parameters = [];
}
/**

View File

@ -16,6 +16,7 @@ class TestConfiguration
private array $submission;
protected const MAX_ITERATIONS = 3;
public array $ignores;
public array $parameters;
/**
* TestConfiguration constructor.
@ -26,6 +27,7 @@ class TestConfiguration
$this->mandatoryFieldSets = [];
$this->optionalFieldSets = [];
$this->ignores = [];
$this->parameters = [];
}
/**
@ -177,7 +179,8 @@ class TestConfiguration
$result = $this->parseField($result, $field);
$ignore = array_unique($ignore + $field->ignorableFields);
}
$this->ignores[] = $ignore;
$this->ignores[] = $ignore;
$this->parameters[] = $set->parameters ?? [];
return $result;
}
@ -227,9 +230,9 @@ class TestConfiguration
// 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)));
$count = count($this->submission);
$currentIgnoreSet = $this->ignores[$count] ?? [];
//$this->ignores[$count] = array_unique(array_values(array_merge($currentIgnoreSet, $field->ignorableFields)));
}
}
}
@ -239,9 +242,87 @@ class TestConfiguration
}
}
// no mandatory sets? Loop the optional sets:
if (0 === count($this->mandatoryFieldSets)) {
// expand the standard submission with extra sets from the optional field set.
$setCount = count($this->optionalFieldSets);
// echo "there are " . $setCount . " optional sets\n";
if (0 !== $setCount) {
$keys = array_keys($this->optionalFieldSets);
// echo " keys to consider are: " . join(', ', $keys) . "\n";
$maxCount = count($keys) > self::MAX_ITERATIONS ? self::MAX_ITERATIONS : count($keys);
// echo " max count is " . $maxCount . "\n";
for ($i = 1; $i <= $maxCount; $i++) {
$combinationSets = $this->combinationsOf($i, $keys);
// echo " will create " . count($combinationSets) . " extra sets.\n";
foreach ($combinationSets as $ii => $combinationSet) {
// echo " Set " . ($ii + 1) . "/" . count($combinationSets) . " will consist of:\n";
// the custom set is born!
//$custom = $this->toArray($set);
$custom = [];
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)));
}
}
$count = count($this->submission);
$this->parameters[$count] = $customSet->parameters ?? [];
}
$this->submission[] = $custom;
}
}
}
}
return $this->submission;
}
/**
* @param array $submissions
*
* @return array
*/
public function generateParameters(array $submissions): array
{
$params = [];
$index = 0;
/** @var array $submission */
foreach ($submissions as $submission) {
// last one defined param
$submission = array_reverse($submission);
foreach ($submission as $key => $value) {
if (array_key_exists($key, $this->optionalFieldSets)) {
/** @var FieldSet $fieldSet */
$fieldSet = $this->optionalFieldSets[$key];
if (null !== $fieldSet->parameters) {
$params[$index] = $fieldSet->parameters;
continue;
}
if (null !== $fieldSet->parameters) {
$params[$index] = [];
}
}
}
$index++;
}
return $params;
}
/**
* @param array $current
* @param Field $field
@ -328,6 +409,8 @@ class TestConfiguration
return $faker->longitude;
case 'random-zoom_level':
return $faker->numberBetween(1, 12);
case 'null':
return null;
}
}

View File

@ -210,7 +210,6 @@ trait TestHelpers
// var_dump($expected[$key]);
// exit;
}
}
}
@ -222,10 +221,9 @@ trait TestHelpers
*/
protected function storeAndCompare(string $route, array $content): void
{
$submission = $content['fields'];
$parameters = $content['parameters'];
$ignore = $content['ignore'];
// submit!
$submission = $content['fields'];
$parameters = $content['parameters'];
$ignore = $content['ignore'];
$response = $this->post(route($route, $parameters), $submission, ['Accept' => 'application/json']);
$responseBody = $response->content();
$responseJson = json_decode($responseBody, true);
@ -257,6 +255,62 @@ trait TestHelpers
}
}
/**
* @param string $route
* @param array $content
*/
protected function updatedUpdateAndCompare(string $route, array $content): void
{
$submission = $content['submission'];
$ignore = $content['ignore'];
$response = $this->put($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->updatedCompareUpdatedArray($route, $submission, $responseAttributes, $ignore);
}
/**
* @param string $url
* @param array $submission
* @param array $response
* @param array $ignore
*/
private function updatedCompareUpdatedArray(string $url, array $submission, array $response, array $ignore): void
{
foreach ($response as $key => $value) {
if (is_array($value) && array_key_exists($key, $submission) && is_array($submission[$key])) {
$this->updatedCompareUpdatedArray($url, $submission[$key], $value, $ignore[$key] ?? []);
}
if (isset($submission[$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\nURL: %s",
$key,
var_export($value, true),
var_export($submission[$key], true),
json_encode($submission),
json_encode($ignore),
json_encode($response),
$url
);
$this->assertEquals($value, $submission[$key], $message);
}
}
}
}
/**
* Some specials:
*