Additional rules around tests

This commit is contained in:
David Bomba 2025-08-12 18:34:38 +10:00
parent 5482f44bea
commit 63e6f75a24
12 changed files with 205 additions and 147 deletions

View File

@ -44,7 +44,7 @@ class EInvoiceController extends BaseController
$el = new EntityLevel();
$data = [];
match ($request->entity) {
'invoices' => $data = $el->checkInvoice($request->getEntity()),
'clients' => $data = $el->checkClient($request->getEntity()),

View File

@ -75,7 +75,6 @@ class ValidateEInvoiceRequest extends Request
return false;
}
$class = Invoice::class;
match ($this->entity) {

View File

@ -330,7 +330,7 @@ class BaseModel extends Model
}
// special catch here for einvoicing eventing
if ($event_id == Webhook::EVENT_SENT_INVOICE && ($this instanceof Invoice) && is_null($this->backup) && $this->client->peppolSendingEnabled()) {
if ($event_id == Webhook::EVENT_SENT_INVOICE && ($this instanceof Invoice) && $this->backup->guid == "" && $this->client->peppolSendingEnabled()) {
\App\Services\EDocument\Jobs\SendEDocument::dispatch(get_class($this), $this->id, $this->company->db);
}

View File

@ -570,8 +570,8 @@ class User extends Authenticatable implements MustVerifyEmail
*
* Note, returning FALSE here means the user does NOT have the permission we want to exclude
*
* @param array $matched_permission
* @param array $excluded_permissions
* @param array $matched_permission = []
* @param array $excluded_permissions = []
* @return bool
*/
public function hasExcludedPermissions(array $matched_permission = [], array $excluded_permissions = []): bool

View File

@ -158,6 +158,7 @@ class Peppol extends AbstractService
public function __construct(public Invoice $invoice)
{
$this->company = $invoice->company;
$this->calc = $this->invoice->calc();
$this->e = new EInvoice();

View File

@ -119,36 +119,6 @@ class FacturaRectificativa extends BaseXmlModel
return $idFacturaRectificada;
}
/**
* Create a FacturaRectificativa instance for a substitutive rectification
*
* @param string $nif The NIF of the rectified invoice
* @param string $numSerie The series number of the rectified invoice
* @param string $fecha The date of the rectified invoice
* @return static
*/
public static function createForSubstitutive(string $nif, string $numSerie, string $fecha): static
{
$instance = new static('S', 0.0, 0.0);
$instance->setRectifiedInvoice($nif, $numSerie, $fecha);
return $instance;
}
/**
* Create a FacturaRectificativa instance for a complete rectification
*
* @param string $nif The NIF of the rectified invoice
* @param string $numSerie The series number of the rectified invoice
* @param string $fecha The date of the rectified invoice
* @return static
*/
public static function createForComplete(string $nif, string $numSerie, string $fecha): static
{
$instance = new static('I', 0.0, 0.0);
$instance->setRectifiedInvoice($nif, $numSerie, $fecha);
return $instance;
}
public static function fromDOMElement(\DOMElement $element): self
{
// This method is required by BaseXmlModel but not used in this context

View File

@ -576,59 +576,6 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
return $this;
}
/**
* Helper method to create a complete rectification invoice with ImporteRectificacion
*
* @param float $importeRectificacion The rectification amount
* @param string $descripcionOperacion Description of the rectification operation
* @return self
*/
public function makeCompleteRectificationWithAmount(float $importeRectificacion, string $descripcionOperacion = 'Rectificación completa de factura'): self
{
return $this->makeRectificativeWithAmount(self::TIPO_RECTIFICATIVA_COMPLETA, $importeRectificacion, $descripcionOperacion);
}
/**
* Helper method to create a substitutive rectification invoice with ImporteRectificacion
*
* @param float $importeRectificacion The rectification amount
* @param string $descripcionOperacion Description of the rectification operation
* @return self
*/
public function makeSubstitutiveRectificationWithAmount(float $importeRectificacion, string $descripcionOperacion = 'Rectificación sustitutiva de factura'): self
{
return $this->makeRectificativeWithAmount(self::TIPO_RECTIFICATIVA_SUSTITUTIVA, $importeRectificacion, $descripcionOperacion);
}
/**
* Helper method to create a substitutive rectification invoice that automatically calculates ImporteRectificacion
* from the difference between the original and new amounts
*
* @param float $originalAmount The original invoice amount
* @param float $newAmount The new invoice amount
* @param string $descripcionOperacion Description of the rectification operation
* @return self
*/
public function makeSubstitutiveRectificationFromDifference(float $originalAmount, float $newAmount, string $descripcionOperacion = 'Rectificación sustitutiva de factura'): self
{
$importeRectificacion = $newAmount - $originalAmount;
return $this->makeRectificativeWithAmount(self::TIPO_RECTIFICATIVA_SUSTITUTIVA, $importeRectificacion, $descripcionOperacion);
}
/**
* Calculate and set ImporteRectificacion based on the difference between amounts
*
* @param float $originalAmount The original invoice amount
* @param float $newAmount The new invoice amount
* @return self
*/
public function calculateImporteRectificacion(float $originalAmount, float $newAmount): self
{
$this->importeRectificacion = $newAmount - $originalAmount;
return $this;
}
/**
@ -652,11 +599,11 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
throw new \InvalidArgumentException('DescripcionOperacion is required');
}
if ($this->cuotaTotal === null || $this->cuotaTotal < 0) {
if ($this->cuotaTotal < 0) {
throw new \InvalidArgumentException('CuotaTotal must be a positive number');
}
if ($this->importeTotal === null || $this->importeTotal < 0) {
if ($this->importeTotal < 0) {
throw new \InvalidArgumentException('ImporteTotal must be a positive number');
}
@ -1042,32 +989,17 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
$root->appendChild($this->createElement($doc, 'ImporteTotal', (string)$this->importeTotal));
// 13. Encadenamiento (always present for R1 invoices)
if ($this->encadenamiento !== null) {
// if ($this->encadenamiento !== null) {
$root->appendChild($this->encadenamiento->toXml($doc));
} else {
// Create default Encadenamiento if not set
$encadenamientoElement = $this->createElement($doc, 'Encadenamiento');
$encadenamientoElement->appendChild($this->createElement($doc, 'PrimerRegistro', 'S'));
$root->appendChild($encadenamientoElement);
}
// } else {
// // Create default Encadenamiento if not set
// $encadenamientoElement = $this->createElement($doc, 'Encadenamiento');
// $encadenamientoElement->appendChild($this->createElement($doc, 'PrimerRegistro', 'S'));
// $root->appendChild($encadenamientoElement);
// }
// 14. SistemaInformatico (always present for R1 invoices)
if ($this->sistemaInformatico !== null) {
$root->appendChild($this->sistemaInformatico->toXml($doc));
} else {
// Create default SistemaInformatico if not set
$sistemaInformaticoElement = $this->createElement($doc, 'SistemaInformatico');
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'NombreRazon', $this->nombreRazonEmisor));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'NIF', $this->idEmisorFactura));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'NombreSistemaInformatico', 'InvoiceNinja'));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'IdSistemaInformatico', '77'));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'Version', '1.0.03'));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'NumeroInstalacion', '383'));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'TipoUsoPosibleSoloVerifactu', 'N'));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'TipoUsoPosibleMultiOT', 'S'));
$sistemaInformaticoElement->appendChild($this->createElement($doc, 'IndicadorMultiplesOT', 'S'));
$root->appendChild($sistemaInformaticoElement);
}
$root->appendChild($this->sistemaInformatico->toXml($doc));
// 15. FechaHoraHusoGenRegistro
$root->appendChild($this->createElement($doc, 'FechaHoraHusoGenRegistro', $this->fechaHoraHusoGenRegistro));

View File

@ -11,20 +11,21 @@
namespace App\Services\EDocument\Standards\Verifactu;
use Mail;
use App\Utils\Ninja;
use App\Models\Company;
use App\Models\Invoice;
use App\Libraries\MultiDB;
use App\Models\Company;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use App\Services\EDocument\Standards\Verifactu;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Mail;
use Illuminate\Mail\Mailables\Address;
class SendToAeat implements ShouldQueue
{
@ -38,9 +39,11 @@ class SendToAeat implements ShouldQueue
public $deleteWhenMissingModels = true;
/**
* Modification Invoices - (modify) Generates a F3 document which replaces the original invoice. And becomes the new invoice.
* Modification Invoices - (modify)
* - If Amount > 0 - We generates a F3 document which replaces the original invoice. And becomes the new invoice.
* - If Amount < 0 - We generate a R2 document which is a negative modification on the original invoice.
* Create Invoices - (create) Generates a F1 document.
* Cancellation Invoices - (cancel) Generates a R3 document with full negative values of the original invoice.
* Cancellation Invoices - (cancel) Generates a R3 document with full negative values of the original invoice.
*/
/**
@ -66,6 +69,50 @@ class SendToAeat implements ShouldQueue
$invoice = Invoice::withTrashed()->find($this->invoice_id);
switch($this->action) {
case 'modify':
$this->modifyInvoice($invoice);
break;
case 'create':
$this->createInvoice($invoice);
break;
case 'cancel':
$this->cancelInvoice($invoice);
break;
}
}
public function modifyInvoice(Invoice $invoice)
{
$verifactu = new Verifactu($invoice);
$verifactu->run();
}
public function createInvoice(Invoice $invoice)
{
$verifactu = new Verifactu($invoice);
$verifactu->run();
}
public function cancelInvoice(Invoice $invoice)
{
$verifactu = new Verifactu($invoice);
$document = (new RegistroAlta($invoice))->run()->getInvoice();
$last_hash = $invoice->company->verifactu_logs()->first();
$huella = $this->cancellationHash($document, $last_hash->hash);
$cancellation = $document->createCancellation();
$cancellation->setHuella($huella);
$soapXml = $cancellation->toSoapEnvelope();
$response = $verifactu->send($soapXml);
nlog($response);
}
public function middleware()
@ -77,4 +124,31 @@ class SendToAeat implements ShouldQueue
{
nlog($exception);
}
/**
* cancellationHash
*
* @param mixed $document
* @param string $huella
* @return string
*/
private function cancellationHash($document, string $huella): string
{
$idEmisorFacturaAnulada = $document->getIdFactura()->getIdEmisorFactura();
$numSerieFacturaAnulada = $document->getIdFactura()->getNumSerieFactura();
$fechaExpedicionFacturaAnulada = $document->getIdFactura()->getFechaExpedicionFactura();
$fechaHoraHusoGenRegistro = $document->getFechaHoraHusoGenRegistro();
$hashInput = "IDEmisorFacturaAnulada={$idEmisorFacturaAnulada}&" .
"NumSerieFacturaAnulada={$numSerieFacturaAnulada}&" .
"FechaExpedicionFacturaAnulada={$fechaExpedicionFacturaAnulada}&" .
"Huella={$huella}&" .
"FechaHoraHusoGenRegistro={$fechaHoraHusoGenRegistro}";
return strtoupper(hash('sha256', $hashInput));
}
}

