Merge branch '2025_11_21_test_refactor' into v5-develop

This commit is contained in:
David Bomba 2025-11-21 22:08:18 +11:00
commit f7c65b3cc9
50 changed files with 801 additions and 522 deletions

View File

@ -140,6 +140,10 @@ class BaseTransformer
public function getFrequency($frequency = RecurringInvoice::FREQUENCY_MONTHLY): int
{
// if(is_string($frequency)){
// $frequency = strtolower(trim($frequency));
// }
switch ($frequency) {
case RecurringInvoice::FREQUENCY_DAILY:
case 'daily':

View File

@ -55,6 +55,8 @@ trait SavesDocuments
public function saveDocument($document, $entity, $force_save = false)
{
$is_public = true;
if ($entity instanceof Company) {
$account = $entity->account;
$company = $entity;

View File

@ -127,7 +127,7 @@
"friendsofphp/php-cs-fixer": "^3.14",
"laracasts/cypress": "^3.0",
"larastan/larastan": "^2",
"laravel/boost": "^1.0",
"laravel/boost": "^1.8",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^8.1",
"phpstan/phpstan": "^1.9",

898
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@ class ActivityApiTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -23,6 +23,8 @@ class ApplePayDomainMerchantUrlTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -30,6 +30,8 @@ class BankTransactionRuleTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -29,6 +29,8 @@ class BankTransactionTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -25,6 +25,8 @@ class BankTransactionRuleApiTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -24,6 +24,8 @@ class ClientModelTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -25,6 +25,8 @@ class ClientPresenterTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -33,6 +33,8 @@ class CompanyGatewayApiTest extends TestCase
use MakesHash;
use DatabaseTransactions;
use MockAccountData;
public $faker;
use CompanyGatewayFeesAndLimitsSaver;
protected function setUp(): void

View File

@ -29,6 +29,8 @@ class CompanyGatewayTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public $faker;
// use RefreshDatabase;
protected function setUp(): void

View File

@ -31,6 +31,8 @@ class CompanySettingsTest extends TestCase
use MakesHash;
use DatabaseTransactions;
use MockAccountData;
public $faker;
// use RefreshDatabase;
public function setUp(): void

View File

@ -32,6 +32,8 @@ class CompanyTokenApiTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -30,6 +30,8 @@ class DeleteInvoiceTest extends TestCase
{
use DatabaseTransactions;
use MockAccountData;
public $faker;
use MakesHash;
protected function setUp(): void

View File

@ -541,12 +541,16 @@ class PeppolTest extends TestCase
[
'cbc:StartDate' => $invoice->date,
'cbc:EndDate' => $invoice->due_date ?? $invoice->date,
'StartDate' => $invoice->date,
'EndDate' => $invoice->due_date ?? $invoice->date,
]
]
]
];
$invoice->save();
$this->assertNotNull($invoice->e_invoice->Invoice->InvoicePeriod[0]->StartDate); //@phpstan-ignore-line
$repo = new InvoiceRepository();
$invoice = $repo->save([], $invoice);
$invoice = $invoice->service()->markSent()->save();
@ -676,6 +680,8 @@ class PeppolTest extends TestCase
[
'cbc:StartDate' => $invoice->date,
'cbc:EndDate' => $invoice->due_date ?? $invoice->date,
'StartDate' => $invoice->date,
'EndDate' => $invoice->due_date ?? $invoice->date,
]
]
]
@ -723,6 +729,8 @@ class PeppolTest extends TestCase
[
'cbc:StartDate' => $invoice->date,
'cbc:EndDate' => $invoice->due_date ?? $invoice->date,
'StartDate' => $invoice->date,
'EndDate' => $invoice->due_date ?? $invoice->date,
]
]
]

View File

@ -34,6 +34,8 @@ class CsvImportTest extends TestCase
use MakesHash;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();
@ -133,6 +135,11 @@ class CsvImportTest extends TestCase
$this->assertTrue($base_transformer->hasRecurringInvoice('54'));
$this->assertTrue($base_transformer->hasRecurringInvoice('781'));
$r = \App\Models\RecurringInvoice::where('number', '781')->first();
$this->assertEquals(\App\Models\RecurringInvoice::FREQUENCY_ANNUALLY, $r->frequency_id);
}

View File

