User and team factory for Laravel Jetstream tests

As many of you know, LoadForge is a Laravel project. In specific our stack looks like this:

  • Laravel
  • Jetstream
  • Livewire
  • Tailwind
  • AlpineJS

Also known as a TALL stack, which is a set of frameworks used to build interactive apps using like LoadForge, based on Laravel.

Unit testing our stack is made easy by two factories (User and Team) and a global function we call getSubscribedUser(). Factories are a way Laravel provides a mock model (e.g. a User) in order to use in your tests. Jetstream requires all users have a team, and so we mock a user and team for majority of our tests.

Then we subscribe that user to a package, but that's of course optional depending on your stack.

The code

The code is in 3 primary files, our two factories and then in our base TestCase.php. We will start with the two factories:

# database/factories/UserFactory.php
<?php

namespace Database\Factories;

use App\Helpers\SubHelper;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    protected $model = User::class;

    public function configure()
    {
        return $this->afterMaking(function (User $user) {
            //
        })->afterCreating(function (User $user) {
            // This part is optional, it's us allocating a Stripe subscription to the user.
            $user->newSubscription(SubHelper::productDefault(), SubHelper::pricePremium())
                ->create('pm_card_visa');
        });
    }

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}

# database/factories/TeamFactory.php
<?php

namespace Database\Factories;

use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;

class TeamFactory extends Factory
{
    protected $model = Team::class;

    public function definition()
    {
        return [
            'name' => $this->faker->name
        ];
    }
}

This allows us to call UserFactory and receive a subscribed (optionally) user with a team pre-allocated. This user is fully functional on a Laravel Jetstream app.

Now we alter our Test Case to provide the function globally:

# tests/TestCase.php
<?php

namespace Tests;

use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    public function getSubscribedUser()
    {
        return User::factory()->hasAttached(
            Team::factory()
                ->state(function (array $attributes, User $user) {
                    return ['user_id' => $user->id, 'personal_team' => true];
                }),
        )->create();
    }
}

Using the function

You can now call getSubscribedUser in any of your unit tests. For example here is a small test to check a user who tries to go to Hosts without setting up their cloud account is redirected:

public function test_hosts_redirect()
{
    $user = $this->getSubscribedUser();

    $response = $this->actingAs($user)->get('/hosts');
    $this->assertMatchesRegularExpression('/Cloud Setup Required/', $response->content());
}

Final words

We hope this types of articles are helpful to our community, we have many Laravel users who run load tests. If you're interested in learning more about Laravel Load Testing please do visit our specific guide.

Ready to run that test?
Start your first test within minutes.