View File

@ -98,12 +98,14 @@ class CreditTest extends TestCase
$ii->product_key = 'xx';
$ii->notes = 'yy';
$credit_array['line_items'] = [$ii];
$credit_array['line_items'] = [];
$credit_array['line_items'][] = (array)$ii;
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits', $credit_array);
])->postJson('/api/v1/credits', $credit_array);
$response->assertStatus(200);
$arr = $response->json();
@ -176,12 +178,14 @@ class CreditTest extends TestCase
$ii->product_key = 'xx';
$ii->notes = 'yy';
$credit_array['line_items'] = [$ii];
$credit_array['line_items'] = [];
$credit_array['line_items'][] = (array)$ii;
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits', $credit_array);
])->postJson('/api/v1/credits', $credit_array);
$response->assertStatus(200);
$arr = $response->json();
@ -581,7 +585,7 @@ class CreditTest extends TestCase
$response = $this->withHeaders([
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits/bulk', $data)
])->postJson('/api/v1/credits/bulk', $data)
->assertStatus(200);
@ -593,7 +597,7 @@ class CreditTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits/bulk', $data)
])->postJson('/api/v1/credits/bulk', $data)
->assertStatus(200);
$data = [
@ -604,7 +608,7 @@ class CreditTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits/bulk', $data)
])->postJson('/api/v1/credits/bulk', $data)
->assertStatus(200);
}
@ -698,7 +702,7 @@ class CreditTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits/', $credit)
])->postJson('/api/v1/credits/', $credit)
->assertStatus(200);
}
@ -733,16 +737,16 @@ class CreditTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits', $data);
])->postJson('/api/v1/credits', $data);
$response->assertStatus(200);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits', $data);
])->postJson('/api/v1/credits', $data);
$response->assertStatus(302);
$response->assertStatus(422);
}
public function testCreditPut()
@ -780,8 +784,8 @@ class CreditTest extends TestCase
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/credits/', $data);
])->postJson('/api/v1/credits/', $data);
$response->assertStatus(302);
$response->assertStatus(422);
}
}