@ -41,7 +41,7 @@ class QuickbooksMappingTest extends TestCase
parent::setUp();
if (config('ninja.testvars.travis') !== false) {
if (config('ninja.testvars.travis') !== false || !config('services.quickbooks.client_id')) {
$this->markTestSkipped('Skip test for GH Actions');
}

View File

@ -403,3 +403,4 @@ Ms. Alena Cassin,golden.green@example.org,always,monthly,endless,777,$17.94,$12.
Ms. Alena Cassin,golden.green@example.org,always,monthly,endless,778,$14.88,$7.97,,Partial,2020-02-27,2019-11-29,,$0.00,,,,sed,In nulla eos ipsam molestias. Perferendis sunt et consequuntur qui ex nesciunt et. Amet animi aut dicta qui facilis voluptatem.,4.96,3
Ms. Alena Cassin,golden.green@example.org,always,monthly,endless,779,$49.00,$28.77,,Partial,2019-10-25,2020-01-10,,$0.00,,,,facere,Reiciendis voluptas unde et ut. Omnis dolorum modi facere exercitationem fuga. Eum recusandae ut ea qui autem.,4.9,10
Ms. Alena Cassin,golden.green@example.org,always,monthly,endless,780,$51.03,$51.03,,Paid,2019-12-01,2020-01-14,,$0.00,,,,voluptas,Saepe eius placeat sit mollitia magni. Porro ipsam praesentium tempora iste. Suscipit dolorem omnis eligendi corrupti est nobis.,7.29,7
Ms. Alena Cassin,golden.green@example.org,always,yearly,endless,781,$51.03,$51.03,,Paid,2019-12-01,2020-01-14,,$0.00,,,,voluptas,Saepe eius placeat sit mollitia magni. Porro ipsam praesentium tempora iste. Suscipit dolorem omnis eligendi corrupti est nobis.,7.29,7

1 Invoice Ninja v4.5.17 - December 19, 2020 11:28 pm
403 Ms. Alena Cassin golden.green@example.org always monthly endless 778 $14.88 $7.97 Partial 2020-02-27 2019-11-29 $0.00 sed In nulla eos ipsam molestias. Perferendis sunt et consequuntur qui ex nesciunt et. Amet animi aut dicta qui facilis voluptatem. 4.96 3
404 Ms. Alena Cassin golden.green@example.org always monthly endless 779 $49.00 $28.77 Partial 2019-10-25 2020-01-10 $0.00 facere Reiciendis voluptas unde et ut. Omnis dolorum modi facere exercitationem fuga. Eum recusandae ut ea qui autem. 4.9 10
405 Ms. Alena Cassin golden.green@example.org always monthly endless 780 $51.03 $51.03 Paid 2019-12-01 2020-01-14 $0.00 voluptas Saepe eius placeat sit mollitia magni. Porro ipsam praesentium tempora iste. Suscipit dolorem omnis eligendi corrupti est nobis. 7.29 7
406 Ms. Alena Cassin golden.green@example.org always yearly endless 781 $51.03 $51.03 Paid 2019-12-01 2020-01-14 $0.00 voluptas Saepe eius placeat sit mollitia magni. Porro ipsam praesentium tempora iste. Suscipit dolorem omnis eligendi corrupti est nobis. 7.29 7

View File

@ -70,6 +70,8 @@ use App\Repositories\RecurringInvoiceRepository;
use App\Factory\InvoiceToRecurringInvoiceFactory;
use App\Repositories\CreditRepository;
use Faker\Generator;
/**
* Class MockAccountData.
*/
@ -78,126 +80,132 @@ trait MockAccountData
use MakesHash;
use GeneratesCounter;
public $credit_calc;
public mixed $credit_calc = null;
public $invoice_calc;
public $quote_calc;
public $recurring_invoice_calc;
/**
* @var
* @var Project|null
*/
public $project;
/**
* @var
* @var Account|null
*/
public $account;
/**
* @var
* @var Company|null
*/
public $company;
/**
* @var
* @var User|null
*/
public $user;
/**
* @var
* @var Client|null
*/
public $client;
/**
* @var
* @var CompanyToken|string|null
*/
public $token;
/**
* @var
* @var RecurringExpense|null
*/
public $recurring_expense;
/**
* @var
* @var RecurringQuote|null
*/
public $recurring_quote;
/**
* @var \App\Models\Credit
* @var Credit|null
*/
public $credit;
/**
* @var \App\Models\Invoice
* @var \App\Models\Invoice|null
*/
public $invoice;
/**
* @var
* @var Quote|null
*/
public $quote;
/**
* @var
* @var Vendor|null
*/
public $vendor;
/**
* @var
* @var Expense|null
*/
public $expense;
/**
* @var
* @var Task|null
*/
public $task;
/**
* @var
* @var TaskStatus|null
*/
public $task_status;
/**
* @var
* @var ExpenseCategory|null
*/
public $expense_category;
/**
* @var
* @var \App\Models\CompanyUser|null
*/
public $cu;
/**
* @var
* @var BankIntegration|null
*/
public $bank_integration;
/**
* @var
* @var BankTransaction|null
*/
public $bank_transaction;
/**
* @var
* @var BankTransactionRule|null
*/
public $bank_transaction_rule;
/**
* @var
* @var Payment|null
*/
public $payment;
/**
* @var
* @var TaxRate|null
*/
public $tax_rate;
/**
* @var
* @var Scheduler|null
*/
public $scheduler;
/**
* @var
* @var \App\Models\PurchaseOrder|null
*/
public $purchase_order;

View File

@ -26,6 +26,8 @@ class AutoBillInvoiceTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -34,6 +34,8 @@ class ChartCurrencyTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -28,6 +28,8 @@ class CloneQuoteToInvoiceFactoryTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -26,6 +26,8 @@ class CompanyDocumentsTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -32,6 +32,8 @@ class EInvoiceTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -37,6 +37,8 @@ class EntityTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
public $invoice;
public $invoice_calc;

View File

@ -26,6 +26,8 @@ class GoogleAnalyticsTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -27,6 +27,8 @@ class GroupSettingsTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public $faker;
use ClientGroupSettingsSaver;
public $company_settings;

View File

@ -25,6 +25,8 @@ class InvitationTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public $faker;
use MakesHash;
protected function setUp(): void

View File

@ -26,6 +26,8 @@ class InvoiceActionsTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public $faker;
use ActionsInvoice;
protected function setUp(): void

View File

@ -27,6 +27,8 @@ class InvoiceBalanceTest extends TestCase
{
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -27,6 +27,8 @@ class InvoiceInclusiveTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
public $invoice;
public $invoice_calc;

View File

@ -27,6 +27,8 @@ class InvoiceItemInclusiveTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -29,6 +29,8 @@ class InvoiceItemTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -27,6 +27,8 @@ class InvoiceItemV2Test extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -26,6 +26,8 @@ class InvoiceStatusTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
public $invoice;
public $invoice_calc;

View File

@ -33,6 +33,8 @@ class InvoiceTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
public $invoice;
public $invoice_calc;
@ -455,6 +457,7 @@ class InvoiceTest extends TestCase
'settings' => $c_settings,
]);
$this->assertEquals(0, $c->balance);
$item = InvoiceItemFactory::create();

