Okay, based on my research that is the default behavior of testing, which processes each test method sequentially.
And I need to use Laravel Dusk, which is specifically designed for testing interactions with a web application, including simulating concurrent requests.
With Dusk, you can run browser tests that execute multiple requests simultaneously.
Here's my solution using the Dusk test:
/** @test */
public function concurrent_purchases(): void
{
// Arrange: Create a user and an item
$user = User::factory()->create();
$item = Item::factory()->create();
// Act: Use Dusk to execute concurrent requests
$this->browse(function (Browser $browser1, Browser $browser2) use ($user, $item) {
tap($browser1->loginAs($user)
->visit(route('purchases.create')), function (Browser $browser) use ($item) {
$browser->type('item_id', $item->id)
$browser->script("document.getElementById('purchase').click()");
})
->assertRouteIs('purchases.index')
->waitForText('Purchase successful.', 5);
tap($browser2->loginAs($user)
->visit(route('purchases.create')), function (Browser $browser) use ($item) {
$browser->type('item_id', $item->id)
$browser->script("document.getElementById('purchase').click()");
})
->assertRouteIs('purchases.create')
->waitForText('Another purchase operation is already in progress. Please try again later.', 5);
});
}
Notice I use $browser->script("document.getElementById('purchase').click()"); here because I'm getting an error that dusk can't click the button because of the debugbar.
But if you prefer press() you can do ->press('Press') to press the button.