KalimeroMK's avatar

Test Invitation Mail

When admin create a user it sends invitation email with a password reset link and it working nice when is sending the mail manually on the staging server but need to write a test but when run the test is failing hire is my code

Controller

public function store(CreateUser $request)
    {
        $input = $request->validated();
        if ($user = User::getByEmail($input['email'], true)) {
            $user->deleted_at = null;
        } else {
            $user = new User;
        }

        $client = ClientContext::get();

        $user->email = $input['email'];
        $user->name = $input['name'];
        $user->phone = $client->shortcodes()->first()->phoneFormatter()->format($input['phone']);
        $user->language = $input['language'];

        $client_id = $input['client_id'];

        $user->password = Hash::make(Str::random(64));

        $now = gmdate('Y-m-d H:i:s');
        $user->updated_at = $now;

        $user->save();

        $user->clients()->sync(
            [
                $client_id => [
                    'client_role_id' => $input['client_role_id'],
                    'timezone' => $input['timezone'],
                ],
            ],
            false
        );

        if (!empty($input['lists'])) {
            $lists = explode(',', $input['lists']);
            $user->lists()->sync($lists);
        }
        Cache::tags(['clients'])->forget("user.{$user->eid}.clients");

        if (isset($input['invite'])) {
            $email = app(Email::class);
            $email->subject = 'Profile created on ' . config('app.name');
            $mailerId = Uuid::uuid4()->toString();
            $email->mailer_id = $mailerId;
            $email->user_id = $user->id;
            $email->save();
            User::sendWelcomeEmail($user);
        }

        return redirect('/user');
    }

Model

public static function sendWelcomeEmail($user)
    {
        $token = app('auth.password.broker')->createToken($user);
        Mail::send('user.mail.profile-created', compact('token', 'user'), function ($m) use ($user) {
            $m->from(
                'no-reply@' . parse_url(config('app.url'), PHP_URL_HOST)
            );
            $m->to($user->email)->subject('Welcome to Tether');
            $headers = $m->getHeaders();
            $headers->addTextHeader('X-Mailer-ID', $user->mailerId);
        });
    }

Test

public function testStoreWithInvitationMail()
    {
        Mail::fake();

        $client = factory(Client::class)->create(['has_dedicated_shortcode' => true]);
        $shortcode = factory(Shortcode::class)->create();
        $client->shortcodes()->attach($shortcode);
        $person = factory(ClientParticipant::class)->states('email')->create([
                'client_id' => $client->id,
            ]);
        $user = $this->createAdministrator($client);
        Passport::actingAs($user);
        $clientRole = factory(ClientRole::class)->states(['mxco'])->create();

        $params = [
            'email' => $this->faker->email,
            'name' => $this->faker->name,
            'phone' => $this->faker->phoneNumber,
            'client_id' => $client->id,
            'client_role_id' => $clientRole->id,
            'language' => 'en',
            'timezone' => 'US/Eastern',
            'keyword' => null,
            'territory_number' => null,
            'invite' => true
        ];

        $response = $this
            ->actingAs($user)
            ->sessionClient($client)
            ->post('/user', $params);

        $this->assertEquals(302, $response->getStatusCode());

        Mail::assertSent(UserProfileCreated::class, 1);
    }

and the UserProfileCreated class

class UserProfileCreated extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * @var string
     */
    public $lang;

    /**
     * @var string
     */
    private $mailerId;

    public function __construct($lang, $mailerId)
    {
        $this->lang = $lang;
        $this->mailerId = $mailerId;
    }

    /**
     * Build the message.
     *
     * @return void
     */
    public function build()
    {
        $this->withSwiftMessage(function ($message) {
            $message->getHeaders()->addTextHeader('X-Mailer-ID', $this->mailerId);
        });

        $this->view('user.mail.profile-created')
            ->with(['$lang' => $this->lang])
            ->subject('Profile created on ' . config('app.name'))
            ->from(config('mail.from.address'), config('mail.from.name'));
    }
}
0 likes
8 replies
Sti3bas's avatar

@kalimeromk your sendWelcomeEmail method should be refactored to send UserProfileCreated mailable. Something like this:

public static function sendWelcomeEmail($user)
{
   Mail::to($user->email)->send(new UserProfileCreated($user->language, $user->mailerId));
}
KalimeroMK's avatar

code refactored to

public static function sendWelcomeEmail($user)
    {
        $token = app('auth.password.broker')->createToken($user);
        Mail::to($user->email)->send(new UserProfileCreated($user->language, $user->mailerId, $token));
    } 

but test still not working

Sti3bas's avatar

@kalimeromk make sure your code is successfully executed by adding this assertion $response->assertRedirect('/user');.

KalimeroMK's avatar

this is the error mail is not sending don't understand why

  1. Tests\User\Controllers\UserControllerTest::testStoreWithInvitationMail The expected [App\Mail\UserProfileCreated] mailable was sent 0 times instead of 1 times. Failed asserting that false is true.
Sti3bas's avatar
Sti3bas
Best Answer
Level 53

@kalimeromk try to add $this->withoutExceptionHandling(); at the top of your test to check if there are no errors.

KalimeroMK's avatar
  1. Tests\User\Controllers\UserControllerTest::testStoreWithInvitationMail Illuminate\Session\TokenMismatchException:
Sti3bas's avatar

@kalimeromk seems like you have some problems with the environment. Are you overriding APP_ENV env variable in your tests? It should be set to testing (in phpunit.xml file).

Please or to participate in this conversation.