View File

@ -21,6 +21,8 @@ class ImportTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
public $migration_array;
protected function setUp(): void

View File

@ -0,0 +1,254 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Unit;
use Tests\TestCase;
use Tests\MockAccountData;
use App\Models\Account;
use App\Models\Company;
use App\Models\User;
use App\Models\Client;
use App\Models\Project;
use App\Models\Vendor;
use App\Models\Expense;
use App\Models\Task;
use App\Models\Quote;
use App\Models\Credit;
use App\Models\Payment;
use App\Models\Product;
use App\Models\TaxRate;
use App\Models\Scheduler;
use App\Models\TaskStatus;
use App\Models\CompanyToken;
use App\Models\RecurringQuote;
use App\Models\RecurringExpense;
use App\Models\RecurringInvoice;
use App\Models\ExpenseCategory;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
use App\Models\BankTransactionRule;
use App\Models\ClientContact;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use ReflectionClass;
use ReflectionProperty;
/**
* Test class for MockAccountData trait.
*
* This test ensures all properties are properly declared with type hints
* to prevent PHP 8.2+ dynamic property deprecation warnings.
*/
class MockAccountDataTest extends TestCase
{
use DatabaseTransactions;
use MockAccountData;
/**
* Test that all properties in MockAccountData trait are properly declared.
*
* This prevents PHP 8.2+ deprecation notices for dynamic properties.
*/
public function testAllPropertiesAreDeclared(): void
{
$reflection = new ReflectionClass($this);
$properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
$expectedProperties = [
'credit_calc',
'invoice_calc',
'quote_calc',
'recurring_invoice_calc',
'project',
'account',
'company',
'user',
'client',
'token',
'recurring_expense',
'recurring_quote',
'credit',
'invoice',
'quote',
'vendor',
'expense',
'task',
'task_status',
'expense_category',
'cu',
'bank_integration',
'bank_transaction',
'bank_transaction_rule',
'payment',
'tax_rate',
'scheduler',
'purchase_order',
'contact',
'product',
'recurring_invoice',
];
$foundProperties = [];
foreach ($properties as $property) {
if (in_array($property->getName(), $expectedProperties)) {
$foundProperties[] = $property->getName();
}
}
// Verify all expected properties were found
$missingProperties = array_diff($expectedProperties, $foundProperties);
$this->assertEmpty(
$missingProperties,
'Missing property declarations: ' . implode(', ', $missingProperties)
);
}
/**
* Test that properties can be assigned without triggering deprecation warnings.
*/
public function testPropertiesCanBeAssignedWithoutWarnings(): void
{
// These assignments should not trigger any deprecation warnings
$this->credit_calc = 'test_value';
$this->invoice_calc = null;
$this->quote_calc = null;
$this->recurring_invoice_calc = null;
// Create mock objects for testing
$this->account = new Account();
$this->company = new Company();
$this->user = new User();
$this->client = new Client();
$this->project = new Project();
$this->vendor = new Vendor();
$this->expense = new Expense();
$this->task = new Task();
$this->quote = new Quote();
$this->credit = new Credit();
$this->payment = new Payment();
$this->product = new Product();
$this->tax_rate = new TaxRate();
$this->scheduler = new Scheduler();
$this->task_status = new TaskStatus();
$this->token = new CompanyToken();
$this->recurring_quote = new RecurringQuote();
$this->recurring_expense = new RecurringExpense();
$this->recurring_invoice = new RecurringInvoice();
$this->expense_category = new ExpenseCategory();
$this->bank_integration = new BankIntegration();
$this->bank_transaction = new BankTransaction();
$this->bank_transaction_rule = new BankTransactionRule();
$this->contact = new ClientContact();
// Assert that the properties were set correctly
$this->assertNotNull($this->credit_calc);
$this->assertInstanceOf(Account::class, $this->account);
$this->assertInstanceOf(Company::class, $this->company);
$this->assertInstanceOf(User::class, $this->user);
$this->assertInstanceOf(Client::class, $this->client);
}
/**
* Test that all properties have proper nullable type hints.
*/
public function testPropertiesHaveNullableTypeHints(): void
{
$reflection = new ReflectionClass($this);
$nullableProperties = [
'invoice_calc',
'quote_calc',
'recurring_invoice_calc',
'project',
'account',
'company',
'user',
'client',
'token',
'recurring_expense',
'recurring_quote',
'credit',
'invoice',
'quote',
'vendor',
'expense',
'task',
'task_status',
'expense_category',
'cu',
'bank_integration',
'bank_transaction',
'bank_transaction_rule',
'payment',
'tax_rate',
'scheduler',
'purchase_order',
'contact',
'product',
'recurring_invoice',
];
foreach ($nullableProperties as $propertyName) {
if ($reflection->hasProperty($propertyName)) {
$property = $reflection->getProperty($propertyName);
// Property should allow null or have a default value of null
$this->assertTrue(
$property->hasDefaultValue() && $property->getDefaultValue() === null,
"Property {$propertyName} should have a default value of null"
);
}
}
}
/**
* Test that properties don't trigger dynamic property creation warnings.
*/
public function testNoDynamicPropertyWarnings(): void
{
// Enable error reporting to catch any warnings
$previousErrorReporting = error_reporting();
error_reporting(E_ALL);
try {
// Set various properties - this should not trigger any warnings
$this->account = null;
$this->company = null;
$this->user = null;
$this->client = null;
// If we got here without warnings/errors, the test passes
$this->assertTrue(true, 'No dynamic property warnings were triggered');
} finally {
// Restore previous error reporting level
error_reporting($previousErrorReporting);
}
}
/**
* Test that credit_calc property accepts mixed types.
*/
public function testCreditCalcAcceptsMixedTypes(): void
{
$this->credit_calc = 'string_value';
$this->assertIsString($this->credit_calc);
$this->credit_calc = 123;
$this->assertIsInt($this->credit_calc);
$this->credit_calc = ['array' => 'value'];
$this->assertIsArray($this->credit_calc);
$this->credit_calc = null;
$this->assertNull($this->credit_calc);
}
}

