Is there a default global scope on the Conversations model that uses the authenticated user somehow?
It is impossible to know for sure without seeing the query/ies that were attempted?
Hi There,
I'm writing some tests around a method called MessageController::store()
The input is validated using a custom rule ConversationPausedCheck to see if the Message I'm creating will be a associated to a Conversation model which currently has a 'paused' status.
Inside my store() method I also use MessagePolicy to validate that the current user is allowed to add messages to this conversation.
My 'positive test' works fine, validation passes and the message is created.
The problem comes when I try to test that my MessagePolicy is working correctly by running exactly the same test with a user who is not authorised to add messages to the current conversation. This test doesn't get as far as the policy challenge but fails in ConversationPausedCheck rule which is making no sense to me.
my store() method:
public function store(MessageStoreRequest $request ): RedirectResponse
{
$currentUser = Auth::User();
//get the validated data from the form request
$validated = $request->validated();
$message = new Message($validated);
$message->user_id = $currentUser->id;
$this->authorize('store',$message);
$message->save();
///
}
MessageStoreRequest:
public function rules(): array
{
return [
'message' => 'required',
'conversation_id' => ['required','exists:conversations,id', new ConversationPausedCheck],
];
}
ConversationPausedCheck:
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$conversation = Conversation::find($value);
if ($conversation->blocked_by !== null){
$fail('This :attribute is currently paused from messaging');
}
}
My test:
public function test_store_method_with_unauthorised_user()
{
// Arrange
$user = User::factory()->create();
$conversation = $this->setUpTestConversation($user);
$unauthUser = User::factory()->create();
Notification::fake();
// ASSERT
$this->assertDatabaseCount('messages',30);
// Act
$this->actingAs($unauthUser);
$response = $this
->from(route('feed'))
->followingRedirects()
->post(route('message.store'),['conversation_id' => $conversation->id, 'message' => 'This is a test message']);
//ASSERT
$response
->assertStatus(403);
$this->assertDatabaseCount('messages',30);
Notification::assertNothingSent();
}
This test fails in ConversationPausedCheck because $conversation is null even though $value=1 and there is definitely an entry in conversations table with ID 1.
If I change the test to $this->actingAs($user) then validation passes fine.
I have no other middleware, gates, policies and I am completely baffled!
Sorry for the very long-winded question, but can anyone help me understand?
Is there a default global scope on the Conversations model that uses the authenticated user somehow?
It is impossible to know for sure without seeing the query/ies that were attempted?
Please or to participate in this conversation.