Fix some tests for account API

This commit is contained in:
James Cole
2021-03-13 12:01:01 +01:00
parent 668b169a5e
commit 7118abe28d
29 changed files with 992 additions and 315 deletions

View File

@@ -0,0 +1,238 @@
<?php
/*
* StoreControllerTest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Tests\Api\Models\Account;
use Faker\Factory;
use Laravel\Passport\Passport;
use Log;
use Tests\TestCase;
use Tests\Traits\CollectsValues;
use Tests\Traits\RandomValues;
use Tests\Traits\TestHelpers;
/**
* Class StoreControllerTest
*/
class StoreControllerTest extends TestCase
{
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
*
* @dataProvider storeAccountDataProvider
*/
public function testStore(array $submission): void
{
// run account store with a minimal data set:
$route = 'api.v1.accounts.store';
$this->submitAndCompare($route, $submission);
}
/**
* @return array
*/
public function storeAccountDataProvider(): array
{
$minimalSets = $this->minimalSets();
$optionalSets = $this->optionalSets();
$regenConfig = [
'name' => function () {
$faker = Factory::create();
return $faker->name;
},
'iban' => function () {
$faker = Factory::create();
return $faker->iban();
},
'account_number' => function () {
$faker = Factory::create();
return $faker->iban();
},
];
return $this->genericDataProvider($minimalSets, $optionalSets, $regenConfig);
}
/**
* @return \array[][]
*/
private function optionalSets(): array
{
$faker = Factory::create();
$currencies = [
1 => 'EUR',
2 => 'HUF',
3 => 'GBP',
4 => 'UAH',
];
$rand = rand(1, 4);
return [
'active' => [
'fields' => [
'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),
// ],
// ],
];
}
/**
* @return array
*/
private function minimalSets(): array
{
$faker = Factory::create();
return [
'asset' => [
'fields' => [
'name' => $faker->name . join(' ', $faker->words(2)),
'type' => 'asset',
'account_role' => $this->randomAccountRole(),
],
],
'expense' => [
'fields' => [
'name' => $faker->name,
'type' => 'expense',
],
],
'liability' => [
'fields' => [
'name' => $faker->name,
'type' => 'liabilities',
'liability_type' => $this->randomLiabilityType(),
'liability_amount' => $this->getRandomAmount(),
'liability_start_date' => $this->getRandomDateString(),
'interest' => $this->getRandomPercentage(),
'interest_period' => $this->getRandomInterestPeriod(),
],
],
'cc' => [
'fields' => [
'name' => $faker->name,
'type' => 'asset',
'account_role' => 'ccAsset',
'credit_card_type' => 'monthlyFull',
'monthly_payment_date' => $this->getRandomDateString(),
],
],
];
}
/**
* @param string $area
* @param string $left
* @param string $right
*
* @return bool
*/
private function ignoreCombination(string $area, string $left, string $right): bool
{
Log::debug(sprintf('Must ignore %s: %s vs %s?', $area, $left, $right));
if ('store-account' === $area) {
if ('expense' === $left && in_array($right, ['virtual_balance', 'opening_balance', 'opening_balance_date'])) {
Log::debug('Yes');
return true;
}
}
Log::debug('NO');
return false;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*
* UpdateControllerTest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Tests\Api\Models\Account;
use Laravel\Passport\Passport;
use Tests\TestCase;
use Log;
/**
* Class UpdateControllerTest
*/
class UpdateControllerTest extends TestCase
{
/**
*
*/
public function setUp(): void
{
parent::setUp();
Passport::actingAs($this->user());
Log::info(sprintf('Now in %s.', get_class($this)));
}
/**
*
*/
public function testUpdate(): void {
}
}

View File

@@ -33,8 +33,6 @@ abstract class TestCase extends BaseTestCase
{
use CreatesApplication, CollectsValues;
// MocksDefaultValues TestHelpers
/**
* @return array
*/

View File

@@ -50,197 +50,208 @@ trait CollectsValues
{
return User::where('email', 'james@firefly')->first();
}
/**
* @return User
*/
public function nonAdminUser(): User
{
return User::where('email', 'no_admin@firefly')->first();
}
/**
* @return Budget
*/
public function getRandomBudget(): Budget
{
return $this->user()->budgets()->inRandomOrder()->first();
}
/**
* @return Category
*/
public function getRandomCategory(): Category
{
return $this->user()->categories()->inRandomOrder()->first();
}
/**
* @return Bill
*/
public function getRandomBill(): Bill
{
return $this->user()->bills()->inRandomOrder()->first();
}
/**
* @return PiggyBank
*/
public function getRandomPiggyBank(): PiggyBank
{
return $this->user()->piggyBanks()->inRandomOrder()->first();
}
/**
* @return Tag
*/
public function getRandomTag(): Tag
{
return $this->user()->tags()->inRandomOrder()->first();
}
/**
* @return TransactionJournal
*/
public function getRandomWithdrawal(): TransactionJournal
{
return $this->getRandomJournal(TransactionType::WITHDRAWAL);
}
/**
* @return TransactionJournal
*/
public function getRandomTransfer(): TransactionJournal
{
return $this->getRandomJournal(TransactionType::TRANSFER);
}
/**
* @return TransactionJournal
*/
public function getRandomDeposit(): TransactionJournal
{
return $this->getRandomJournal(TransactionType::DEPOSIT);
}
/**
* @param string $type
* @return TransactionJournal
* @throws FireflyException
*/
private function getRandomJournal(string $type): TransactionJournal
{
$query = DB::table('transactions')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_journals.user_id', $this->user()->id)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->where('transaction_types.type', $type)
->groupBy('transactions.transaction_journal_id')
->having('ct', '=', 2)
->inRandomOrder()->take(1);
$result = $query->get(
[
'transactions.transaction_journal_id',
'transaction_journals.transaction_type_id',
DB::raw('COUNT(transaction_journal_id) as ct'),
]
)->first();
if (null === $result) {
throw new FireflyException(sprintf('Cannot find suitable journal "%s" to use.', $type));
}
return TransactionJournal::find((int) $result->transaction_journal_id);
}
/**
* @return TransactionCurrency
*/
public function getEuro(): TransactionCurrency
{
return TransactionCurrency::whereCode('EUR')->first();
}
/**
* @return TransactionCurrency
*/
public function getDollar(): TransactionCurrency
{
return TransactionCurrency::whereCode('USD')->first();
}
/**
* @param int|null $except
*
* @return Account
*/
public function getRandomAsset(?int $except = null): Account
{
return $this->getRandomAccount(AccountType::ASSET, $except);
}
/**
* @param int|null $except
*
* @return Account
*/
public function getRandomDebt(?int $except = null): Account
{
return $this->getRandomAccount(AccountType::DEBT, $except);
}
/**
* @param int|null $except
*
* @return Account
*/
public function getRandomLoan(?int $except = null): Account
{
return $this->getRandomAccount(AccountType::LOAN, $except);
}
/**
* @param int|null $except
*
* @return Account
*/
public function getRandomRevenue(?int $except = null): Account
{
return $this->getRandomAccount(AccountType::REVENUE, $except);
}
/**
* @param int|null $except
*
* @return Account
*/
public function getRandomExpense(?int $except = null): Account
{
return $this->getRandomAccount(AccountType::EXPENSE, $except);
}
/**
* @param string $type
*
* @param int|null $except
*
* @return Account
*/
private function getRandomAccount(string $type, ?int $except): Account
{
$query = Account::
leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->whereNull('accounts.deleted_at')
->where('accounts.user_id', $this->user()->id)
->where('account_types.type', $type)
->inRandomOrder()->take(1);
if (null !== $except) {
$query->where('accounts.id', '!=', $except);
}
return $query->first(['accounts.*']);
}
//
// /**
// * @return User
// */
// public function nonAdminUser(): User
// {
// return User::where('email', 'no_admin@firefly')->first();
// }
//
// /**
// * @return Budget
// */
// public function getRandomBudget(): Budget
// {
// return $this->user()->budgets()->inRandomOrder()->first();
// }
//
// /**
// * @return Category
// */
// public function getRandomCategory(): Category
// {
// return $this->user()->categories()->inRandomOrder()->first();
// }
//
// /**
// * @return Bill
// */
// public function getRandomBill(): Bill
// {
// return $this->user()->bills()->inRandomOrder()->first();
// }
//
// /**
// * @return PiggyBank
// */
// public function getRandomPiggyBank(): PiggyBank
// {
// return $this->user()->piggyBanks()->inRandomOrder()->first();
// }
//
//
// /**
// * @return Tag
// */
// public function getRandomTag(): Tag
// {
// return $this->user()->tags()->inRandomOrder()->first();
// }
//
// /**
// * @return TransactionJournal
// */
// public function getRandomWithdrawal(): TransactionJournal
// {
// return $this->getRandomJournal(TransactionType::WITHDRAWAL);
// }
//
// /**
// * @return TransactionJournal
// */
// public function getRandomTransfer(): TransactionJournal
// {
// return $this->getRandomJournal(TransactionType::TRANSFER);
// }
//
// /**
// * @return TransactionJournal
// */
// public function getRandomDeposit(): TransactionJournal
// {
// return $this->getRandomJournal(TransactionType::DEPOSIT);
// }
//
// /**
// * @param string $type
// *
// * @return TransactionJournal
// * @throws FireflyException
// */
// private function getRandomJournal(string $type): TransactionJournal
// {
// $query = DB::table('transactions')
// ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
// ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
// ->where('transaction_journals.user_id', $this->user()->id)
// ->whereNull('transaction_journals.deleted_at')
// ->whereNull('transactions.deleted_at')
// ->where('transaction_types.type', $type)
// ->groupBy('transactions.transaction_journal_id')
// ->having('ct', '=', 2)
// ->inRandomOrder()->take(1);
// $result = $query->get(
// [
// 'transactions.transaction_journal_id',
// 'transaction_journals.transaction_type_id',
// DB::raw('COUNT(transaction_journal_id) as ct'),
// ]
// )->first();
// if (null === $result) {
// throw new FireflyException(sprintf('Cannot find suitable journal "%s" to use.', $type));
// }
//
// return TransactionJournal::find((int)$result->transaction_journal_id);
//
// }
//
// /**
// * @return TransactionCurrency
// */
// public function getEuro(): TransactionCurrency
// {
// return TransactionCurrency::whereCode('EUR')->first();
// }
//
// /**
// * @return TransactionCurrency
// */
// public function getRandomCurrency(): TransactionCurrency
// {
// return TransactionCurrency::where('code', '!=', 'EUR')->inRandomOrder()->first();
// }
//
// /**
// * @return TransactionCurrency
// */
// public function getDollar(): TransactionCurrency
// {
// return TransactionCurrency::whereCode('USD')->first();
// }
//
// /**
// * @param int|null $except
// *
// * @return Account
// */
// public function getRandomAsset(?int $except = null): Account
// {
// return $this->getRandomAccount(AccountType::ASSET, $except);
// }
//
// /**
// * @param int|null $except
// *
// * @return Account
// */
// public function getRandomDebt(?int $except = null): Account
// {
// return $this->getRandomAccount(AccountType::DEBT, $except);
// }
//
// /**
// * @param int|null $except
// *
// * @return Account
// */
// public function getRandomLoan(?int $except = null): Account
// {
// return $this->getRandomAccount(AccountType::LOAN, $except);
// }
//
// /**
// * @param int|null $except
// *
// * @return Account
// */
// public function getRandomRevenue(?int $except = null): Account
// {
// return $this->getRandomAccount(AccountType::REVENUE, $except);
// }
//
// /**
// * @param int|null $except
// *
// * @return Account
// */
// public function getRandomExpense(?int $except = null): Account
// {
// return $this->getRandomAccount(AccountType::EXPENSE, $except);
// }
//
// /**
// * @param string $type
// *
// * @param int|null $except
// *
// * @return Account
// */
// private function getRandomAccount(string $type, ?int $except): Account
// {
// $query = Account::
// leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
// ->whereNull('accounts.deleted_at')
// ->where('accounts.user_id', $this->user()->id)
// ->where('account_types.type', $type)
// ->inRandomOrder()->take(1);
// if (null !== $except) {
// $query->where('accounts.id', '!=', $except);
// }
//
// return $query->first(['accounts.*']);
// }
}

View File

@@ -0,0 +1,34 @@
<?php
/*
* FakeValues.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Tests\Traits;
trait FakeValues
{
// /**
// * @return string
// */
// protected function fakeName(): string {
// return '';
// }
}

View File

@@ -31,17 +31,17 @@ use FireflyConfig;
*/
trait MocksDefaultValues
{
public function mockDefaultConfiguration(): void
{
$falseConfig = new Configuration;
$falseConfig->data = false;
$idConfig = new Configuration;
$idConfig->data = 'abc';
FireflyConfig::shouldReceive('get')->withArgs(['is_demo_site', false])->andReturn($falseConfig);
FireflyConfig::shouldReceive('get')->withArgs(['installation_id', null])->andReturn($idConfig);
}
// public function mockDefaultConfiguration(): void
// {
//
// $falseConfig = new Configuration;
// $falseConfig->data = false;
//
// $idConfig = new Configuration;
// $idConfig->data = 'abc';
//
// FireflyConfig::shouldReceive('get')->withArgs(['is_demo_site', false])->andReturn($falseConfig);
// FireflyConfig::shouldReceive('get')->withArgs(['installation_id', null])->andReturn($idConfig);
// }
}

View File

@@ -0,0 +1,126 @@
<?php
/*
* RandomValues.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace Tests\Traits;
use Carbon\Carbon;
/**
* Trait RandomValues
*/
trait RandomValues
{
/**
* @param $k
* @param $xs
*
* @return array|array[]
*/
protected function combinationsOf($k, $xs): array
{
if ($k === 0) {
return [[]];
}
if (count($xs) === 0) {
return [];
}
$x = $xs[0];
$xs1 = array_slice($xs, 1, count($xs) - 1);
$res1 = $this->combinationsOf($k - 1, $xs1);
for ($i = 0; $i < count($res1); $i++) {
array_splice($res1[$i], 0, 0, $x);
}
$res2 = $this->combinationsOf($k, $xs1);
return array_merge($res1, $res2);
}
/**
* @return string
*/
protected function randomAccountRole(): string
{
return $this->randomFromArray(['defaultAsset', 'sharedAsset', 'savingAsset']);
}
/**
* @return string
*/
protected function randomLiabilityType(): string
{
return $this->randomFromArray(['loan', 'debt', 'mortgage']);
}
/**
* @return string
*/
protected function getRandomCurrencyCode(): string
{
return $this->randomFromArray(['EUR', 'USD', 'GBP']);
}
/**
* @return string
*/
protected function getRandomAmount(): string
{
return number_format(rand(1000, 100000) / 100, '2', '.');
}
/**
* @return string
*/
protected function getRandomDateString(): string
{
$date = Carbon::now();
$date->subDays(rand(10, 100));
return $date->format('Y-m-d');
}
/**
* @return string
*/
protected function getRandomPercentage(): string
{
return rand(1, 10000) / 100;
}
/**
* @return string
*/
protected function getRandomInterestPeriod(): string
{
return $this->randomFromArray(['daily', 'monthly', 'yearly']);
}
/**
* @param array $array
*
* @return mixed
*/
private function randomFromArray(array $array)
{
return $array[rand(0, count($array) - 1)];
}
}

View File

@@ -22,6 +22,7 @@
declare(strict_types=1);
namespace Tests\Traits;
use Exception;
use Log;
@@ -30,6 +31,51 @@ use Log;
*/
trait TestHelpers
{
/**
* @param array $minimalSets
* @param array $startOptionalSets
* @param array $regenConfig
*
* @return array
*/
protected function genericDataProvider(array $minimalSets, array $startOptionalSets, array $regenConfig): array
{
$submissions = [];
foreach ($minimalSets as $set) {
$body = [];
foreach ($set['fields'] as $field => $value) {
$body[$field] = $value;
}
// minimal set is part of all submissions:
$submissions[] = [$body];
// then loop and add fields:
$optionalSets = $startOptionalSets;
$keys = array_keys($optionalSets);
$submissions = [];
for ($i = 1; $i <= count($keys); $i++) {
$combinations = $this->combinationsOf($i, $keys);
// expand body with N extra fields:
foreach ($combinations as $extraFields) {
$second = $body;
foreach ($extraFields as $extraField) {
// now loop optional sets on $extraField and add whatever the config is:
foreach ($optionalSets[$extraField]['fields'] as $newField => $newValue) {
$second[$newField] = $newValue;
}
}
$second = $this->regenerateValues($second, $regenConfig);
$submissions[] = [$second];
}
}
unset($second);
}
return $submissions;
}
/**
* @return int
*/
@@ -45,4 +91,123 @@ trait TestHelpers
return $result;
}
/**
* @param $set
* @param $opts
*
* @return array
*/
protected function regenerateValues($set, $opts): array
{
foreach ($opts as $key => $func) {
if (array_key_exists($key, $set)) {
$set[$key] = $func();
}
}
return $set;
}
protected function submitAndCompare(string $route, array $submission): void {
// submit!
$response = $this->post(route($route), $submission, ['Accept' => 'application/json']);
$responseBody = $response->content();
$responseJson = json_decode($responseBody, true);
$message = sprintf('Status code is %d and body is %s', $response->getStatusCode(), $responseBody);
$this->assertEquals($response->getStatusCode(), 200, $message);
$response->assertHeader('Content-Type', 'application/vnd.api+json');
// compare results:
foreach ($responseJson['data']['attributes'] as $returnName => $returnValue) {
if (array_key_exists($returnName, $submission)) {
if ($this->ignoreCombination('store-account', $submission['type'], $returnName)) {
continue;
}
$message = sprintf(
"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 string $route
* @param array $minimalSets
* @param array $startOptionalSets
* @param array $regenConfig
*/
protected function runBasicStoreTest(string $route, array $minimalSets, array $startOptionalSets, array $regenConfig): void
{
// test API
foreach ($minimalSets as $set) {
$body = [];
foreach ($set['fields'] as $field => $value) {
$body[$field] = $value;
}
// submit minimal set:
Log::debug(sprintf('Submitting: %s', json_encode($body)));
$response = $this->post(route($route), $body, ['Accept' => 'application/json']);
$response->assertStatus(200);
$response->assertHeader('Content-Type', 'application/vnd.api+json');
// then loop and add fields:
$optionalSets = $startOptionalSets;
$keys = array_keys($optionalSets);
$submissions = [];
for ($i = 1; $i <= count($keys); $i++) {
$combinations = $this->combinationsOf($i, $keys);
// expand body with N extra fields:
foreach ($combinations as $extraFields) {
$second = $body;
foreach ($extraFields as $extraField) {
// now loop optional sets on $extraField and add whatever the config is:
foreach ($optionalSets[$extraField]['fields'] as $newField => $newValue) {
$second[$newField] = $newValue;
}
}
$second = $this->regenerateValues($second, $regenConfig);
$submissions[] = $second;
}
}
unset($second);
// count and progress maybe
// all submissions counted and submitted:
foreach ($submissions as $submission) {
Log::debug(sprintf('Submitting: %s', json_encode($submission)));
// submit again!
$response = $this->post(route($route), $submission, ['Accept' => 'application/json']);
$responseBody = $response->content();
$responseJson = json_decode($responseBody, true);
$message = sprintf('Status code is %d and body is %s', $response->getStatusCode(), $responseBody);
$this->assertEquals($response->getStatusCode(), 200, $message);
$response->assertHeader('Content-Type', 'application/vnd.api+json');
// compare results:
foreach ($responseJson['data']['attributes'] as $returnName => $returnValue) {
if (array_key_exists($returnName, $submission)) {
if ($this->ignoreCombination('store-account', $submission['type'], $returnName)) {
continue;
}
$message = sprintf(
"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);
}
}
}
}
}
}