View File

@ -11,6 +11,7 @@
namespace Tests\Feature\EInvoice;
use Faker\Factory;
use Tests\TestCase;
use App\Models\Client;
use App\Models\Company;
@ -23,6 +24,7 @@ use App\DataMapper\Tax\TaxModel;
use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Factory\CompanyUserFactory;
use App\Repositories\InvoiceRepository;
use InvoiceNinja\EInvoice\EInvoice;
use InvoiceNinja\EInvoice\Symfony\Encode;
use App\Services\EDocument\Standards\Peppol;
@ -46,6 +48,9 @@ class PeppolTest extends TestCase
protected int $iterations = 10;
public $faker;
protected function setUp(): void
{
parent::setUp();
@ -54,6 +59,8 @@ class PeppolTest extends TestCase
$this->markTestSkipped('Skip test for GH Actions');
}
$this->faker = Factory::create();
$this->makeTestData();
$this->withoutMiddleware(
@ -109,6 +116,7 @@ class PeppolTest extends TestCase
$this->company->save();
$company = $this->company;
/** @var Client $client */
$client = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
@ -121,15 +129,23 @@ class PeppolTest extends TestCase
'id_number' => $params['client_id_number'] ?? '',
]);
$client->setRelation('company', $company);
/** @var ClientContact $contact */
$contact = ClientContact::factory()->create([
'client_id' => $client->id,
'company_id' =>$client->company_id,
'user_id' => $client->user_id,
'first_name' => $this->faker->firstName(),
'last_name' => $this->faker->lastName(),
'email' => $this->faker->safeEmail()
'email' => $this->faker->safeEmail(),
'is_primary' => true,
'send_email' => true,
]);
$client->setRelation('contacts', [$contact]);
/** @var Invoice $invoice */
$invoice = \App\Models\Invoice::factory()->create([
'client_id' => $client->id,
'company_id' => $this->company->id,
@ -143,8 +159,10 @@ class PeppolTest extends TestCase
'tax_name2' => '',
'tax_rate3' => 0,
'tax_name3' => '',
'status_id' => Invoice::STATUS_DRAFT,
]);
$items = $invoice->line_items;
foreach($items as &$item)
@ -160,6 +178,9 @@ class PeppolTest extends TestCase
$invoice->line_items = array_values($items);
$invoice = $invoice->calc()->getInvoice();
$invoice->setRelation('client', $client);
$invoice->setRelation('company', $company);
return compact('company', 'client', 'invoice');
}
@ -179,7 +200,6 @@ class PeppolTest extends TestCase
'is_tax_exempt' => false,
];
$entity_data = $this->setupTestData($scenario);
$invoice = $entity_data['invoice'];
@ -257,6 +277,17 @@ class PeppolTest extends TestCase
$company->settings = $settings;
$company->save();
$invoice->setRelation('company', $company);
$invoice->setRelation('client', $entity_data['client']);
$invoice->save();
$repo = new InvoiceRepository();
$invoice = $repo->save([], $invoice);
$invoice = $invoice->service()->markSent()->save();
$this->assertGreaterThan(0, $invoice->invitations()->count());
$data = [
'entity' => 'invoices',
'entity_id' => $invoice->hashed_id
@ -511,6 +542,10 @@ class PeppolTest extends TestCase
];
$invoice->save();
$repo = new InvoiceRepository();
$invoice = $repo->save([], $invoice);
$invoice = $invoice->service()->markSent()->save();
$company = $entity_data['company'];
$settings = $company->settings;

