Skip to content

Commit

Permalink
[WIP] Improvements to unit tests. (#3574)
Browse files Browse the repository at this point in the history
* Improvemenets to unit tests.

* Break up modelfactory into multiple files, populate many states.
* Begin testing validation at the unit test level, test relationships.
* Add tests for Asset::availableForCheckout.
* Model factories now generate all needed relationships on demand,
  which allows us to unit test with a empty database.
* To faciliate the empty database, we move to using sqlite in memory as
  the unit testing database.

* Fix bug with logs of checkouts to non users.

* Fix location finding for assets.  Also Fix location show page to show users associated with location.  Still need some work to show assets.

* More test and generator improvements

* More unit test fixes. PermissionsTest is borked still.

* More Updates

* Rewrite permissionstest.  Check that we have access on the model level rather than via web requests.  Also test delete permissions.

* Fix seeders.

* Make the default asset model factory generate assets that are rtd for testing.

* Save progress.

* Rebase tests, fix department unit test, update database for functional tests.

* Update functional and api tests to use new modelfactory signatures.
  • Loading branch information
dmeltzer authored and snipe committed Jun 13, 2017
1 parent 966a736 commit 5d4920c
Show file tree
Hide file tree
Showing 64 changed files with 1,522 additions and 705 deletions.
5 changes: 3 additions & 2 deletions .env.tests
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
APP_ENV=local
APP_ENV=testing
APP_DEBUG=true
APP_URL=http:https://snipe-it.localapp
DB_CONNECTION=mysql
DB_CONNECTION=sqlite_testing
DB_DEFAULT=sqlite_testing
DB_HOST=localhost
DB_DATABASE=snipeittests
DB_USERNAME=snipeit
Expand Down
6 changes: 5 additions & 1 deletion app/Http/Controllers/Api/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ public function index(Request $request)
}

if ($request->has('company_id')) {
$users = $users->where('company_id','=',$request->input('company_id'));
$users = $users->where('company_id', '=', $request->input('company_id'));
}

if ($request->has('location_id')) {
$users = $users->where('location_id', '=', $request->input('location_id'));
}

