propertyテーブルが関係するテストを実装しています。
編集エラーテストの前にバリデーション未設定について解決を行いましたので、いよいよ編集エラー時のテストを実施していきます。
今回の目的
Propertyテーブルに関連する設定で、想定されるエラーに対しての動作が正常にできていることを確認する
なぜやるか
バリデーションなどエラーに対しての処理が正常に行えている担保をとるため
やりたいこと
- 想定されるエラーに対してのエラー表示がされていることを確認する
- リダイレクト処理が正常にできていることを確認する
やったこと
- 所有書籍のタイトルを削除するとエラーとなること
- 存在しない所有書籍情報を編集しようとするとエラーとなること
- 他人の所有情報を編集できないようにする
- 他人の所有情報を編集しようとするとエラーとなること
実施内容
編集時のエラーテストを実装する
タイトルがない場合
前回の記事でそもそもタイトル編集は行わないといいながら、テストを行っています。
不正な登録としてタイトル情報、bookdata_idが送信されても更新されないことを確認することで、テストを行っています。
# ~/tests/Feature/PropertyTest.php
// 所有書籍情報編集NG、タイトルなし
public function test_propertyControll_ng_notTitleEdit()
{
// property 自動生成 // 関連 user,bookdataも作成
$propertydata = factory(Property::class)->create();
// ユーザーログイン
$user = User::first(); // 作成済みユーザー情報取得
$this->actingAs($user); // 選択ユーザーでログイン
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
//// 編集パス
$propertypath = 'property/'.$propertydata->id.'/edit'; // 書籍編集パス
//// 編集
$editpropertydata = [
'bookdata_id' => '',
'_method' => 'PUT',
]; // タイトルなしに編集
$response = $this->from($propertypath)->
post('property/'.$propertydata->id, $editpropertydata); // 本情報保存
$response->assertSessionHasErrors(['bookdata_id']); // エラーメッセージがあること
$response->assertStatus(302); // リダイレクト
$response->assertRedirect($propertypath); // トップページ表示
$this->assertEquals('bookdata idは必須です。',
session('errors')->first('bookdata_id')); // エラメッセージを確認
}
Propertyファクトリーで、所有書籍と関連する書籍情報・ユーザー情報をまとめて作成し、作成ユーザーでログインしています。
そして、作成されている所有書籍情報の編集ページから送信するpostデータにbookdata_id=>''を指定して、書籍idを削除しているパターンです。
結果として、bookdata_idカラム情報は送信されるのでバリデーションにひっかかり、エラーが返ってきます。
propertyテーブルにまだ存在していないidを指定する
propertyテーブルに1件のみ登録した状態で2件目の編集を強制的に行っています。
# ~/tests/Feature/PropertyTest.php
// 所有書籍情報編集NG、未登録id
public function test_propertyControll_ng_notIdEdit()
{
// property 自動生成 // 関連 user,bookdataも作成
$propertydata = factory(Property::class)->create();
// ユーザーログイン
$user = User::first(); // 作成済みユーザー情報取得
$this->actingAs($user); // 選択ユーザーでログイン
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
// 編集パス
$propertypath = 'property/2/edit'; // 書籍編集パス(存在しないID)
// アクセス不可
$response = $this->get($propertypath); // ページにアクセス
$response->assertStatus(500); // 500ステータスであること
}
ファクトリーにより1件の情報を作成しています。
この時点ではpropertyテーブルのid=1に対して、user_id=1,bookdata_id=1というデータのみが存在する状態です。
この状態でpropertyテーブルのid=2を編集しようとしています。
当然、まだ存在しないテーブルですので編集できるわけがなく、エラーとして帰ってきます。
他人が所有している書籍情報を強制的に書き換える
自分の所有書籍を編集するのが基本ですが、プログラム上で強制的に他人の所有書籍を変更させてみたところ、変更できてしまいました。
propertyテーブル,user_id=1,bookdata_id=1というデータがあったとして、user_id=2の人がログインした状態でこのレコードの情報を無理矢理変更しようというものです。
テストとしてuser_id=2でログインした状態を作り、propertyレコード宛てにpost送信すると更新できました。
と、この場合、更新できては困るので、先にこの対策を行います。
# ~/app/Http/Controllers/PropertyController.php
public function update(Request $request, $id)
{
// バリデーションチェック
$createPropertyRules = Property::createPropertyRules();
$this->validate($request, $createPropertyRules);
// 対象レコード取得
$property = Property::find($id);
// 本人認証の上、更新処理
if ($property['user_id'] == Auth::user()->id){
$form = $request->all();
unset($form['_token']);
// レコードアップデート
$property->fill($form)->save();
}
return redirect('/property');
}
ifによって取得したpropertyレコード内のuser_idとログインユーザーのidを照合し、本人であれば編集する形に変更としました。
本来フォーム上からこのような状態のデータは送信されない設計となっていますが、テスト上で通っていた問題点は解決しておくべきなので、処理を追加しています。
対策が完了したので、改めて他人の所有書籍編集に対してテストを実施します。
# ~/tests/Feature/PropertyTest.php
// 複数ユーザーデータ有りで他人データ編集
public function test_propertySomeControll_ng_otherUserDataEdit()
{
// 設定
$usernumber = 2;// ユーザー数
$booknumber = 10;// 所有書籍数
// ユーザー情報
factory(User::class, $usernumber)->create(); // 複数ユーザー作成
$user = User::find(1); // ユーザー情報取得
$this->actingAs($user); // 選択ユーザーでログイン
$this->assertTrue(Auth::check()); // Auth認証済であることを確認
// 所有書籍情報登録
// 複数ユーザー分の所有書籍情報
for ($usercount = 1; $usercount <= $usernumber; $usercount++) {
// 各ユーザーに対して複数書籍所持情報を作成
for ($i = 1; $i <= $booknumber; $i++) {
$propertydata = factory(Property::class)->create([
'user_id' => $usercount,
]);
}
}
//// 編集パス
$propertypath = 'property/11/edit'; // 書籍編集パス
//// 登録
$editpropertydata = [
'number' => 11,
'_method' => 'PUT',
]; // タイトルを編集
$response = $this->from($propertypath)->post('property/11', $editpropertydata);
// 本情報保存
$response->assertStatus(302); // リダイレクト
$response->assertRedirect('property'); // indexへリダイレクト
// DBが変更されていないこと
$savebook = Property::find(11);
$this->assertDatabaseHas('properties', [
'id' => $savebook->id,
'number' => $savebook->number,
]); //DBに配列で指定した情報が残っていること
}
2人のユーザーを準備し、それぞれ10件の書籍を所有している状態としました。
この時点でユーザー1がbookdata_id=1〜10、ユーザー2がbookdata_id_11=20を所有している状態です。
ユーザー1でログインしておき、ユーザー2のbookdata_id=11を強制的に編集しています。
本来であれば、ユーザーが異なるのでそもそもproperty/11にはアクセスできないはずですが、それでもユーザーが異なる場合は編集できないことを確認しています。
最後にDB上でも変更されていないことを確認して、他人の所有書籍が変更できていないことを確認しました。
以上で、編集時のエラーテストは終了です。
残るは削除時のエラーテストを実施します。