View File

@ -30,7 +30,8 @@ use App\Services\EDocument\Standards\Verifactu\Models\Invoice as VerifactuInvoic
class VerifactuFeatureTest extends TestCase
{
private $account;
/** @var Account $account */
private Account $account;
private $company;
private $user;
private $cu;
@ -50,24 +51,32 @@ class VerifactuFeatureTest extends TestCase
parent::setUp();
$this->faker = Faker::create();
$this->markTestSkipped('not now');
}
private function buildData($settings = null)
{
$this->account = Account::factory()->create([
/** @var Account $a */
$a = Account::factory()->create([
'hosted_client_count' => 1000,
'hosted_company_count' => 1000,
]);
$this->account->num_users = 3;
$this->account->save();
$a->num_users = 3;
$a->save();
$this->user = User::factory()->create([
$this->account = $a;
/** @var User $u */
$u = User::factory()->create([
'account_id' => $this->account->id,
'confirmation_code' => 'xyz123',
'email' => $this->faker->unique()->safeEmail(),
]);
$this->user = $u;
if(!$settings) {
$settings = CompanySettings::defaults();
$settings->client_online_payment_notification = false;
@ -268,6 +277,7 @@ class VerifactuFeatureTest extends TestCase
$invoice->number = 'TEST0033343459';
$invoice->save();
/** @var Invoice $_inv */
$_inv = Invoice::factory()->create([
'user_id' => $invoice->user_id,
'company_id' => $invoice->company_id,
@ -292,7 +302,6 @@ class VerifactuFeatureTest extends TestCase
$huella = $this->cancellationHash($document, $xx->hash);
$cancellation = $document->createCancellation();
// $cancellation->setFechaHoraHusoGenRegistro('2025-08-09T23:57:25+00:00');
$cancellation->setHuella($huella);
$soapXml = $cancellation->toSoapEnvelope();

View File

@ -37,6 +37,8 @@ class PermissionsTest extends TestCase
public $token;
private Account $account;
protected function setUp(): void
{
parent::setUp();
@ -47,25 +49,25 @@ class PermissionsTest extends TestCase
$this->faker = \Faker\Factory::create();
$account = Account::factory()->create([
$acc = Account::factory()->create([
'hosted_client_count' => 1000,
'hosted_company_count' => 1000,
]);
$account->num_users = 3;
$account->save();
$acc->num_users = 3;
$acc->save();
$this->company = Company::factory()->create([
'account_id' => $account->id,
'account_id' => $acc->id,
]);
$this->user = User::factory()->create([
'account_id' => $account->id,
'account_id' => $acc->id,
'confirmation_code' => '123',
'email' => $this->faker->safeEmail(),
]);
$this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $account->id);
$this->cu = CompanyUserFactory::create($this->user->id, $this->company->id, $acc->id);
$this->cu->is_owner = false;
$this->cu->is_admin = false;
$this->cu->is_locked = false;
@ -77,21 +79,25 @@ class PermissionsTest extends TestCase
$company_token = new CompanyToken();
$company_token->user_id = $this->user->id;
$company_token->company_id = $this->company->id;
$company_token->account_id = $account->id;
$company_token->account_id = $acc->id;
$company_token->name = 'test token';
$company_token->token = $this->token;
$company_token->is_system = true;
$company_token->save();
$this->account = $acc;
}
public function testClientOverviewPermissions()
{
/** @var User $u */
$u = User::factory()->create([
'account_id' => $this->company->account_id,
'confirmation_code' => '123',
'email' => $this->faker->safeEmail(),
]);
/** @var Client $c */
$c = Client::factory()->create([
'company_id' => $this->company->id,
'user_id' => $u->id,
@ -131,6 +137,9 @@ class PermissionsTest extends TestCase
$this->assertEquals(2, count($data));
$u->forceDelete();
$this->account->forceDelete();
}
@ -148,6 +157,10 @@ class PermissionsTest extends TestCase
$this->assertTrue($this->user->hasExcludedPermissions(["view_client"]));
$this->account->forceDelete();
}
public function testHasExcludedPermissions2()
@ -177,6 +190,8 @@ class PermissionsTest extends TestCase
$this->assertFalse($this->user->hasExcludedPermissions(["view_client"], ['view_invoice']));
$this->account->forceDelete();
}
public function testIntersectPermissions()
@ -209,6 +224,10 @@ class PermissionsTest extends TestCase
$this->assertFalse($this->user->hasIntersectPermissions(["createbank_transaction"]));
$this->assertTrue($this->user->hasIntersectPermissions(["create_bank_transaction"]));
$this->assertTrue($this->user->hasIntersectPermissions(['create_bank_transaction','edit_bank_transaction','view_bank_transaction']));
$this->account->forceDelete();
}
public function testViewClientPermission()
@ -265,6 +284,9 @@ class PermissionsTest extends TestCase
$low_cu->save();
$this->assertTrue($this->user->hasPermission('view_recurring_invoice'));
$this->account->forceDelete();
}
public function testPermissionResolution()
@ -312,6 +334,8 @@ class PermissionsTest extends TestCase
$this->assertEquals('invoice', \Illuminate\Support\Str::snake(class_basename(Invoice::class)));
$this->assertEquals('recurring_invoice', \Illuminate\Support\Str::snake(class_basename(RecurringInvoice::class)));
$this->account->forceDelete();
}
public function testExactPermissions()
@ -328,6 +352,9 @@ class PermissionsTest extends TestCase
$this->assertFalse($this->user->hasExactPermissionAndAll("view_client"));
$this->assertFalse($this->user->hasExactPermissionAndAll("view_all"));
$this->account->forceDelete();
}
public function testViewAllValidPermissions()
@ -338,6 +365,9 @@ class PermissionsTest extends TestCase
$this->assertTrue($this->user->hasExactPermissionAndAll("view_client"));
$this->assertTrue($this->user->hasExactPermissionAndAll("view_all"));
$this->account->forceDelete();
}
public function testReturnTypesOfStripos()
@ -368,5 +398,9 @@ class PermissionsTest extends TestCase
$this->assertTrue(is_int(stripos($all_permission, "view_client")) !== false);
$this->assertTrue(is_int(stripos($all_permission, "view_client")));
$this->account->forceDelete();
}
}