View File

@ -26,6 +26,8 @@ class PasswordTimeoutTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -37,6 +37,8 @@ class RecurringDatesTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -35,6 +35,8 @@ class RelationExistsTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
private $models = [
Invoice::class,
Client::class,

View File

@ -26,6 +26,8 @@ class ShopProfileTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -33,6 +33,8 @@ class TaskRepositoryBulkUpdateTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
private TaskRepository $taskRepository;
private Client $testClient;
private Project $testProject;

View File

@ -34,6 +34,8 @@ class EuTaxTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -35,6 +35,8 @@ class SumTaxTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
public Response $response;
public array $resp = [

View File

@ -28,6 +28,8 @@ class TaxConfigTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
protected function setUp(): void
{
parent::setUp();

View File

@ -32,6 +32,8 @@ class UsTaxTest extends TestCase
use MockAccountData;
use DatabaseTransactions;
public $faker;
private array $mock_response = [
"geoPostalCode" => "92582",
"geoCity" => "SAN JACINTO",

View File

@ -44,7 +44,7 @@ class TimeZoneTest extends TestCase
'America/Santiago' => 'America/Santiago',
'Canada/Newfoundland' => 'America/St_Johns',
'America/Buenos_Aires' => 'America/Argentina/Buenos_Aires',
'America/Godthab' => 'America/Godthab',
'America/Godthab' => 'America/Nuuk',
'America/Sao_Paulo' => 'America/Sao_Paulo',
'Atlantic/Stanley' => 'Atlantic/Stanley',
'Atlantic/Azores' => 'Atlantic/Azores',