mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-28 23:19:42 -08:00
427 lines
18 KiB
PHP
427 lines
18 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Importing\Api;
|
|
|
|
use App\Models\Accessory;
|
|
use App\Models\Actionlog;
|
|
use App\Models\Company;
|
|
use Database\Factories\AccessoryFactory;
|
|
use Database\Factories\CompanyFactory;
|
|
use Illuminate\Support\Str;
|
|
use Database\Factories\UserFactory;
|
|
use Database\Factories\ImportFactory;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Illuminate\Foundation\Testing\WithFaker;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Testing\TestResponse;
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
use Tests\Support\Importing\AccessoriesImportFileBuilder as ImportFileBuilder;
|
|
|
|
class ImportAccessoriesTest extends ImportDataTestCase
|
|
{
|
|
use WithFaker;
|
|
|
|
protected function importFileResponse(array $parameters = []): TestResponse
|
|
{
|
|
if (!array_key_exists('import-type', $parameters)) {
|
|
$parameters['import-type'] = 'accessory';
|
|
}
|
|
|
|
return parent::importFileResponse($parameters);
|
|
}
|
|
|
|
#[Test]
|
|
#[DataProvider('permissionsTestData')]
|
|
public function onlyUserWithPermissionCanImportAccessories(array|string $permissions): void
|
|
{
|
|
$permissions = collect((array) $permissions)
|
|
->map(fn (string $permission) => [$permission => '1'])
|
|
->toJson();
|
|
|
|
$this->actingAsForApi(UserFactory::new()->create(['permissions' => $permissions]));
|
|
|
|
$this->importFileResponse(['import' => 44])->assertForbidden();
|
|
}
|
|
|
|
#[Test]
|
|
public function userWithImportAccessoryPermissionCanImportAccessories(): void
|
|
{
|
|
$this->actingAsForApi(UserFactory::new()->canImport()->create());
|
|
|
|
$import = ImportFactory::new()->accessory()->create();
|
|
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
}
|
|
|
|
#[Test]
|
|
public function importAccessory(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::new();
|
|
$row = $importFileBuilder->firstRow();
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])
|
|
->assertOk()
|
|
->assertExactJson([
|
|
'payload' => null,
|
|
'status' => 'success',
|
|
'messages' => [
|
|
'redirect_url' => route('accessories.index')
|
|
]
|
|
]);
|
|
|
|
$newAccessory = Accessory::query()
|
|
->with(['location', 'category', 'manufacturer', 'supplier', 'company'])
|
|
->where('name', $row['itemName'])
|
|
->sole();
|
|
|
|
$activityLog = Actionlog::query()
|
|
->where('item_type', Accessory::class)
|
|
->where('item_id', $newAccessory->id)
|
|
->sole();
|
|
|
|
$this->assertEquals('create', $activityLog->action_type);
|
|
$this->assertEquals('importer', $activityLog->action_source);
|
|
$this->assertEquals($newAccessory->company->id, $activityLog->company_id);
|
|
|
|
$this->assertEquals($row['itemName'], $newAccessory->name);
|
|
$this->assertEquals($row['quantity'], $newAccessory->qty);
|
|
$this->assertEquals($row['purchaseDate'], $newAccessory->purchase_date->toDateString());
|
|
$this->assertEquals($row['purchaseCost'], $newAccessory->purchase_cost);
|
|
$this->assertEquals($row['orderNumber'], $newAccessory->order_number);
|
|
$this->assertEquals($row['notes'], $newAccessory->notes);
|
|
$this->assertEquals($row['category'], $newAccessory->category->name);
|
|
$this->assertEquals('accessory', $newAccessory->category->category_type);
|
|
$this->assertEquals($row['manufacturerName'], $newAccessory->manufacturer->name);
|
|
$this->assertEquals($row['supplierName'], $newAccessory->supplier->name);
|
|
$this->assertEquals($row['location'], $newAccessory->location->name);
|
|
$this->assertEquals($row['companyName'], $newAccessory->company->name);
|
|
$this->assertEquals($row['modelNumber'], $newAccessory->model_number);
|
|
$this->assertFalse($newAccessory->requestable);
|
|
$this->assertNull($newAccessory->min_amt);
|
|
$this->assertNull($newAccessory->user_id);
|
|
}
|
|
|
|
#[Test]
|
|
public function whenImportFileContainsUnknownColumns(): void
|
|
{
|
|
$row = ImportFileBuilder::new()->definition();
|
|
$row['unknownColumn'] = $this->faker->word;
|
|
|
|
$importFileBuilder = new ImportFileBuilder([$row]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
}
|
|
|
|
#[Test]
|
|
public function willFormatDate(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::new(['purchaseDate' => '2022/10/10']);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$accessory = Accessory::query()
|
|
->where('name', $importFileBuilder->firstRow()['itemName'])
|
|
->sole(['purchase_date']);
|
|
|
|
$this->assertEquals('2022-10-10', $accessory->purchase_date->toDateString());
|
|
}
|
|
|
|
#[Test]
|
|
public function willNotCreateNewCategoryWhenCategoryExists(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::times(4)->replace(['category' => Str::random()]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$newAccessories = Accessory::query()
|
|
->whereIn('name', $importFileBuilder->pluck('itemName'))
|
|
->get();
|
|
|
|
$this->assertCount(1, $newAccessories->pluck('category_id')->unique()->all());
|
|
}
|
|
|
|
#[Test]
|
|
public function willNotCreateNewAccessoryWhenAccessoryWithNameExists(): void
|
|
{
|
|
$accessory = AccessoryFactory::new()->create(['name' => Str::random()]);
|
|
$importFileBuilder = ImportFileBuilder::times(2)->replace(['itemName' => $accessory->name]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$probablyNewAccessories = Accessory::query()
|
|
->where('name', $importFileBuilder->pluck('itemName'))
|
|
->get(['name']);
|
|
|
|
$this->assertCount(1, $probablyNewAccessories);
|
|
$this->assertEquals($accessory->name, $probablyNewAccessories->first()->name);
|
|
}
|
|
|
|
#[Test]
|
|
public function willNotCreateNewCompanyWhenCompanyAlreadyExists(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::times(4)->replace(['companyName' => Str::random()]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$newAccessories = Accessory::query()
|
|
->where('name', $importFileBuilder->pluck('itemName'))
|
|
->get(['company_id']);
|
|
|
|
$this->assertCount(1, $newAccessories->pluck('company_id')->unique()->all());
|
|
}
|
|
|
|
#[Test]
|
|
public function willNotCreateNewLocationWhenLocationAlreadyExists(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::times(4)->replace(['location' => Str::random()]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$newAccessories = Accessory::query()
|
|
->where('name', $importFileBuilder->pluck('itemName'))
|
|
->get(['location_id']);
|
|
|
|
$this->assertCount(1, $newAccessories->pluck('location_id')->unique()->all());
|
|
}
|
|
|
|
#[Test]
|
|
public function willNotCreateNewManufacturerWhenManufacturerAlreadyExists(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::times(4)->replace(['manufacturerName' => $this->faker->company]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$newAccessories = Accessory::query()
|
|
->where('name', $importFileBuilder->pluck('itemName'))
|
|
->get(['manufacturer_id']);
|
|
|
|
$this->assertCount(1, $newAccessories->pluck('manufacturer_id')->unique()->all());
|
|
}
|
|
|
|
#[Test]
|
|
public function willNotCreateNewSupplierWhenSupplierAlreadyExists(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::times(4)->replace(['supplierName' => $this->faker->company]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$newAccessories = Accessory::query()
|
|
->where('name', $importFileBuilder->pluck('itemName'))
|
|
->get(['supplier_id']);
|
|
|
|
$this->assertCount(1, $newAccessories->pluck('supplier_id')->unique()->all());
|
|
}
|
|
|
|
#[Test]
|
|
public function whenColumnsAreMissingInImportFile(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::new()->forget(['minimumAmount', 'purchaseCost', 'purchaseDate']);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])->assertOk();
|
|
|
|
$newAccessory = Accessory::query()
|
|
->where('name', $importFileBuilder->firstRow()['itemName'])
|
|
->sole();
|
|
|
|
$this->assertNull($newAccessory->min_amt);
|
|
$this->assertNull($newAccessory->purchase_date);
|
|
$this->assertNull($newAccessory->purchase_cost);
|
|
}
|
|
|
|
#[Test]
|
|
public function whenRequiredColumnsAreMissingInImportFile(): void
|
|
{
|
|
$importFileBuilder = ImportFileBuilder::new()->forget(['itemName', 'quantity', 'category']);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])
|
|
->assertInternalServerError()
|
|
->assertExactJson([
|
|
'status' => 'import-errors',
|
|
'payload' => null,
|
|
'messages' => [
|
|
'' => [
|
|
'Accessory' => [
|
|
'name' => ['The name field is required.'],
|
|
'qty' => ['The qty field must be at least 1.'],
|
|
'category_id' => ['The category id field is required.']
|
|
]
|
|
]
|
|
]
|
|
]);
|
|
}
|
|
|
|
#[Test]
|
|
public function updateAccessoryFromImport(): void
|
|
{
|
|
$accessory = AccessoryFactory::new()->create(['name' => Str::random()])->refresh();
|
|
$importFileBuilder = ImportFileBuilder::new(['itemName' => $accessory->name]);
|
|
$row = $importFileBuilder->firstRow();
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id, 'import-update' => true])->assertOk();
|
|
|
|
$updatedAccessory = Accessory::query()->find($accessory->id);
|
|
$updatedAttributes = [
|
|
'name', 'company_id', 'qty', 'purchase_date', 'purchase_cost',
|
|
'order_number', 'notes', 'category_id', 'manufacturer_id', 'supplier_id',
|
|
'location_id', 'model_number', 'updated_at'
|
|
];
|
|
|
|
$this->assertEquals($row['itemName'], $updatedAccessory->name);
|
|
$this->assertEquals($row['companyName'], $updatedAccessory->company->name);
|
|
$this->assertEquals($row['quantity'], $updatedAccessory->qty);
|
|
$this->assertEquals($row['purchaseDate'], $updatedAccessory->purchase_date->toDateString());
|
|
$this->assertEquals($row['purchaseCost'], $updatedAccessory->purchase_cost);
|
|
$this->assertEquals($row['orderNumber'], $updatedAccessory->order_number);
|
|
$this->assertEquals($row['notes'], $updatedAccessory->notes);
|
|
$this->assertEquals($row['category'], $updatedAccessory->category->name);
|
|
$this->assertEquals('accessory', $updatedAccessory->category->category_type);
|
|
$this->assertEquals($row['manufacturerName'], $updatedAccessory->manufacturer->name);
|
|
$this->assertEquals($row['supplierName'], $updatedAccessory->supplier->name);
|
|
$this->assertEquals($row['location'], $updatedAccessory->location->name);
|
|
$this->assertEquals($row['modelNumber'], $updatedAccessory->model_number);
|
|
|
|
$this->assertEquals(
|
|
Arr::except($accessory->attributesToArray(), $updatedAttributes),
|
|
Arr::except($updatedAccessory->attributesToArray(), $updatedAttributes),
|
|
);
|
|
}
|
|
|
|
#[Test]
|
|
public function whenImportFileContainsEmptyValues(): void
|
|
{
|
|
$accessory = AccessoryFactory::new()->create(['name' => Str::random()]);
|
|
$accessory->refresh();
|
|
|
|
$importFileBuilder = ImportFileBuilder::new([
|
|
'companyName' => ' ',
|
|
'purchaseDate' => ' ',
|
|
'purchaseCost' => '',
|
|
'location' => '',
|
|
'companyName' => '',
|
|
'orderNumber' => '',
|
|
'category' => '',
|
|
'quantity' => '',
|
|
'manufacturerName' => '',
|
|
'supplierName' => '',
|
|
'notes' => '',
|
|
'requestAble' => '',
|
|
'minimumAmount' => '',
|
|
'modelNumber' => ''
|
|
]);
|
|
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse(['import' => $import->id])
|
|
->assertInternalServerError()
|
|
->assertExactJson([
|
|
'status' => 'import-errors',
|
|
'payload' => null,
|
|
'messages' => [
|
|
$importFileBuilder->firstRow()['itemName'] => [
|
|
'Accessory' => [
|
|
'qty' => ['The qty field must be at least 1.'],
|
|
'category_id' => ['The category id field is required.']
|
|
]
|
|
]
|
|
]
|
|
]);
|
|
|
|
$importFileBuilder->replace(['itemName' => $accessory->name]);
|
|
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->importFileResponse(['import' => $import->id, 'import-update' => true])->assertOk();
|
|
|
|
$updatedAccessory = clone $accessory;
|
|
$updatedAccessory->refresh();
|
|
|
|
$this->assertEquals($accessory->toArray(), $updatedAccessory->toArray());
|
|
}
|
|
|
|
#[Test]
|
|
public function customColumnMapping(): void
|
|
{
|
|
$faker = ImportFileBuilder::new()->definition();
|
|
$row = [
|
|
'itemName' => $faker['modelNumber'],
|
|
'purchaseDate' => $faker['notes'],
|
|
'purchaseCost' => $faker['location'],
|
|
'location' => $faker['purchaseCost'],
|
|
'companyName' => $faker['orderNumber'],
|
|
'orderNumber' => $faker['companyName'],
|
|
'category' => $faker['manufacturerName'],
|
|
'manufacturerName' => $faker['category'],
|
|
'notes' => $faker['purchaseDate'],
|
|
'minimumAmount' => $faker['supplierName'],
|
|
'modelNumber' => $faker['itemName'],
|
|
'quantity' => $faker['quantity']
|
|
];
|
|
|
|
$importFileBuilder = new ImportFileBuilder([$row]);
|
|
$import = ImportFactory::new()->accessory()->create(['file_path' => $importFileBuilder->saveToImportsDirectory()]);
|
|
|
|
$this->actingAsForApi(UserFactory::new()->superuser()->create());
|
|
$this->importFileResponse([
|
|
'import' => $import->id,
|
|
'column-mappings' => [
|
|
'Item Name' => 'model_number',
|
|
'Purchase Date' => 'notes',
|
|
'Purchase Cost' => 'location',
|
|
'Location' => 'purchase_cost',
|
|
'Company' => 'order_number',
|
|
'Order Number' => 'company',
|
|
'Category' => 'manufacturer',
|
|
'Manufacturer' => 'category',
|
|
'Supplier' => 'min_amt',
|
|
'Notes' => 'purchase_date',
|
|
'Min QTY' => 'supplier',
|
|
'Model Number' => 'item_name',
|
|
'Quantity' => 'quantity'
|
|
]
|
|
])->assertOk();
|
|
|
|
$newAccessory = Accessory::query()
|
|
->with(['location', 'category', 'manufacturer', 'supplier'])
|
|
->where('name', $row['modelNumber'])
|
|
->sole();
|
|
|
|
$this->assertEquals($row['modelNumber'], $newAccessory->name);
|
|
$this->assertEquals($row['itemName'], $newAccessory->model_number);
|
|
$this->assertEquals($row['quantity'], $newAccessory->qty);
|
|
$this->assertEquals($row['notes'], $newAccessory->purchase_date->toDateString());
|
|
$this->assertEquals($row['location'], $newAccessory->purchase_cost);
|
|
$this->assertEquals($row['companyName'], $newAccessory->order_number);
|
|
$this->assertEquals($row['purchaseDate'], $newAccessory->notes);
|
|
$this->assertEquals($row['manufacturerName'], $newAccessory->category->name);
|
|
$this->assertEquals($row['category'], $newAccessory->manufacturer->name);
|
|
$this->assertEquals($row['purchaseCost'], $newAccessory->location->name);
|
|
}
|
|
}
|