Pragmatic Testing in AdonisJS with Japa #6.1

Testing Auth Protected Routes

In This Lesson

We'll learn how to test auth-protected routes via the auth middleware and non-auth-protected routes via the guest middleware. We'll ensure our user is redirected appropriately and shown a flash message where applicable

Created by
@tomgobich
Published

Notes Used to Craft this Lesson

What we want to do now is write a test for the sad path where our unauthenticated user is blocked from accessing the page because our authentication middleware is protecting the route.

test("not allow an unauthenticated user to view the page", async ({
  assert,
  client,
  route,
}) => {
  const response = await client.get(route("settings.account"));

  response.assertOk();
  response.assertTextIncludes("Unauthorized access");
});
Copied!

Now, the auth middleware should also redirect unauthorized requests to the login page. So we can verify that it did or didn't happen, respectively, between this test and the test we wrote in our last lesson.

test.group("Settings account", (group) => {
  group.each.setup(() => testUtils.db().withGlobalTransaction());

  test("allow an authenticated user to view the page", async ({
    assert,
    client,
    route,
  }) => {
    const user = await UserFactory.create();
    const response = await client.get(route("settings.account")).loginAs(user);

    response.assertOk();
    response.assertTextIncludes("Account Settings");
    assert.lengthOf(response.redirects(), 0);
  });

  test("not allow an unauthenticated user to view the page", async ({
    assert,
    client,
    route,
  }) => {
    const response = await client.get(route("settings.account"));

    response.assertOk();
    response.assertTextIncludes("Unauthorized access");
    response.assertRedirectsTo(route("auth.login.show"));
  });
});
Copied!

Great, so we've confirmed our auth middleware is appropriately protecting our account settings page. What about the inverse side of this picture, where an authenticated user is blocked from accessing something? For example, an already logged-in user should be blocked from logging in again via our guest middleware.

test("redirect an already authenticated user attempting to login", async ({
  client,
  route,
}) => {
  const user = await UserFactory.create();
  const response = await client
    .post(route("auth.login.store"))
    .withCsrfToken()
    .header("Referer", route("auth.login.show"))
    .loginAs(user)
    .form({
      email: user.email,
      password: "something",
    })
    .redirects(0);

  response.assertHeader("Location", "/");
  response.assertFlashMessage("warning", "You are already logged in");
});
Copied!

While we're here, let's write the happy path for this as well.

test("allow an existing user to log in", async ({ client, route }) => {
  const user = await UserFactory.merge({
    password: "MyC00lPassword!01",
  }).create();
  const response = await client
    .post(route("auth.login.store"))
    .withCsrfToken()
    .header("Referer", route("auth.login.show"))
    .form({
      email: user.email.toLowerCase(),
      password: "MyC00lPassword!01",
    })
    .redirects(0);

  response.assertHeader("Location", route("jumpstart"));
  response.assertFlashMessage("success", `Welcome back, ${user.fullName}`);
});
Copied!

Great, although not specific to this lesson's subject, we also need to confirm that a user can't log in with invalid credentials, so let's test that quickly as well.

test("not log in a user who sent an invalid password", async ({
  client,
  route,
}) => {
  const user = await UserFactory.create();
  const response = await client
    .post(route("auth.login.store"))
    .withCsrfToken()
    .header("Referer", route("auth.login.show"))
    .form({
      email: user.email.toLowerCase(),
      password: "Invalid!Password",
    })
    .redirects(0);

  response.assertHeader("Location", route("auth.login.show"));
  response.assertFlashMessage(
    "errorsBag.E_INVALID_CREDENTIALS",
    "Invalid user credentials"
  );
});
Copied!

Also, note that if you ever need to see what you are getting for your flash messages, you can easily do this via:

console.log(response.flashMessages());
Copied!

Join the Discussion 0 comments

Create a free account to join in on the discussion
robot comment bubble

Be the first to comment!