if ($request->has('department_id')) {
Expand Down
9 changes: 4 additions & 5 deletions app/Models/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public function availableForCheckout()
* @param null $name
* @return bool
*/
//FIXME: The admin parameter is never used. Can probably be removed.
public function checkOut($target, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
{
if (!$target) {
Expand All @@ -163,7 +164,7 @@ public function checkOut($target, $admin, $checkout_at = null, $expected_checkin
}

if ($this->save()) {
$log = $this->logCheckout($note);
$this->logCheckout($note, $target);
// if ((($this->requireAcceptance()=='1') || ($this->getEula())) && ($user->email!='')) {
// $this->checkOutNotifyMail($log->id, $user, $checkout_at, $expected_checkin, $note);
// }
Expand Down Expand Up @@ -272,15 +273,13 @@ public function assignedAssets()
**/
public function assetLoc()
{
if ($this->assignedTo) {
return $this->assignedTo->userloc();
}

if (!empty($this->assignedType())) {
if ($this->assignedType() == self::ASSET) {
return $this->assignedTo->assetloc(); // Recurse until we have a final location
} elseif ($this->assignedType() == self::LOCATION) {
return $this->assignedTo();
} elseif ($this->assignedType() == self::USER) {
return $this->assignedTo->userLoc();
}
}
return $this->defaultLoc();
Expand Down
17 changes: 11 additions & 6 deletions app/Models/Loggable.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,17 @@ public function logCheckout($note, $target = null /*target is overridable for co
$log->user_id = Auth::user()->id;

// @FIXME This needs to be generalized with new asset checkout.
if (!is_null($this->asset_id) || isset($target)) {
$log->target_type = Asset::class;
$log->target_id = $this->asset_id;
} elseif (!is_null($this->assigned_to)) {
$log->target_type = User::class;
$log->target_id = $this->assigned_to;
if(isset($target)) {
$log->target_type = get_class($target);
$log->target_id = $target->id;
} else {
if (!is_null($this->asset_id)) {
$log->target_type = Asset::class;
$log->target_id = $this->asset_id;
} elseif (!is_null($this->assigned_to)) {
$log->target_type = User::class;
$log->target_id = $this->assigned_to;
}
}

$item = call_user_func(array($log->target_type, 'find'), $log->target_id);
Expand Down
2 changes: 1 addition & 1 deletion config/database.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

'sqlite_testing' => [
'driver' => 'sqlite',
'database' => database_path('testing.sqlite'),
'database' => ':memory:',
'prefix' => '',
],

Expand Down
111 changes: 111 additions & 0 deletions database/factories/ActionLogFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

use App\Models\Actionlog;

$factory->defineAs(App\Models\Actionlog::class, 'asset-upload', function ($faker) {
$asset = factory(App\Models\Asset::class)->create();
return [
'item_type' => get_class($asset),
'item_id' => $asset->id,
'user_id' => function () {
return factory(App\Models\User::class)->create()->id;
},
'filename' => $faker->word,
'action_type' => 'uploaded'
];
});

$factory->defineAs(Actionlog::class, 'asset-checkout', function (Faker\Generator $faker) {
$company = factory(App\Models\Company::class)->create();
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$target = factory(App\Models\User::class)->create(['company_id' => $company->id]);
// $item = factory(App\Models\Asset::class)->create(['company_id' => $company->id]);

return [
'user_id' => $user->id,
'action_type' => 'checkout',
'item_id' => factory(App\Models\Asset::class)->create(['company_id' => $company->id])->id,
'item_type' => App\Models\Asset::class,
'target_id' => $target->id,
'target_type' => get_class($target),
'created_at' => $faker->dateTime(),
'note' => $faker->sentence,
'company_id' => $company->id
];
});

$factory->defineAs(Actionlog::class, 'license-checkout-asset', function (Faker\Generator $faker) {
$company = factory(App\Models\Company::class)->create();
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$target = factory(App\Models\Asset::class)->create(['company_id' => $company->id]);
$item = factory(App\Models\License::class)->create(['company_id' => $company->id]);

return [
'user_id' => $user->id,
'action_type' => 'checkout',
'item_id' => $item->id,
'item_type' => get_class($item),
'target_id' => $target->id,
'target_type' => get_class($target),
'created_at' => $faker->dateTime(),
'note' => $faker->sentence,
'company_id' => $company->id
];
});

$factory->defineAs(Actionlog::class, 'accessory-checkout', function (Faker\Generator $faker) {
$company = factory(App\Models\Company::class)->create();
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$target = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$item = factory(App\Models\Accessory::class)->create(['company_id' => $company->id]);

return [
'user_id' => $user->id,
'action_type' => 'checkout',
'item_id' => $item->id,
'item_type' => get_class($item),
'target_id' => $target->id,
'target_type' => get_class($target),
'created_at' => $faker->dateTime(),
'note' => $faker->sentence,
'company_id' => $company->id
];
});

$factory->defineAs(Actionlog::class, 'consumable-checkout', function (Faker\Generator $faker) {
$company = factory(App\Models\Company::class)->create();
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$target = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$item = factory(App\Models\Consumable::class)->create(['company_id' => $company->id]);

return [
'user_id' => $user->id,
'action_type' => 'checkout',
'item_id' => $item->id,
'item_type' => get_class($item),
'target_id' => $target->id,
'target_type' => get_class($target),
'created_at' => $faker->dateTime(),
'note' => $faker->sentence,
'company_id' => $company->id
];
});

$factory->defineAs(Actionlog::class, 'component-checkout', function (Faker\Generator $faker) {
$company = factory(App\Models\Company::class)->create();
$user = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$target = factory(App\Models\User::class)->create(['company_id' => $company->id]);
$item = factory(App\Models\Component::class)->create(['company_id' => $company->id]);

return [
'user_id' => $user->id,
'action_type' => 'checkout',
'item_id' => $item->id,
'item_type' => get_class($item),
'target_id' => $target->id,
'target_type' => get_class($target),
'created_at' => $faker->dateTime(),
'note' => $faker->sentence,
'company_id' => $company->id
];
});
106 changes: 106 additions & 0 deletions database/factories/AssetFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

use App\Models\Asset;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Factories related exclusively to modelling assets.
|
*/

$factory->define(Asset::class, function (Faker\Generator $faker) {
return [
'name' => $faker->catchPhrase,
'model_id' => function () {
return factory(App\Models\AssetModel::class)->create()->id;
},
'rtd_location_id' => function () {
return factory(App\Models\Location::class)->create()->id;
},
'serial' => $faker->uuid,
'status_id' => function () {
return factory(App\Models\Statuslabel::class)->states('rtd')->create()->id;
},
'user_id' => function () {
return factory(App\Models\User::class)->create()->id;
},
'asset_tag' => $faker->unixTime('now'),
'notes' => $faker->sentence,
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'order_number' => $faker->numberBetween(1000000, 50000000),
'supplier_id' => function () {
return factory(App\Models\Supplier::class)->create()->id;
},
'company_id' => function () {
return factory(App\Models\Company::class)->create()->id;
},
'requestable' => $faker->boolean()
];
});

$factory->state(Asset::class, 'deleted', function ($faker) {
return [
'deleted_at' => $faker->dateTime(),
];
});

$factory->state(Asset::class, 'assigned-to-user', function ($faker) {
return [
'assigned_to' => factory(App\Models\User::class)->create()->id,
'assigned_type' => App\Models\User::class,
];
});

$factory->state(Asset::class, 'assigned-to-location', function ($faker) {
return [
'assigned_to' => factory(App\Models\Location::class)->create()->id,
'assigned_type' => App\Models\Location::class,
];
});

$factory->state(Asset::class, 'assigned-to-asset', function ($faker) {
return [
'assigned_to' => factory(App\Models\Asset::class)->create()->id,
'assigned_type' => App\Models\Asset::class,
];
});


$factory->define(App\Models\AssetModel::class, function (Faker\Generator $faker) {
return [
'name' => $faker->catchPhrase,
'manufacturer_id' => function () {
return factory(App\Models\Manufacturer::class)->create()->id;
},
'category_id' => function () {
return factory(App\Models\Category::class)->states('asset-category')->create()->id;
},
'model_number' => $faker->numberBetween(1000000, 50000000),
'eol' => 1,
'notes' => $faker->paragraph(),
'requestable' => $faker->boolean(),
'depreciation_id' => function () {
return factory(App\Models\Depreciation::class)->create()->id;
},
];
});

$factory->define(App\Models\AssetMaintenance::class, function (Faker\Generator $faker) {
return [
'asset_id' => function () {
return factory(App\Models\Asset::class)->create()->id;
},
'supplier_id' => function () {
return factory(App\Models\Supplier::class)->create()->id;
},
'asset_maintenance_type' => $faker->randomElement(['maintenance', 'repair', 'upgrade']),
'title' => $faker->sentence,
'start_date' => $faker->date(),
'is_warranty' => $faker->boolean(),
'notes' => $faker->paragraph(),
];
});
46 changes: 46 additions & 0 deletions database/factories/CategoryFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/*
|--------------------------------------------------------------------------
| Category Factories
|--------------------------------------------------------------------------
|
| Factories related exclusively to creating categories and the various states..
|
*/


$factory->define(App\Models\Category::class, function (Faker\Generator $faker) {
return [
'name' => $faker->text(20),
'category_type' => $faker->randomElement(['asset', 'accessory', 'component', 'consumable']),
'eula_text' => $faker->paragraph(),
'require_acceptance' => $faker->boolean(),
'use_default_eula' => $faker->boolean(),
'checkin_email' => $faker->boolean()
];
});

$factory->state(App\Models\Category::class, 'asset-category', function ($faker) {
return [
'category_type' => 'asset',
];
});

$factory->state(App\Models\Category::class, 'accessory-category', function ($faker) {
return [
'category_type' => 'accessory',
];
});

$factory->state(App\Models\Category::class, 'component-category', function ($faker) {
return [
'category_type' => 'component',
];
});

$factory->state(App\Models\Category::class, 'consumable-category', function ($faker) {
return [
'category_type' => 'consumable',
];
});
Loading

0 comments on commit 5d4920c

Please sign in to comment.