diff --git a/.travis.yml b/.travis.yml index 6bb7ca309f..dbbc2f502d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ services: php: - 5.6 - 7.0 - - 7.2 + # - 7.2 DISABLE Temporarily until we fix the count(null) bugs - 7.1.4 # execute any number of scripts before the test run, custom env's are available as variables diff --git a/app/Http/Controllers/Api/ComponentsController.php b/app/Http/Controllers/Api/ComponentsController.php index 8e557df6a1..4b18a259e2 100644 --- a/app/Http/Controllers/Api/ComponentsController.php +++ b/app/Http/Controllers/Api/ComponentsController.php @@ -93,13 +93,11 @@ class ComponentsController extends Controller public function show($id) { $this->authorize('view', Component::class); - $component = Component::find($id); + $component = Component::findOrFail($id); if ($component) { return (new ComponentsTransformer)->transformComponent($component); } - - return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.does_not_exist'))); } diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php index 29748b9c22..a3c698fa7c 100644 --- a/app/Http/Controllers/Api/StatuslabelsController.php +++ b/app/Http/Controllers/Api/StatuslabelsController.php @@ -56,7 +56,7 @@ class StatuslabelsController extends Controller $request->except('deployable', 'pending','archived'); if (!$request->has('type')) { - return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]])); + return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]]),500); } $statuslabel = new Statuslabel; diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index f5b7ce08e4..d4d0339f09 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -28,30 +28,32 @@ class UsersController extends Controller $this->authorize('view', User::class); $users = User::select([ - 'users.id', - 'users.employee_num', - 'users.two_factor_enrolled', - 'users.jobtitle', - 'users.email', - 'users.phone', + 'users.activated', 'users.address', + 'users.avatar', 'users.city', - 'users.state', - 'users.country', - 'users.zip', - 'users.username', - 'users.location_id', - 'users.manager_id', - 'users.first_name', - 'users.last_name', - 'users.created_at', - 'users.notes', 'users.company_id', - 'users.last_login', + 'users.country', + 'users.created_at', 'users.deleted_at', 'users.department_id', - 'users.activated', - 'users.avatar', + 'users.email', + 'users.employee_num', + 'users.first_name', + 'users.id', + 'users.jobtitle', + 'users.last_login', + 'users.last_name', + 'users.location_id', + 'users.manager_id', + 'users.notes', + 'users.permissions', + 'users.phone', + 'users.state', + 'users.two_factor_enrolled', + 'users.updated_at', + 'users.username', + 'users.zip', ])->with('manager', 'groups', 'userloc', 'company', 'department','assets','licenses','accessories','consumables') ->withCount('assets','licenses','accessories','consumables'); @@ -69,7 +71,7 @@ class UsersController extends Controller if ($request->has('location_id')) { $users = $users->where('users.location_id', '=', $request->input('location_id')); } - + if ($request->has('group_id')) { $users = $users->ByGroup($request->get('group_id')); } diff --git a/app/Http/Transformers/AccessoriesTransformer.php b/app/Http/Transformers/AccessoriesTransformer.php index b4143ec584..fd6832e00c 100644 --- a/app/Http/Transformers/AccessoriesTransformer.php +++ b/app/Http/Transformers/AccessoriesTransformer.php @@ -32,7 +32,7 @@ class AccessoriesTransformer 'notes' => ($accessory->notes) ? e($accessory->notes) : null, 'qty' => ($accessory->qty) ? (int) $accessory->qty : null, 'purchase_date' => ($accessory->purchase_date) ? Helper::getFormattedDateObject($accessory->purchase_date, 'date') : null, - 'purchase_cost' => ($accessory->purchase_cost) ? e($accessory->purchase_cost) : null, + 'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost), 'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null, 'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null, 'remaining_qty' => $accessory->numRemaining(), diff --git a/app/Models/Component.php b/app/Models/Component.php index 21b794c71b..38610277bb 100644 --- a/app/Models/Component.php +++ b/app/Models/Component.php @@ -54,8 +54,9 @@ class Component extends SnipeModel 'purchase_cost', 'purchase_date', 'min_amt', + 'order_number', 'qty', - 'serial' + 'serial', ]; public function location() diff --git a/app/Models/Consumable.php b/app/Models/Consumable.php index 564d9d80bc..26c8b615fa 100644 --- a/app/Models/Consumable.php +++ b/app/Models/Consumable.php @@ -50,10 +50,12 @@ class Consumable extends SnipeModel protected $fillable = [ 'category_id', 'company_id', + 'item_no', 'location_id', 'manufacturer_id', 'name', 'order_number', + 'model_number', 'purchase_cost', 'purchase_date', 'qty', diff --git a/app/Models/Location.php b/app/Models/Location.php index 75b1b86289..ce6d06906e 100755 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -45,7 +45,19 @@ class Location extends SnipeModel * * @var array */ - protected $fillable = ['name','parent_id','address','address2','city','state', 'country','zip','ldap_ou']; + protected $fillable = [ + 'name', + 'parent_id', + 'address', + 'address2', + 'city', + 'state', + 'country', + 'zip', + 'ldap_ou', + 'currency', + 'image', + ]; protected $hidden = ['user_id']; public function users() diff --git a/app/Models/Statuslabel.php b/app/Models/Statuslabel.php index bfaba26c49..6a700b973e 100755 --- a/app/Models/Statuslabel.php +++ b/app/Models/Statuslabel.php @@ -27,7 +27,13 @@ class Statuslabel extends SnipeModel 'archived' => 'required', ); - protected $fillable = ['name', 'deployable', 'pending', 'archived']; + protected $fillable = [ + 'archived', + 'deployable', + 'name', + 'notes', + 'pending', + ]; /** diff --git a/app/Models/User.php b/app/Models/User.php index 9a31beb437..92f3caf9a5 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -28,24 +28,25 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo protected $table = 'users'; protected $injectUniqueIdentifier = true; protected $fillable = [ - 'email', - 'last_name', - 'company_id', - 'department_id', - 'employee_num', - 'jobtitle', - 'location_id', - 'password', - 'phone', - 'username', - 'first_name', + 'activated', 'address', 'city', - 'state', + 'company_id', 'country', - 'zip', - 'activated', + 'department_id', + 'email', + 'employee_num', + 'first_name', + 'jobtitle', + 'last_name', + 'locale', + 'location_id', 'manager_id', + 'password', + 'phone', + 'state', + 'username', + 'zip', ]; protected $casts = [ diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index eb79b53eba..a26897817c 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -6,21 +6,26 @@ $password = bcrypt('password'); $factory->define(App\Models\User::class, function (Faker\Generator $faker) use ($password) { return [ + 'activated' => 1, + 'address' => $faker->address, + 'city' => $faker->city, + 'company_id' => rand(1,4), + 'country' => $faker->country, + 'department_id' => rand(1,6), + 'email' => $faker->safeEmail, + 'employee_num' => $faker->numberBetween(3500, 35050), 'first_name' => $faker->firstName, + 'jobtitle' => $faker->jobTitle, 'last_name' => $faker->lastName, - 'username' => $faker->username, + 'locale' => $faker->locale, + 'location_id' => rand(1,5), + 'notes' => 'Created by DB seeder', 'password' => $password, 'permissions' => '{"user":"0"}', - 'email' => $faker->safeEmail, - 'company_id' => rand(1,4), - 'locale' => $faker->locale, - 'employee_num' => $faker->numberBetween(3500, 35050), - 'jobtitle' => $faker->jobTitle, - 'department_id' => rand(1,6), 'phone' => $faker->phoneNumber, - 'notes' => 'Created by DB seeder', - 'location_id' => rand(1,5), - 'activated' => 1, + 'state' => $faker->stateAbbr, + 'username' => $faker->username, + 'zip' => $faker->postcode ]; }); diff --git a/tests/api/ApiAccessoriesCest.php b/tests/api/ApiAccessoriesCest.php new file mode 100644 index 0000000000..23b7c4296b --- /dev/null +++ b/tests/api/ApiAccessoriesCest.php @@ -0,0 +1,154 @@ +user = \App\Models\User::find(1); + $I->haveHttpHeader('Accept', 'application/json'); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function indexAccessories(ApiTester $I) + { + + $I->wantTo('Get a list of accessories'); + + // call + $I->sendGET('/accessories?limit=10'); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse(), true); + // sample verify + $accessory = App\Models\Accessory::orderByDesc('created_at')->take(10)->get()->shuffle()->first(); + $I->seeResponseContainsJson((new AccessoriesTransformer)->transformAccessory($accessory)); + } + + /** @test */ + public function createAccessory(ApiTester $I, $scenario) + { + $I->wantTo('Create a new accessory'); + + $temp_accessory = factory(\App\Models\Accessory::class)->states('apple-bt-keyboard')->make([ + 'name' => "Test Accessory Name", + 'company_id' => 2 + ]); + + // setup + $data = [ + 'category_id' => $temp_accessory->category_id, + 'company_id' => $temp_accessory->company->id, + 'location_id' => $temp_accessory->location_id, + 'name' => $temp_accessory->name, + 'order_number' => $temp_accessory->order_number, + 'purchase_cost' => $temp_accessory->purchase_cost, + 'purchase_date' => $temp_accessory->purchase_date, + 'model_number' => $temp_accessory->model_number, + 'manufacturer_id' => $temp_accessory->manufacturer_id, + 'supplier_id' => $temp_accessory->supplier_id, + 'qty' => $temp_accessory->qty, + ]; + + // create + $I->sendPOST('/accessories', $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + } + + // Put is routed to the same method in the controller + // DO we actually need to test both? + /** @test */ + public function updateAccessoryWithPatch(ApiTester $I, $scenario) + { + $I->wantTo('Update an accessory with PATCH'); + + // create + $accessory = factory(\App\Models\Accessory::class)->states('apple-bt-keyboard')->create([ + 'name' => 'Original Accessory Name', + 'company_id' => 2, + 'location_id' => 3 + ]); + $I->assertInstanceOf(\App\Models\Accessory::class, $accessory); + + $temp_accessory = factory(\App\Models\Accessory::class)->states('microsoft-mouse')->make([ + 'company_id' => 3, + 'name' => "updated accessory name", + 'location_id' => 1, + ]); + + $data = [ + 'category_id' => $temp_accessory->category_id, + 'company_id' => $temp_accessory->company->id, + 'location_id' => $temp_accessory->location_id, + 'name' => $temp_accessory->name, + 'order_number' => $temp_accessory->order_number, + 'purchase_cost' => $temp_accessory->purchase_cost, + 'purchase_date' => $temp_accessory->purchase_date, + 'model_number' => $temp_accessory->model_number, + 'manufacturer_id' => $temp_accessory->manufacturer_id, + 'supplier_id' => $temp_accessory->supplier_id, + 'qty' => $temp_accessory->qty, + ]; + + $I->assertNotEquals($accessory->name, $data['name']); + + // update + $I->sendPATCH('/accessories/' . $accessory->id, $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/accessories/message.update.success'), $response->messages); + $I->assertEquals($accessory->id, $response->payload->id); // accessory id does not change + $I->assertEquals($temp_accessory->company_id, $response->payload->company_id); // company_id updated + $I->assertEquals($temp_accessory->name, $response->payload->name); // accessory name updated + $I->assertEquals($temp_accessory->location_id, $response->payload->location_id); // accessory location_id updated + $temp_accessory->created_at = Carbon::parse($response->payload->created_at); + $temp_accessory->updated_at = Carbon::parse($response->payload->updated_at); + $temp_accessory->id = $accessory->id; + // verify + $I->sendGET('/accessories/' . $accessory->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + $I->seeResponseContainsJson((new AccessoriesTransformer)->transformAccessory($temp_accessory)); + } + + /** @test */ + public function deleteAccessoryTest(ApiTester $I, $scenario) + { + $I->wantTo('Delete an accessory'); + + // create + $accessory = factory(\App\Models\Accessory::class)->states('apple-bt-keyboard')->create([ + 'name' => "Soon to be deleted" + ]); + $I->assertInstanceOf(\App\Models\Accessory::class, $accessory); + + // delete + $I->sendDELETE('/accessories/' . $accessory->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/accessories/message.delete.success'), $response->messages); + + // verify, expect a 200 + $I->sendGET('/accessories/' . $accessory->id); + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + } +} diff --git a/tests/api/ApiAssetsCest.php b/tests/api/ApiAssetsCest.php index ea41b99f72..5a14120ff4 100644 --- a/tests/api/ApiAssetsCest.php +++ b/tests/api/ApiAssetsCest.php @@ -1,5 +1,8 @@ setupDatabase(); $this->faker = \Faker\Factory::create(); $this->user = \App\Models\User::find(1); - $this->timeFormat = Setting::getSettings()->date_display_format .' '. Setting::getSettings()->time_display_format; + Setting::getSettings()->time_display_format = "H:i"; $I->amBearerAuthenticated($I->getToken($this->user)); } @@ -24,105 +26,15 @@ class ApiAssetsCest $I->wantTo('Get a list of assets'); - // We rely on the seeded database for this. No need to create new assets. - // $assets = factory(\App\Models\Asset::class, 10)->create(); - // call - $I->sendGET('/hardware?limit=10'); + $I->sendGET('/hardware?limit=20&sort=id&order=desc'); $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); $response = json_decode($I->grabResponse(), true); // sample verify - $asset = App\Models\Asset::orderByDesc('created_at')->first(); - - $I->seeResponseContainsJson([ - - 'id' => (int) $asset->id, - 'name' => e($asset->name), - 'asset_tag' => e($asset->asset_tag), - 'serial' => e($asset->serial), - 'model' => ($asset->model) ? [ - 'id' => (int) $asset->model->id, - 'name'=> e($asset->model->name) - ] : null, - 'model_number' => ($asset->model) ? e($asset->model->model_number) : null, - 'status_label' => ($asset->assetstatus) ? [ - 'id' => (int) $asset->assetstatus->id, - 'name'=> e($asset->assetstatus->name) - ] : null, - 'category' => ($asset->model->category) ? [ - 'id' => (int) $asset->model->category->id, - 'name'=> e($asset->model->category->name) - ] : null, - 'manufacturer' => ($asset->model->manufacturer) ? [ - 'id' => (int) $asset->model->manufacturer->id, - 'name'=> e($asset->model->manufacturer->name) - ] : null, - 'supplier' => ($asset->supplier) ? [ - 'id' => (int) $asset->supplier->id, - 'name'=> e($asset->supplier->name) - ] : null, - 'notes' => e($asset->notes), - 'order_number' => e($asset->order_number), - 'company' => ($asset->company) ? [ - 'id' => (int) $asset->company->id, - 'name'=> e($asset->company->name) - ] : null, - 'location' => ($asset->location) ? [ - 'id' => (int) $asset->location->id, - 'name'=> e($asset->location->name) - ] : null, - 'rtd_location' => ($asset->defaultLoc) ? [ - 'id' => (int) $asset->defaultLoc->id, - 'name'=> e($asset->defaultLoc->name) - ] : null, - 'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null, - 'assigned_to' => ($asset->assigneduser) ? [ - 'id' => (int) $asset->assigneduser->id, - 'name' => e($asset->assigneduser->getFullNameAttribute()), - 'first_name'=> e($asset->assigneduser->first_name), - 'last_name'=> e($asset->assigneduser->last_name) - ] : null, - 'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null, - 'warranty_expires' => ($asset->warranty_months > 0) ? [ - 'datetime' => $asset->created_at->format('Y-m-d'), - 'formatted' => $asset->created_at->format('Y-m-d'), - ] : null, - - // I have no idea why these cause the test to fail. I think it's something about nested json. - // 'created_at' => ($asset->created_at) ? [ - // 'datetime' => $asset->created_at->format('Y-m-d H:i:s'), - // 'formatted' => $asset->created_at->format('Y-m-d H:i a'), - // ] : null, - // 'updated_at' => ($asset->updated_at) ? [ - // 'datetime' => $asset->updated_at->format('Y-m-d H:i:s'), - // 'formatted' => $asset->updated_at->format('Y-m-d H:i a'), - // ] : null, - // // TODO: Implement last_audit_date and next_audit_date - // 'purchase_date' => ($asset->purchase_date) ? [ - // 'datetime' => $asset->purchase_date->format('Y-m-d'), - // 'formatted' => $asset->purchase_date->format('Y-m-d'), - // ] : null, - // 'last_checkout' => ($asset->last_checkout) ? [ - // 'datetime' => $asset->last_checkout->format('Y-m-d'), - // 'formatted' => $asset->last_checkout->format('Y-m-d'), - // ] : null, - // 'expected_checkin' => ($asset->created_at) ? [ - // 'date' => $asset->created_at->format('Y-m-d'), - // 'formatted' => $asset->created_at->format('Y-m-d'), - // ] : null, - 'purchase_cost' => (float) $asset->purchase_cost, - 'user_can_checkout' => (bool) $asset->availableForCheckout(), - 'available_actions' => [ - 'checkout' => (bool) Gate::allows('checkout', Asset::class), - 'checkin' => (bool) Gate::allows('checkin', Asset::class), - 'clone' => (bool) Gate::allows('create', Asset::class), - 'restore' => (bool) false, // FIXME: when this gets implemented in assetstransformer it should be updated here - 'update' => (bool) Gate::allows('update', Asset::class), - 'delete' => (bool) Gate::allows('delete', Asset::class), - ], - ]); + $asset = Asset::orderByDesc('id')->take(20)->get()->first(); + $I->seeResponseContainsJson((new AssetsTransformer)->transformAsset($asset)); } /** @test */ @@ -185,6 +97,7 @@ class ApiAssetsCest 'model_id' => $temp_asset->model_id, 'name' => $temp_asset->name, 'notes' => $temp_asset->notes, + 'order_number' => $temp_asset->order_number, 'purchase_cost' => $temp_asset->purchase_cost, 'purchase_date' => $temp_asset->purchase_date->format('Y-m-d'), 'rtd_location_id' => $temp_asset->rtd_location_id, @@ -202,227 +115,23 @@ class ApiAssetsCest $I->seeResponseCodeIs(200); $response = json_decode($I->grabResponse()); + // dd($response); $I->assertEquals('success', $response->status); $I->assertEquals(trans('admin/hardware/message.update.success'), $response->messages); $I->assertEquals($asset->id, $response->payload->id); // asset id does not change $I->assertEquals($temp_asset->asset_tag, $response->payload->asset_tag); // asset tag updated $I->assertEquals($temp_asset->name, $response->payload->name); // asset name updated $I->assertEquals($temp_asset->rtd_location_id, $response->payload->rtd_location_id); // asset rtd_location_id updated - - // verify - $I->sendGET('/hardware/' . $asset->id); - // dd($I->grabResponse()); - $I->seeResponseIsJson(); - $I->seeResponseCodeIs(200); - $I->seeResponseContainsJson([ - 'id' => (int) $asset->id, - 'name' => e($temp_asset->name), - 'asset_tag' => e($temp_asset->asset_tag), - 'serial' => e($temp_asset->serial), - 'model' => ($temp_asset->model) ? [ - 'id' => (int) $temp_asset->model->id, - 'name'=> e($temp_asset->model->name) - ] : null, - 'model_number' => ($temp_asset->model) ? e($temp_asset->model->model_number) : null, - 'status_label' => ($temp_asset->assetstatus) ? [ - 'id' => (int) $temp_asset->assetstatus->id, - 'name'=> e($temp_asset->assetstatus->name), - 'status_type' => $temp_asset->assetstatus->getStatuslabelType(), - 'status_meta' => $temp_asset->present()->statusMeta - ] : null, - 'category' => ($temp_asset->model->category) ? [ - 'id' => (int) $temp_asset->model->category->id, - 'name'=> e($temp_asset->model->category->name) - ] : null, - 'manufacturer' => ($temp_asset->model->manufacturer) ? [ - 'id' => (int) $temp_asset->model->manufacturer->id, - 'name'=> e($temp_asset->model->manufacturer->name) - ] : null, - 'notes' => e($temp_asset->notes), - 'order_number' => e($asset->order_number), - 'company' => ($asset->company) ? [ - 'id' => (int) $temp_asset->company->id, - 'name'=> e($temp_asset->company->name) - ] : null, - 'rtd_location' => ($temp_asset->defaultLoc) ? [ - 'id' => (int) $temp_asset->defaultLoc->id, - 'name'=> e($temp_asset->defaultLoc->name) - ] : null, - 'image' => ($temp_asset->getImageUrl()) ? $temp_asset->getImageUrl() : null, - 'assigned_to' => ($temp_asset->assigneduser) ? [ - 'id' => (int) $temp_asset->assigneduser->id, - 'name' => e($temp_asset->assigneduser->getFullNameAttribute()), - 'first_name'=> e($temp_asset->assigneduser->first_name), - 'last_name'=> e($temp_asset->assigneduser->last_name) - ] : null, - 'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null, - 'warranty_expires' => ($asset->warranty_months > 0) ? [ - 'datetime' => $asset->created_at->format('Y-m-d'), - 'formatted' => $asset->created_at->format('Y-m-d'), - ] : null, - // 'created_at' => ($asset->created_at) ? [ - // 'datetime' => $asset->created_at->format('Y-m-d H:i:s'), - // 'formatted' => $asset->created_at->format($this->timeFormat), - // ] : null, - // 'updated_at' => ($asset->updated_at) ? [ - // 'datetime' => $asset->updated_at->format('Y-m-d H:i:s'), - // 'formatted' => $asset->updated_at->format($this->timeFormat), - // ] : null, - 'purchase_date' => ($asset->purchase_date) ? [ - 'date' => $temp_asset->purchase_date->format('Y-m-d'), - 'formatted' => $temp_asset->purchase_date->format('Y-m-d'), - ] : null, - // 'last_checkout' => ($asset->last_checkout) ? [ - // 'datetime' => $asset->last_checkout->format('Y-m-d'), - // 'formatted' => $asset->last_checkout->format('Y-m-d'), - // ] : null, - // 'expected_checkin' => ($asset->created_at) ? [ - // 'date' => $asset->created_at->format('Y-m-d'), - // 'formatted' => $asset->created_at->format('Y-m-d'), - // ] : null, - // 'purchase_cost' => (float) $asset->purchase_cost, - 'user_can_checkout' => (bool) $temp_asset->availableForCheckout(), - 'available_actions' => [ - 'checkout' => (bool) Gate::allows('checkout', Asset::class), - 'checkin' => (bool) Gate::allows('checkin', Asset::class), - 'update' => (bool) Gate::allows('update', Asset::class), - 'delete' => (bool) Gate::allows('delete', Asset::class), - ], - ]); - } - - /** @test */ - public function updateAssetWithPut(ApiTester $I) - { - $I->wantTo('Update a asset with PUT'); - - // create - $asset = factory(\App\Models\Asset::class)->states('laptop-mbp')->create([ - 'company_id' => 2, - 'name' => "Original name" - ]); - $I->assertInstanceOf(\App\Models\Asset::class, $asset); - - $temp_asset = factory(\App\Models\Asset::class)->states('laptop-air')->make([ - 'company_id' => 1, - 'name' => "Updated Name" - ]); - - $I->assertNotNull($temp_asset->asset_tag); - - $data = [ - 'asset_tag' => $temp_asset->asset_tag, - 'assigned_to' => $temp_asset->assigned_to, - 'company_id' => $temp_asset->company->id, - 'image' => $temp_asset->image, - 'model_id' => $temp_asset->model_id, - 'name' => $temp_asset->name, - 'notes' => $temp_asset->notes, - 'purchase_cost' => $temp_asset->purchase_cost, - 'purchase_date' => $temp_asset->purchase_date->format('Y-m-d'), - 'rtd_location_id' => $temp_asset->rtd_location_id, - 'serial' => $temp_asset->serial, - 'status_id' => $temp_asset->status_id, - 'supplier_id' => $temp_asset->supplier_id, - 'warranty_months' => $temp_asset->warranty_months, - ]; - - $I->assertNotEquals($asset->name, $data['name']); - - // update - $I->sendPUT('/hardware/' . $asset->id, $data); - $I->seeResponseIsJson(); - $I->seeResponseCodeIs(200); - - $response = json_decode($I->grabResponse()); - $I->assertEquals('success', $response->status); - $I->assertEquals(trans('admin/hardware/message.update.success'), $response->messages); - $I->assertEquals($asset->id, $response->payload->id); // asset id does not change - $I->assertEquals($temp_asset->asset_tag, $response->payload->asset_tag); // asset tag updated - $I->assertEquals($temp_asset->name, $response->payload->name); // asset name updated - $I->assertEquals($temp_asset->rtd_location_id, $response->payload->rtd_location_id); // asset rtd_location_id updated + $temp_asset->created_at = Carbon::parse($response->payload->created_at); + $temp_asset->updated_at = Carbon::parse($response->payload->updated_at); + $temp_asset->id = $asset->id; + $temp_asset->location_id = $response->payload->rtd_location_id; // verify $I->sendGET('/hardware/' . $asset->id); $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); - $I->seeResponseContainsJson([ - 'id' => (int) $asset->id, - 'name' => e($temp_asset->name), - 'asset_tag' => e($temp_asset->asset_tag), - 'serial' => e($temp_asset->serial), - 'model' => ($temp_asset->model) ? [ - 'id' => (int) $temp_asset->model->id, - 'name'=> e($temp_asset->model->name) - ] : null, - 'model_number' => ($temp_asset->model) ? e($temp_asset->model->model_number) : null, - 'status_label' => ($temp_asset->assetstatus) ? [ - 'id' => (int) $temp_asset->assetstatus->id, - 'name'=> e($temp_asset->assetstatus->name) - ] : null, - 'category' => ($temp_asset->model->category) ? [ - 'id' => (int) $temp_asset->model->category->id, - 'name'=> e($temp_asset->model->category->name) - ] : null, - 'manufacturer' => ($temp_asset->model->manufacturer) ? [ - 'id' => (int) $temp_asset->model->manufacturer->id, - 'name'=> e($temp_asset->model->manufacturer->name) - ] : null, - 'notes' => e($temp_asset->notes), - 'order_number' => e($asset->order_number), - 'company' => ($asset->company) ? [ - 'id' => (int) $temp_asset->company->id, - 'name'=> e($temp_asset->company->name) - ] : null, - // 'location' => ($temp_asset->location) ? [ - // 'id' => (int) $temp_asset->location->id, - // 'name'=> e($temp_asset->location->name) - // ] : null, - 'rtd_location' => ($temp_asset->defaultLoc) ? [ - 'id' => (int) $temp_asset->defaultLoc->id, - 'name'=> e($temp_asset->defaultLoc->name) - ] : null, - 'image' => ($temp_asset->getImageUrl()) ? $temp_asset->getImageUrl() : null, - 'assigned_to' => ($temp_asset->assigneduser) ? [ - 'id' => (int) $temp_asset->assigneduser->id, - 'name' => e($temp_asset->assigneduser->getFullNameAttribute()), - 'first_name'=> e($temp_asset->assigneduser->first_name), - 'last_name'=> e($temp_asset->assigneduser->last_name) - ] : null, - 'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null, - 'warranty_expires' => ($asset->warranty_months > 0) ? [ - 'datetime' => $asset->created_at->format('Y-m-d'), - 'formatted' => $asset->created_at->format('Y-m-d'), - ] : null, - // 'created_at' => ($asset->created_at) ? [ - // 'datetime' => $asset->created_at->format('Y-m-d H:i:s'), - // 'formatted' => $asset->created_at->format('Y-m-d H:i a'), - // ] : null, - // 'updated_at' => ($asset->updated_at) ? [ - // 'datetime' => $asset->updated_at->format('Y-m-d H:i:s'), - // 'formatted' => $asset->updated_at->format('Y-m-d H:i a'), - // ] : null, - 'purchase_date' => ($asset->purchase_date) ? [ - 'date' => $temp_asset->purchase_date->format('Y-m-d'), - 'formatted' => $temp_asset->purchase_date->format('Y-m-d'), - ] : null, - // 'last_checkout' => ($asset->last_checkout) ? [ - // 'datetime' => $asset->last_checkout->format('Y-m-d'), - // 'formatted' => $asset->last_checkout->format('Y-m-d'), - // ] : null, - // 'expected_checkin' => ($asset->created_at) ? [ - // 'date' => $asset->created_at->format('Y-m-d'), - // 'formatted' => $asset->created_at->format('Y-m-d'), - // ] : null, - // 'purchase_cost' => (float) $asset->purchase_cost, - 'user_can_checkout' => (bool) $temp_asset->availableForCheckout(), - 'available_actions' => [ - 'checkout' => (bool) Gate::allows('checkout', Asset::class), - 'checkin' => (bool) Gate::allows('checkin', Asset::class), - 'update' => (bool) Gate::allows('update', Asset::class), - 'delete' => (bool) Gate::allows('delete', Asset::class), - ], - ]); + $I->seeResponseContainsJson((new AssetsTransformer)->transformAsset($temp_asset)); } /** @test */ @@ -446,9 +155,10 @@ class ApiAssetsCest // verify, expect a 200 $I->sendGET('/hardware/' . $asset->id); $I->seeResponseCodeIs(200); - $I->seeResponseIsJson(); // @todo: response is not JSON + $I->seeResponseIsJson(); - - // $scenario->incomplete('not found response should be JSON, receiving HTML instead'); + // Make sure we're soft deleted. + $response = json_decode($I->grabResponse()); + $I->assertNotNull($response->deleted_at); } } diff --git a/tests/api/ApiCheckoutAssetsCest.php b/tests/api/ApiCheckoutAssetsCest.php new file mode 100644 index 0000000000..daf56fc5d5 --- /dev/null +++ b/tests/api/ApiCheckoutAssetsCest.php @@ -0,0 +1,141 @@ +user = \App\Models\User::find(1); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function checkoutAssetToUser(ApiTester $I) { + $I->wantTo('Check out an asset to a user'); + //Grab an asset from the database that isn't checked out. + $asset = Asset::whereNull('assigned_to')->first(); + $targetUser = factory('App\Models\User')->create(); + $data = [ + 'assigned_user' => $targetUser->id, + 'note' => "This is a test checkout note", + 'expected_checkin' => "2018-05-24", + 'name' => "Updated Asset Name", + 'checkout_to_type' => 'user' + ]; + $I->sendPOST("/hardware/{$asset->id}/checkout", $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/hardware/message.checkout.success'), $response->messages); + + // Confirm results. + $I->sendGET("/hardware/{$asset->id}"); + $I->seeResponseContainsJson([ + 'assigned_to' => [ + 'id' => $targetUser->id, + 'type' => 'user' + ], + 'name' => "Updated Asset Name", + 'expected_checkin' => Helper::getFormattedDateObject('2018-05-24', 'date') + ]); + + } + + /** @test */ + public function checkoutAssetToAsset(ApiTester $I) { + $I->wantTo('Check out an asset to an asset'); + //Grab an asset from the database that isn't checked out. + $asset = Asset::whereNull('assigned_to')->where('model_id',8)->first(); // We need to make sure that this is an asset/model that doesn't require acceptance + $targetAsset = factory('App\Models\Asset')->states('desktop-macpro')->create([ + 'name' => "Test Asset For Checkout to" + ]); + // dd($targetAsset->model->category); + $data = [ + 'assigned_asset' => $targetAsset->id, + 'checkout_to_type' => 'asset' + ]; + $I->sendPOST("/hardware/{$asset->id}/checkout", $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/hardware/message.checkout.success'), $response->messages); + + // Confirm results. + $I->sendGET("/hardware/{$asset->id}"); + $I->seeResponseContainsJson([ + 'assigned_to' => [ + 'id' => $targetAsset->id, + 'type' => 'asset' + ] + ]); + + } + + /** @test */ + public function checkoutAssetToLocation(ApiTester $I) { + $I->wantTo('Check out an asset to an asset'); + //Grab an asset from the database that isn't checked out. + $asset = Asset::whereNull('assigned_to')->where('model_id',8)->first(); + $targetLocation = factory('App\Models\Location')->create([ + 'name' => "Test Location for Checkout" + ]); + // dd($targetAsset->model->category); + $data = [ + 'assigned_location' => $targetLocation->id, + 'checkout_to_type' => 'location' + ]; + $I->sendPOST("/hardware/{$asset->id}/checkout", $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/hardware/message.checkout.success'), $response->messages); + + // Confirm results. + $I->sendGET("/hardware/{$asset->id}"); + $I->seeResponseContainsJson([ + 'assigned_to' => [ + 'id' => $targetLocation->id, + 'type' => 'location' + ] + ]); + + } + + /** @test */ + public function checkinAsset(ApiTester $I) { + $I->wantTo('Checkin an asset that is currently checked out'); + + $asset = Asset::whereNotNull('assigned_to')->first(); + + $I->sendPOST("/hardware/{$asset->id}/checkin", [ + "note" => "Checkin Note" + ]); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/hardware/message.checkin.success'), $response->messages); + + // Verify + $I->sendGET("/hardware/{$asset->id}"); + $I->seeResponseContainsJson([ + 'assigned_to' => null + ]); + } +} diff --git a/tests/api/ApiCompaniesCest.php b/tests/api/ApiCompaniesCest.php new file mode 100644 index 0000000000..35653b4e9e --- /dev/null +++ b/tests/api/ApiCompaniesCest.php @@ -0,0 +1,133 @@ +user = \App\Models\User::find(1); + $I->haveHttpHeader('Accept', 'application/json'); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function indexCompanys(ApiTester $I) + { + + $I->wantTo('Get a list of companies'); + + // call + $I->sendGET('/companies?order_by=id&limit=10'); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse(), true); + // dd($response); + // sample verify + $company = App\Models\Company::withCount('assets','licenses','accessories','consumables','components','users') + ->orderByDesc('created_at')->take(10)->get()->shuffle()->first(); + + $I->seeResponseContainsJson((new CompaniesTransformer)->transformCompany($company)); + } + + /** @test */ + public function createCompany(ApiTester $I, $scenario) + { + $I->wantTo('Create a new company'); + + $temp_company = factory(\App\Models\Company::class)->make([ + 'name' => "Test Company Tag", + ]); + + // setup + $data = [ + 'name' => $temp_company->name, + ]; + + // create + $I->sendPOST('/companies', $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + } + + // Put is routed to the same method in the controller + // DO we actually need to test both? + /** @test */ + public function updateCompanyWithPatch(ApiTester $I, $scenario) + { + $I->wantTo('Update an company with PATCH'); + + // create + $company = factory(\App\Models\Company::class)->create([ + 'name' => 'Original Company Name', + ]); + $I->assertInstanceOf(\App\Models\Company::class, $company); + + $temp_company = factory(\App\Models\Company::class)->make([ + 'name' => "updated company name", + ]); + + $data = [ + 'name' => $temp_company->name, + ]; + + $I->assertNotEquals($company->name, $data['name']); + + // update + $I->sendPATCH('/companies/' . $company->id, $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/companies/message.update.success'), $response->messages); + $I->assertEquals($company->id, $response->payload->id); // company id does not change + $I->assertEquals($temp_company->name, $response->payload->name); // company name updated + // Some manual copying to compare against + $temp_company->created_at = Carbon::parse($response->payload->created_at->datetime); + $temp_company->updated_at = Carbon::parse($response->payload->updated_at->datetime); + $temp_company->id = $company->id; + + // verify + $I->sendGET('/companies/' . $company->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + $I->seeResponseContainsJson((new CompaniesTransformer)->transformCompany($temp_company)); + + } + + /** @test */ + public function deleteCompanyTest(ApiTester $I, $scenario) + { + $I->wantTo('Delete an company'); + + // create + $company = factory(\App\Models\Company::class)->create([ + 'name' => "Soon to be deleted" + ]); + $I->assertInstanceOf(\App\Models\Company::class, $company); + + // delete + $I->sendDELETE('/companies/' . $company->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/companies/message.delete.success'), $response->messages); + + // verify, expect a 200 + $I->sendGET('/companies/' . $company->id); + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + } +} diff --git a/tests/api/ApiComponentsCest.php b/tests/api/ApiComponentsCest.php index d7e05f4a7d..33120be95d 100644 --- a/tests/api/ApiComponentsCest.php +++ b/tests/api/ApiComponentsCest.php @@ -1,18 +1,20 @@ faker = \Faker\Factory::create(); $this->user = \App\Models\User::find(1); - + $I->haveHttpHeader('Accept', 'application/json'); $I->amBearerAuthenticated($I->getToken($this->user)); } @@ -21,104 +23,81 @@ class ApiComponentsCest { $I->wantTo('Get a list of components'); - // setup - // $components = factory(\App\Models\Component::class, 10)->create(); - // call - $I->sendGET('/components?limit=10&order=desc'); + $I->sendGET('/components?limit=10'); $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); + $response = json_decode($I->grabResponse(), true); // sample verify - $component = Component::orderByDesc('created_at')->first(); - $I->seeResponseContainsJson([ - 'name' => $component->name, - 'qty' => $component->qty, - ]); + $component = App\Models\Component::orderByDesc('created_at')->take(10)->get()->shuffle()->first(); - $I->seeResponseContainsJson([ - 'total' => \App\Models\Component::count(), - ]); + $I->seeResponseContainsJson((new ComponentsTransformer)->transformComponent($component)); } /** @test */ - public function createComponent(ApiTester $I) + public function createComponent(ApiTester $I, $scenario) { $I->wantTo('Create a new component'); - // setup - $category = factory(\App\Models\Category::class)->states('asset-laptop-category')->create([ - 'name' => "Test Category Name", - 'user_id' => $this->user->id + $temp_component = factory(\App\Models\Component::class)->states('ram-crucial4')->make([ + 'name' => "Test Component Name", + 'company_id' => 2 ]); - $location = factory(\App\Models\Location::class)->create(['user_id' => $this->user->id]); - $company = factory(\App\Models\Company::class)->create(); + // setup $data = [ - 'category_id' => $category->id, - 'company_id' => $company->id, - 'location_id' => $location->id, - 'name' => $this->faker->sentence(3), - 'purchase_cost' => $this->faker->randomFloat(2, 0), - 'purchase_date' => $this->faker->dateTime->format('Y-m-d'), - 'qty' => rand(1, 10), + 'category_id' => $temp_component->category_id, + 'company_id' => $temp_component->company->id, + 'location_id' => $temp_component->location_id, + 'manufacturer_id' => $temp_component->manufacturer_id, + 'model_number' => $temp_component->model_number, + 'name' => $temp_component->name, + 'order_number' => $temp_component->order_number, + 'purchase_cost' => $temp_component->purchase_cost, + 'purchase_date' => $temp_component->purchase_date, + 'qty' => $temp_component->qty, + 'serial' => $temp_component->serial ]; // create $I->sendPOST('/components', $data); $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); - - $response = json_decode($I->grabResponse()); - $id = $response->payload->id; - - $I->assertEquals('success', $response->status); - - // verify - $I->sendGET('/components/' . $id); - $I->seeResponseIsJson(); - $I->seeResponseCodeIs(200); - $I->seeResponseContainsJson([ - 'id' => (int) $id, - 'name' => e($data['name']), - // 'serial_number' => e($component->serial), - 'location' => [ - 'id' => (int) $data['location_id'], - 'name' => e($location->name), - ], - 'qty' => number_format($data['qty']), - // 'min_amt' => e($component->min_amt), - 'category' => [ - 'id' => (int) $data['category_id'], - 'name' => e($category->name), - ], - // 'order_number' => e($component->order_number), - 'purchase_date' => \App\Helpers\Helper::getFormattedDateObject($data['purchase_date'], 'date'), - 'purchase_cost' => \App\Helpers\Helper::formatCurrencyOutput($data['purchase_cost']), - // 'remaining' => (int) $component->numRemaining(), - 'company' => [ - 'id' => (int) $data['company_id'], - 'name' => e($company->name), - ], - // 'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'), - // 'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'), - ]); } + // Put is routed to the same method in the controller + // DO we actually need to test both? /** @test */ - public function updateComponentWithPatch(ApiTester $I) + public function updateComponentWithPatch(ApiTester $I, $scenario) { - $I->wantTo('Update a component with PATCH'); + $I->wantTo('Update an component with PATCH'); // create $component = factory(\App\Models\Component::class)->states('ram-crucial4')->create([ - 'name' => "Test Component" + 'name' => 'Original Component Name', + 'company_id' => 2, + 'location_id' => 3 ]); $I->assertInstanceOf(\App\Models\Component::class, $component); + $temp_component = factory(\App\Models\Component::class)->states('ssd-crucial240')->make([ + 'company_id' => 3, + 'name' => "updated component name", + 'location_id' => 1, + ]); + $data = [ - 'name' => $this->faker->sentence(3), - 'qty' => $this->faker->randomDigit + 1, + 'category_id' => $temp_component->category_id, + 'company_id' => $temp_component->company->id, + 'location_id' => $temp_component->location_id, + 'min_amt' => $temp_component->min_amt, + 'name' => $temp_component->name, + 'order_number' => $temp_component->order_number, + 'purchase_cost' => $temp_component->purchase_cost, + 'purchase_date' => $temp_component->purchase_date, + 'qty' => $temp_component->qty, + 'serial' => $temp_component->serial, ]; $I->assertNotEquals($component->name, $data['name']); @@ -129,63 +108,31 @@ class ApiComponentsCest $I->seeResponseCodeIs(200); $response = json_decode($I->grabResponse()); - $I->assertEquals('success', $response->status); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/components/message.update.success'), $response->messages); + $I->assertEquals($component->id, $response->payload->id); // component id does not change + $I->assertEquals($temp_component->company_id, $response->payload->company_id); // company_id updated + $I->assertEquals($temp_component->name, $response->payload->name); // component name updated + $I->assertEquals($temp_component->location_id, $response->payload->location_id); // component location_id updated + $temp_component->created_at = Carbon::parse($response->payload->created_at); + $temp_component->updated_at = Carbon::parse($response->payload->updated_at); + $temp_component->id = $component->id; // verify $I->sendGET('/components/' . $component->id); $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); - $I->seeResponseContainsJson([ - 'name' => $data['name'], - 'id' => $component->id, - 'qty' => $data['qty'], - ]); - } - - /** @test */ - public function updateComponentWithPut(ApiTester $I) - { - $I->wantTo('Update a component with PUT'); - - // create - $component = factory(\App\Models\Component::class)->states('ram-crucial4')->create([ - 'name' => "Test Component" - ]); - $I->assertInstanceOf(\App\Models\Component::class, $component); - - $data = [ - 'name' => $this->faker->sentence(3), - ]; - - $I->assertNotEquals($component->name, $data['name']); - - // update - $I->sendPUT('/components/' . $component->id, $data); - $I->seeResponseIsJson(); - $I->seeResponseCodeIs(200); - - $response = json_decode($I->grabResponse()); - $I->assertEquals('success', $response->status); - - // verify - $I->sendGET('/components/' . $component->id); - $I->seeResponseIsJson(); - $I->seeResponseCodeIs(200); - $I->seeResponseContainsJson([ - 'name' => e($data['name']), - 'id' => e($component->id), - 'qty' => e($component->qty), - ]); + $I->seeResponseContainsJson((new ComponentsTransformer)->transformComponent($temp_component)); } /** @test */ public function deleteComponentTest(ApiTester $I, $scenario) { - $I->wantTo('Delete a component'); + $I->wantTo('Delete an component'); // create $component = factory(\App\Models\Component::class)->states('ram-crucial4')->create([ - 'name' => "Test Component" + 'name' => "Soon to be deleted" ]); $I->assertInstanceOf(\App\Models\Component::class, $component); @@ -194,10 +141,15 @@ class ApiComponentsCest $I->seeResponseIsJson(); $I->seeResponseCodeIs(200); - // verify, expect a 200 with an error message + $response = json_decode($I->grabResponse()); + // dd($response); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/components/message.delete.success'), $response->messages); + + // verify, expect a 200 $I->sendGET('/components/' . $component->id); + $I->seeResponseCodeIs(200); - $I->seeResponseIsJson(); // @todo: response is not JSON - // $scenario->incomplete('Resource not found response should be JSON, receiving HTML instead'); + $I->seeResponseIsJson(); } } diff --git a/tests/api/ApiConsumablesCest.php b/tests/api/ApiConsumablesCest.php new file mode 100644 index 0000000000..d7938195b5 --- /dev/null +++ b/tests/api/ApiConsumablesCest.php @@ -0,0 +1,154 @@ +user = \App\Models\User::find(1); + $I->haveHttpHeader('Accept', 'application/json'); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function indexConsumables(ApiTester $I) + { + $I->wantTo('Get a list of consumables'); + + // call + $I->sendGET('/consumables?limit=10'); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse(), true); + // sample verify + $consumable = App\Models\Consumable::orderByDesc('created_at')->take(10)->get()->shuffle()->first(); + + $I->seeResponseContainsJson((new ConsumablesTransformer)->transformConsumable($consumable)); + } + + /** @test */ + public function createConsumable(ApiTester $I, $scenario) + { + $I->wantTo('Create a new consumable'); + + $temp_consumable = factory(\App\Models\Consumable::class)->states('ink')->make([ + 'name' => "Test Consumable Name", + 'company_id' => 2 + ]); + + // setup + $data = [ + 'category_id' => $temp_consumable->category_id, + 'company_id' => $temp_consumable->company->id, + 'location_id' => $temp_consumable->location_id, + 'manufacturer_id' => $temp_consumable->manufacturer_id, + 'name' => $temp_consumable->name, + 'order_number' => $temp_consumable->order_number, + 'purchase_cost' => $temp_consumable->purchase_cost, + 'purchase_date' => $temp_consumable->purchase_date, + 'qty' => $temp_consumable->qty, + 'model_number' => $temp_consumable->model_number, + ]; + + // create + $I->sendPOST('/consumables', $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + } + + // Put is routed to the same method in the controller + // DO we actually need to test both? + /** @test */ + public function updateConsumableWithPatch(ApiTester $I, $scenario) + { + $I->wantTo('Update an consumable with PATCH'); + + // create + $consumable = factory(\App\Models\Consumable::class)->states('ink')->create([ + 'name' => 'Original Consumable Name', + 'company_id' => 2, + 'location_id' => 3 + ]); + $I->assertInstanceOf(\App\Models\Consumable::class, $consumable); + + $temp_consumable = factory(\App\Models\Consumable::class)->states('cardstock')->make([ + 'company_id' => 3, + 'name' => "updated consumable name", + 'location_id' => 1, + ]); + + $data = [ + 'category_id' => $temp_consumable->category_id, + 'company_id' => $temp_consumable->company->id, + 'item_no' => $temp_consumable->item_no, + 'location_id' => $temp_consumable->location_id, + 'name' => $temp_consumable->name, + 'order_number' => $temp_consumable->order_number, + 'purchase_cost' => $temp_consumable->purchase_cost, + 'purchase_date' => $temp_consumable->purchase_date, + 'model_number' => $temp_consumable->model_number, + 'manufacturer_id' => $temp_consumable->manufacturer_id, + 'supplier_id' => $temp_consumable->supplier_id, + 'qty' => $temp_consumable->qty, + ]; + + $I->assertNotEquals($consumable->name, $data['name']); + + // update + $I->sendPATCH('/consumables/' . $consumable->id, $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/consumables/message.update.success'), $response->messages); + $I->assertEquals($consumable->id, $response->payload->id); // consumable id does not change + $I->assertEquals($temp_consumable->company_id, $response->payload->company_id); // company_id updated + $I->assertEquals($temp_consumable->name, $response->payload->name); // consumable name updated + $I->assertEquals($temp_consumable->location_id, $response->payload->location_id); // consumable location_id updated + $temp_consumable->created_at = Carbon::parse($response->payload->created_at); + $temp_consumable->updated_at = Carbon::parse($response->payload->updated_at); + $temp_consumable->id = $consumable->id; + // verify + $I->sendGET('/consumables/' . $consumable->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + $I->seeResponseContainsJson((new ConsumablesTransformer)->transformConsumable($temp_consumable)); + } + + /** @test */ + public function deleteConsumableTest(ApiTester $I, $scenario) + { + $I->wantTo('Delete an consumable'); + + // create + $consumable = factory(\App\Models\Consumable::class)->states('ink')->create([ + 'name' => "Soon to be deleted" + ]); + $I->assertInstanceOf(\App\Models\Consumable::class, $consumable); + + // delete + $I->sendDELETE('/consumables/' . $consumable->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/consumables/message.delete.success'), $response->messages); + + // verify, expect a 200 + $I->sendGET('/consumables/' . $consumable->id); + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + } +} diff --git a/tests/api/ApiLocationsCest.php b/tests/api/ApiLocationsCest.php new file mode 100644 index 0000000000..b30bb317e5 --- /dev/null +++ b/tests/api/ApiLocationsCest.php @@ -0,0 +1,145 @@ +user = \App\Models\User::find(1); + $this->timeFormat = Setting::getSettings()->date_display_format .' '. Setting::getSettings()->time_display_format; + $this->dateFormat = Setting::getSettings()->date_display_format; + $I->haveHttpHeader('Accept', 'application/json'); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function indexLocations(ApiTester $I) + { + + $I->wantTo('Get a list of locations'); + + // call + $I->sendGET('/locations?limit=1'); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse(), true); + // sample verify + $location = App\Models\Location::orderByDesc('created_at') + ->withCount('assignedAssets', 'assets', 'users') + ->take(1)->get()->shuffle()->first(); + $I->seeResponseContainsJson((new LocationsTransformer)->transformLocation($location)); + } + + /** @test */ + public function createLocation(ApiTester $I, $scenario) + { + $I->wantTo('Create a new location'); + + $temp_location = factory(\App\Models\Location::class)->make([ + 'name' => "Test Location Tag", + ]); + + // setup + $data = [ + 'name' => $temp_location->name, + ]; + + // create + $I->sendPOST('/locations', $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + } + + // Put is routed to the same method in the controller + // DO we actually need to test both? + /** @test */ + public function updateLocationWithPatch(ApiTester $I, $scenario) + { + $I->wantTo('Update an location with PATCH'); + + // create + $location = factory(\App\Models\Location::class)->create([ + 'name' => 'Original Location Name', + ]); + $I->assertInstanceOf(\App\Models\Location::class, $location); + + $temp_location = factory(\App\Models\Location::class)->make([ + 'name' => "updated location name", + ]); + + $data = [ + 'name' => $temp_location->name, + 'image' => $temp_location->image, + 'address' => $temp_location->address, + 'address2' => $temp_location->address2, + 'city' => $temp_location->city, + 'state' => $temp_location->state, + 'country' => $temp_location->country, + 'zip' => $temp_location->zip, + 'parent_id' => $temp_location->parent_id, + 'parent_id' => $temp_location->parent_id, + 'manager_id' => $temp_location->manager_id, + 'currency' => $temp_location->currency + ]; + + $I->assertNotEquals($location->name, $data['name']); + + // update + $I->sendPATCH('/locations/' . $location->id, $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/locations/message.update.success'), $response->messages); + $I->assertEquals($location->id, $response->payload->id); // location id does not change + $I->assertEquals($temp_location->name, $response->payload->name); // location name updated + + // Some necessary manual copying + $temp_location->created_at = Carbon::parse($response->payload->created_at->datetime); + $temp_location->updated_at = Carbon::parse($response->payload->updated_at->datetime); + $temp_location->id = $location->id; + // verify + $I->sendGET('/locations/' . $location->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + $I->seeResponseContainsJson((new LocationsTransformer)->transformLocation($temp_location)); + // $I->seeResponseContainsJson($this->generateJsonResponse($temp_location, $location)); + } + + /** @test */ + public function deleteLocationTest(ApiTester $I, $scenario) + { + $I->wantTo('Delete an location'); + + // create + $location = factory(\App\Models\Location::class)->create([ + 'name' => "Soon to be deleted" + ]); + $I->assertInstanceOf(\App\Models\Location::class, $location); + + // delete + $I->sendDELETE('/locations/' . $location->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/locations/message.delete.success'), $response->messages); + + // verify, expect a 200 + $I->sendGET('/locations/' . $location->id); + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + } +} diff --git a/tests/api/ApiStatusLabelsCest.php b/tests/api/ApiStatusLabelsCest.php new file mode 100644 index 0000000000..d3f02e843c --- /dev/null +++ b/tests/api/ApiStatusLabelsCest.php @@ -0,0 +1,143 @@ +user = \App\Models\User::find(1); + $I->haveHttpHeader('Accept', 'application/json'); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function indexStatuslabels(ApiTester $I) + { + + $I->wantTo('Get a list of statuslabels'); + + // call + $I->sendGET('/statuslabels?limit=10'); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse(), true); + // sample verify + $statuslabel = App\Models\Statuslabel::orderByDesc('created_at') + ->withCount('assets') + ->take(10)->get()->shuffle()->first(); + $I->seeResponseContainsJson((new StatuslabelsTransformer)->transformStatuslabel($statuslabel)); + } + + /** @test */ + public function createStatuslabel(ApiTester $I, $scenario) + { + $I->wantTo('Create a new statuslabel'); + + $temp_statuslabel = factory(\App\Models\Statuslabel::class)->make([ + 'name' => "Test Statuslabel Tag", + ]); + + // setup + $data = [ + 'name' => $temp_statuslabel->name, + 'archived' => $temp_statuslabel->archived, + 'deployable' => $temp_statuslabel->deployable, + 'notes' => $temp_statuslabel->notes, + 'pending' => $temp_statuslabel->pending, + 'type' => 'deployable' + ]; + + // create + $I->sendPOST('/statuslabels', $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + } + + // Put is routed to the same method in the controller + // DO we actually need to test both? + /** @test */ + public function updateStatuslabelWithPatch(ApiTester $I, $scenario) + { + $I->wantTo('Update an statuslabel with PATCH'); + + // create + $statuslabel = factory(\App\Models\Statuslabel::class)->states('rtd')->create([ + 'name' => 'Original Statuslabel Name', + ]); + $I->assertInstanceOf(\App\Models\Statuslabel::class, $statuslabel); + + $temp_statuslabel = factory(\App\Models\Statuslabel::class)->states('pending')->make([ + 'name' => "updated statuslabel name", + 'type' => 'pending' + ]); + + $data = [ + 'name' => $temp_statuslabel->name, + 'archived' => $temp_statuslabel->archived, + 'deployable' => $temp_statuslabel->deployable, + 'notes' => $temp_statuslabel->notes, + 'pending' => $temp_statuslabel->pending, + 'type' => $temp_statuslabel->type + ]; + + $I->assertNotEquals($statuslabel->name, $data['name']); + + // update + $I->sendPATCH('/statuslabels/' . $statuslabel->id, $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); +// dd($response); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/statuslabels/message.update.success'), $response->messages); + $I->assertEquals($statuslabel->id, $response->payload->id); // statuslabel id does not change + $I->assertEquals($temp_statuslabel->name, $response->payload->name); // statuslabel name updated + // Some manual copying to compare against + $temp_statuslabel->created_at = Carbon::parse($response->payload->created_at); + $temp_statuslabel->updated_at = Carbon::parse($response->payload->updated_at); + $temp_statuslabel->id = $statuslabel->id; + + // verify + $I->sendGET('/statuslabels/' . $statuslabel->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + $I->seeResponseContainsJson((new StatuslabelsTransformer)->transformStatuslabel($temp_statuslabel)); + + } + + /** @test */ + public function deleteStatuslabelTest(ApiTester $I, $scenario) + { + $I->wantTo('Delete an statuslabel'); + + // create + $statuslabel = factory(\App\Models\Statuslabel::class)->create([ + 'name' => "Soon to be deleted" + ]); + $I->assertInstanceOf(\App\Models\Statuslabel::class, $statuslabel); + + // delete + $I->sendDELETE('/statuslabels/' . $statuslabel->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/statuslabels/message.delete.success'), $response->messages); + + // verify, expect a 200 + $I->sendGET('/statuslabels/' . $statuslabel->id); + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + } +} diff --git a/tests/api/ApiUsersCest.php b/tests/api/ApiUsersCest.php new file mode 100644 index 0000000000..0744035a97 --- /dev/null +++ b/tests/api/ApiUsersCest.php @@ -0,0 +1,190 @@ +user = \App\Models\User::find(1); + $I->haveHttpHeader('Accept', 'application/json'); + $I->amBearerAuthenticated($I->getToken($this->user)); + } + + /** @test */ + public function indexUsers(ApiTester $I) + { + $I->wantTo('Get a list of users'); + + // call + $I->sendGET('/users?limit=10&sort=created_at'); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse(), true); + // sample verify + $user = App\Models\User::orderByDesc('created_at') + ->withCount('assets', 'licenses', 'accessories', 'consumables') + ->take(10)->get()->shuffle()->first(); + $I->seeResponseContainsJson((new UsersTransformer)->transformUser($user)); + } + + /** @test */ + public function createUser(ApiTester $I, $scenario) + { + $I->wantTo('Create a new user'); + + $temp_user = factory(\App\Models\User::class)->make([ + 'name' => "Test User Name", + ]); + + // setup + $data = [ + 'activated' => $temp_user->activated, + 'address' => $temp_user->address, + 'city' => $temp_user->city, + 'company_id' => $temp_user->company_id, + 'country' => $temp_user->country, + 'department_id' => $temp_user->department_id, + 'email' => $temp_user->email, + 'employee_num' => $temp_user->employee_num, + 'first_name' => $temp_user->first_name, + 'jobtitle' => $temp_user->jobtitle, + 'last_name' => $temp_user->last_name, + 'locale' => $temp_user->locale, + 'location_id' => $temp_user->location_id, + 'notes' => $temp_user->notes, + 'manager_id' => $temp_user->manager_id, + 'password' => $temp_user->password, + 'phone' => $temp_user->phone, + 'state' => $temp_user->state, + 'username' => $temp_user->username, + 'zip' => $temp_user->zip, + ]; + + // create + $I->sendPOST('/users', $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + } + + // Put is routed to the same method in the controller + // DO we actually need to test both? + /** @test */ + public function updateUserWithPatch(ApiTester $I, $scenario) + { + $I->wantTo('Update an user with PATCH'); + + // create + $user = factory(\App\Models\User::class)->create([ + 'first_name' => 'Original User Name', + 'company_id' => 2, + 'location_id' => 3 + ]); + $I->assertInstanceOf(\App\Models\User::class, $user); + + $temp_user = factory(\App\Models\User::class)->make([ + 'company_id' => 3, + 'first_name' => "updated user name", + 'location_id' => 1, + ]); + + $data = [ + 'activated' => $temp_user->activated, + 'address' => $temp_user->address, + 'city' => $temp_user->city, + 'company_id' => $temp_user->company_id, + 'country' => $temp_user->country, + 'department_id' => $temp_user->department_id, + 'email' => $temp_user->email, + 'employee_num' => $temp_user->employee_num, + 'first_name' => $temp_user->first_name, + 'jobtitle' => $temp_user->jobtitle, + 'last_name' => $temp_user->last_name, + 'locale' => $temp_user->locale, + 'location_id' => $temp_user->location_id, + 'notes' => $temp_user->notes, + 'manager_id' => $temp_user->manager_id, + 'password' => $temp_user->password, + 'phone' => $temp_user->phone, + 'state' => $temp_user->state, + 'username' => $temp_user->username, + 'zip' => $temp_user->zip, + ]; + + $I->assertNotEquals($user->first_name, $data['first_name']); + + // update + $I->sendPATCH('/users/' . $user->id, $data); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/users/message.success.update'), $response->messages); + $I->assertEquals($user->id, $response->payload->id); // user id does not change + $I->assertEquals($temp_user->company_id, $response->payload->company->id); // company_id updated + $I->assertEquals($temp_user->first_name, $response->payload->first_name); // user name updated + $I->assertEquals($temp_user->location_id, $response->payload->location->id); // user location_id updated + $temp_user->created_at = Carbon::parse($response->payload->created_at->datetime); + $temp_user->updated_at = Carbon::parse($response->payload->updated_at->datetime); + $temp_user->id = $user->id; + // verify + $I->sendGET('/users/' . $user->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + $I->seeResponseContainsJson((new UsersTransformer)->transformUser($temp_user)); + } + + /** @test */ + public function deleteUserTest(ApiTester $I, $scenario) + { + $I->wantTo('Delete an user'); + + // create + $user = factory(\App\Models\User::class)->create([ + 'first_name' => "Soon to be deleted" + ]); + $I->assertInstanceOf(\App\Models\User::class, $user); + + // delete + $I->sendDELETE('/users/' . $user->id); + $I->seeResponseIsJson(); + $I->seeResponseCodeIs(200); + + $response = json_decode($I->grabResponse()); + // dd($response); + $I->assertEquals('success', $response->status); + $I->assertEquals(trans('admin/users/message.success.delete'), $response->messages); + + // verify, expect a 200 + $I->sendGET('/users/' . $user->id); + + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + } + + /** @test */ + public function fetchUserAssetsTest(ApiTester $I, $scenario) { + $I->wantTo("Fetch assets for a user"); + + $user = User::has('assets')->first(); + $asset = $user->assets->shuffle()->first(); + $I->sendGET("/users/{$user->id}/assets"); + $response = json_decode($I->grabResponse()); + $I->seeResponseCodeIs(200); + $I->seeResponseIsJson(); + + // Just test a random one. + $I->seeResponseContainsJson([ + 'asset_tag' => $asset->asset_tag, + ]); + } +}