diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php
index 915fc3a..e7c3d4a 100644
--- a/src/Controller/ProfileController.php
+++ b/src/Controller/ProfileController.php
@@ -36,7 +36,7 @@ class ProfileController extends ControllerBase implements ContainerInjectionInte
       'type' => $profile_type->id(),
     ]);
 
-    return $this->entityFormBuilder()->getForm($profile, 'add', ['uid' => $user->id(), 'created' => REQUEST_TIME]);
+    return $this->entityFormBuilder()->getForm($profile, 'create', ['uid' => $user->id(), 'created' => REQUEST_TIME]);
   }
 
   /**
diff --git a/src/ProfileAccessControlHandler.php b/src/ProfileAccessControlHandler.php
index 570003b..bbeef7c 100644
--- a/src/ProfileAccessControlHandler.php
+++ b/src/ProfileAccessControlHandler.php
@@ -19,15 +19,30 @@ class ProfileAccessControlHandler extends EntityAccessControlHandler {
   /**
    * {@inheritdoc}
    */
-  public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
-    $account = $this->prepareUser($account);
+  public function access(EntityInterface $entity, $operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
+    $this->prepareUser($account);
+    if ($account->hasPermission("bypass {$this->entityTypeId} access")) {
+      $result = AccessResult::allowed()->cachePerPermissions();
+      return $return_as_object ? $result : $result->isAllowed();
+    }
+
+    $result = parent::access($entity, $operation, $account, TRUE)->cachePerPermissions();
+    return $return_as_object ? $result : $result->isAllowed();
+  }
 
-    if ($account->hasPermission('bypass profile access')) {
+  /**
+   * {@inheritdoc}
+   */
+  public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
+    $this->prepareUser($account);
+    if ($account->hasPermission("bypass {$this->entityTypeId} access")) {
       $result = AccessResult::allowed()->cachePerPermissions();
       return $return_as_object ? $result : $result->isAllowed();
     }
 
+    /** @var \Drupal\Core\Access\AccessResult $result */
     $result = parent::createAccess($entity_bundle, $account, $context, TRUE)->cachePerPermissions();
+
     return $return_as_object ? $result : $result->isAllowed();
   }
 
@@ -38,75 +53,78 @@ class ProfileAccessControlHandler extends EntityAccessControlHandler {
    * otherwise $entity is of type 'profile'.
    */
   protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
+    /** @var \Drupal\profile\Entity\ProfileInterface $entity */
     $account = $this->prepareUser($account);
 
-    $user_page = \Drupal::request()->attributes->get('user');
+    if ($account->hasPermission("bypass {$this->entityTypeId} access")) {
+      $result = AccessResult::allowed()->cachePerPermissions();
+      return $result;
+    }
+
+    $own_permission = "$operation own {$entity->bundle()} {$entity->getEntityTypeId()}";
+    $any_permission = "$operation any {$entity->bundle()} {$entity->getEntityTypeId()}";
 
     // Some times, operation edit is called update.
     // Use edit in any case.
     if ($operation == 'update') {
       $operation = 'edit';
     }
+    elseif ($operation == 'create') {
+      $operation = 'add';
+    }
 
-    // Check that if profile type has require roles, the user the profile is
-    // being added to has any of the required roles.
-    if ($entity->getEntityTypeId() == 'profile') {
-      $profile_roles = ProfileType::load($entity->bundle())->getRoles();
-      // Retrieve all user roles including locked roles.
-      $user_roles = $entity->getOwner()->getRoles();
-      if (!empty(array_filter($profile_roles)) && !array_intersect($user_roles, $profile_roles)) {
-        return AccessResult::forbidden();
+    /** @var \Drupal\Core\Access\AccessResult $result */
+    $result = parent::checkAccess($entity, $operation, $account);
+
+    if ($result->isNeutral()) {
+      if (($account->id() == $entity->getOwnerId())) {
+        $result = AccessResult::allowedIfHasPermission($account, $own_permission);
+        if ($result->isNeutral()) {
+          // Check if user has "any" permission, still.
+          // Users may provide only "any" permission not just "own".
+          $result = AccessResult::allowedIfHasPermission($account, $any_permission);
+        }
       }
-    }
-    elseif ($entity->getEntityTypeId() == 'profile_type') {
-      $profile_roles = $entity->getRoles();
-      // Retrieve all user roles including locked roles.
-      $user_roles = User::load($user_page->id())->getRoles();
-      if (!empty(array_filter($profile_roles)) && !array_intersect($user_roles, $profile_roles)) {
-        return AccessResult::forbidden();
+      else {
+        $result = AccessResult::allowedIfHasPermission($account, $any_permission);
       }
     }
 
-    if ($account->hasPermission('bypass profile access')) {
-      return AccessResult::allowed()->cachePerPermissions();
-    }
-    elseif (
-      (
-        $operation == 'add'
-        && (
-          (
-            $user_page->id() == $account->id()
-            && $account->hasPermission($operation . ' own ' . $entity->id() . ' profile')
-          )
-          || $account->hasPermission($operation . ' any ' . $entity->id() . ' profile')
-        )
-      ) || (
-        $operation != 'add'
-        && (
-          (
-            $entity->getOwnerId() == $account->id()
-            && $account->hasPermission($operation . ' own ' . $entity->getType() . ' profile')
-          )
-          || $account->hasPermission($operation . ' any ' . $entity->getType() . ' profile')
-        )
-      )
-    ){
-      return AccessResult::allowed()->cachePerPermissions();
-    }
-    else {
-      // No opinion.
-      return AccessResult::neutral()->cachePerPermissions();
+    // If access is allowed, check role restriction.
+    if ($result->isAllowed()) {
+      $bundle = ProfileType::load($entity->bundle());
+      if (!empty(array_filter($bundle->getRoles()))) {
+        $result = AccessResult::allowedIf(!empty(array_intersect($account->getRoles(), $bundle->getRoles())));
+      }
     }
+
+    $result->cachePerUser()->addCacheableDependency($entity);
+
+    return $result;
   }
 
   /**
    * {@inheritdoc}
    */
   protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
-    return AccessResult::allowedIfHasPermissions($account, [
-      'add any ' . $entity_bundle . ' profile',
-      'add own ' . $entity_bundle . ' profile',
-    ], 'OR');
+    $result = parent::checkCreateAccess($account, $context, $entity_bundle);
+
+    if ($result->isNeutral()) {
+      $result = AccessResult::allowedIfHasPermissions($account, [
+        'add any ' . $entity_bundle . ' ' . $this->entityTypeId,
+        'add own ' . $entity_bundle . ' ' . $this->entityTypeId,
+      ], 'OR');
+    }
+
+    // If access is allowed, check role restriction.
+    if ($result->isAllowed()) {
+      $bundle = ProfileType::load($entity_bundle);
+      if (!empty(array_filter($bundle->getRoles()))) {
+        $result = AccessResult::allowedIf(!empty(array_intersect($account->getRoles(), $bundle->getRoles())));
+      }
+    }
+
+    return $result;
   }
 
 }
diff --git a/src/Tests/ProfileRoleAccessTest.php b/src/Tests/ProfileRoleAccessTest.php
deleted file mode 100644
index 15b1a79..0000000
--- a/src/Tests/ProfileRoleAccessTest.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-namespace Drupal\profile\Tests;
-
-use Drupal\Core\Session\AccountInterface;
-
-/**
- * Tests profile role access handling.
- *
- * @group profile
- */
-class ProfileRoleAccessTest extends ProfileTestBase {
-
-  /**
-   * Randomly generated profile type entity.
-   *
-   * Requires some, but not all roles.
-   *
-   * @var \Drupal\profile\Entity\ProfileType
-   */
-  protected $type2;
-
-  /**
-   * Randomly generated profile type entity.
-   *
-   * Requires all profile roles.
-   *
-   * @var \Drupal\profile\Entity\ProfileType
-   */
-  protected $type3;
-
-  /**
-   * Randomly generated user role entity.
-   *
-   * @var \Drupal\user\Entity\Role
-   */
-  protected $role1;
-
-  /**
-   * Randomly generated user role entity.
-   *
-   * @var \Drupal\user\Entity\Role
-   */
-  protected $role2;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->role1 = $this->drupalCreateRole([]);
-    $this->role2 = $this->drupalCreateRole([]);
-    $this->type2 = $this->createProfileType(NULL, NULL, FALSE, [$this->role2]);
-    $this->type3 = $this->createProfileType(NULL, NULL, FALSE, [$this->role1, $this->role2]);
-  }
-
-  /**
-   * Tests add profile form access for a profile type that does not require
-   * users to have a role.
-   */
-  public function testProfileWithNoRoles() {
-    // Create user with add own profile permissions.
-    $web_user1 = $this->drupalCreateUser(["add own {$this->type->id()} profile"]);
-    $this->drupalLogin($web_user1);
-
-    // Test user without role can access add profile form.
-    // Expected: User can access form.
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type->id()}");
-    $this->assertResponse(200);
-  }
-
-  public function testLockedRoles() {
-    $locked_role_type = $this->createProfileType(NULL, NULL, FALSE, [AccountInterface::AUTHENTICATED_ROLE]);
-
-    // Create user with add own profile permissions.
-    $web_user1 = $this->drupalCreateUser(["add own {$locked_role_type->id()} profile"]);
-    $this->drupalLogin($web_user1);
-
-    // Test user without role can access add profile form.
-    // Expected: User can access form.
-    $this->drupalGet("user/{$web_user1->id()}/{$locked_role_type->id()}");
-    $this->assertResponse(200);
-  }
-
-  /**
-   * Tests add profile form access for a profile type that requires users to
-   * have a single role.
-   */
-  public function testProfileWithSingleRole() {
-    // Create user with add own profile permissions.
-    $web_user1 = $this->drupalCreateUser(["add own {$this->type2->id()} profile"]);
-    $this->drupalLogin($web_user1);
-
-    // Test user without role can access add profile form.
-    // Expected: User cannot access form.
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type2->id()}");
-    $this->assertResponse(403);
-
-    // Test user with wrong role can access add profile form.
-    // Expected: User cannot access form.
-    $web_user1->addRole($this->role1);
-    $web_user1->save();
-
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type2->id()}");
-    $this->assertResponse(403);
-
-    // Test user with correct role can access add profile form.
-    // Expected: User can access form.
-    $web_user1->removeRole($this->role1);
-    $web_user1->addRole($this->role2);
-    $web_user1->save();
-
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type2->id()}");
-    $this->assertResponse(200);
-  }
-
-  /**
-   * Tests add profile form access for a profile type that requires users to
-   * have one of multiple roles.
-   */
-  public function testProfileWithAllRoles() {
-    // Create user with add own profile permissions.
-    $web_user1 = $this->drupalCreateUser(["add own {$this->type3->id()} profile"]);
-    $this->drupalLogin($web_user1);
-
-    // Test user without role can access add profile form.
-    // Expected: User cannot access form.
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type3->id()}");
-    $this->assertResponse(403);
-
-    // Test user with role 1 can access add profile form.
-    // Expected: User can access form.
-    $web_user1->addRole($this->role1);
-    $web_user1->save();
-
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type3->id()}");
-    $this->assertResponse(200);
-
-    // Test user with both roles can access add profile form.
-    // Expected: User can access form.
-    $web_user1->addRole($this->role2);
-    $web_user1->save();
-
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type3->id()}");
-    $this->assertResponse(200);
-
-    // Test user with role 2 can access add profile form.
-    // Expected: User can access form.
-    $web_user1->removeRole($this->role1);
-    $web_user1->save();
-
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type3->id()}");
-    $this->assertResponse(200);
-
-    // Test user without role can access add profile form.
-    // Expected: User cannot access form.
-    $web_user1->removeRole($this->role2);
-    $web_user1->save();
-
-    $this->drupalGet("user/{$web_user1->id()}/{$this->type3->id()}");
-    $this->assertResponse(403);
-  }
-
-}
diff --git a/tests/src/Kernel/ProfileAccessTest.php b/tests/src/Kernel/ProfileAccessTest.php
index c71476b..cd570a6 100644
--- a/tests/src/Kernel/ProfileAccessTest.php
+++ b/tests/src/Kernel/ProfileAccessTest.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\profile\Tests;
+namespace Drupal\Tests\profile\Kernel;
 
 use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
 use Drupal\profile\Entity\Profile;
@@ -158,18 +158,6 @@ class ProfileAccessTest extends EntityKernelTestBase {
     // Test user2 can view any profiles.
     $this->assertTrue($profile1->access('view', $web_user2));
     $this->assertTrue($profile2->access('view', $web_user2));
-
-    $user_view_builder = $this->container->get('entity_type.manager')->getViewBuilder('user');
-
-    $this->container->get('current_user')->setAccount($web_user1);
-    $user2_view = $user_view_builder->view($web_user2);
-    $this->render($user2_view);
-    $this->assertNoText($this->type->label());
-
-    $this->container->get('current_user')->setAccount($web_user2);
-    $user1_view = $user_view_builder->view($web_user1);
-    $this->render($user1_view);
-    $this->assertText($this->type->label());
   }
 
   /**
diff --git a/tests/src/Kernel/ProfileRoleAccessTest.php b/tests/src/Kernel/ProfileRoleAccessTest.php
new file mode 100644
index 0000000..ac043b3
--- /dev/null
+++ b/tests/src/Kernel/ProfileRoleAccessTest.php
@@ -0,0 +1,194 @@
+<?php
+
+namespace Drupal\Tests\profile\Kernel;
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
+use Drupal\profile\ProfileTestTrait;
+use Drupal\user\Entity\Role;
+
+/**
+ * Tests profile role access handling.
+ *
+ * @group profile
+ */
+class ProfileRoleAccessTest extends EntityKernelTestBase {
+
+  use ProfileTestTrait;
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['user', 'system', 'field', 'text', 'profile', 'views'];
+
+  /**
+   * Randomly generated profile type entity.
+   *
+   * No roles.
+   *
+   * @var \Drupal\profile\Entity\ProfileType
+   */
+  protected $type1;
+
+  /**
+   * Randomly generated profile type entity.
+   *
+   * Requires some, but not all roles.
+   *
+   * @var \Drupal\profile\Entity\ProfileType
+   */
+  protected $type2;
+
+  /**
+   * Randomly generated profile type entity.
+   *
+   * Requires all profile roles.
+   *
+   * @var \Drupal\profile\Entity\ProfileType
+   */
+  protected $type3;
+
+  /**
+   * Randomly generated user role entity.
+   *
+   * @var \Drupal\user\Entity\Role
+   */
+  protected $role1;
+
+  /**
+   * Randomly generated user role entity.
+   *
+   * @var \Drupal\user\Entity\Role
+   */
+  protected $role2;
+
+  /**
+   * @var \Drupal\profile\ProfileAccessControlHandler
+   */
+  protected $accessHandler;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->role1 = Role::create([
+      'id' => strtolower($this->randomMachineName(8)),
+      'label' => $this->randomMachineName(8),
+    ]);
+    $this->role1->save();
+    $this->role2 = Role::create([
+      'id' => strtolower($this->randomMachineName(8)),
+      'label' => $this->randomMachineName(8),
+    ]);
+    $this->role2->save();
+    $this->type1 = $this->createProfileType(NULL, NULL, FALSE, []);
+    $this->type2 = $this->createProfileType(NULL, NULL, FALSE, [$this->role2->id()]);
+    $this->type3 = $this->createProfileType(NULL, NULL, FALSE, [$this->role1->id(), $this->role2->id()]);
+
+    $this->accessHandler = $this->container->get('entity_type.manager')->getAccessControlHandler('profile');
+
+    // Do not allow uid == 1 to skew tests.
+    $this->createUser();
+  }
+
+  /**
+   * Tests add profile form access for a profile type that does not require
+   * users to have a role.
+   */
+  public function testProfileWithNoRoles() {
+    // Create user with add own profile permissions.
+    $web_user1 = $this->createUser([], ["add own {$this->type1->id()} profile"]);
+    $this->assertTrue($this->accessHandler->createAccess($this->type1->id(), $web_user1));
+  }
+
+  public function testLockedRoles() {
+    $locked_role_type = $this->createProfileType(NULL, NULL, FALSE, [AccountInterface::AUTHENTICATED_ROLE]);
+    // Create user with add own profile permissions.
+    $web_user1 = $this->createUser([], ["add own {$locked_role_type->id()} profile"]);
+    $this->assertTrue($this->accessHandler->createAccess($locked_role_type->id(), $web_user1));
+  }
+
+  /**
+   * Tests add profile form access for a profile type that requires users to
+   * have a single role.
+   *
+   * @group failing
+   */
+  public function testProfileWithSingleRole() {
+    // Create user with add own profile permissions.
+    $web_user1 = $this->createUser([], ["add own {$this->type2->id()} profile"]);
+
+    // Test user without role can access add profile form.
+    // Expected: User cannot access form.
+    $this->assertFalse($this->accessHandler->createAccess($this->type2->id(), $web_user1));
+    $this->accessHandler->resetCache();
+
+    // Test user with wrong role can access add profile form.
+    // Expected: User cannot access form.
+    $web_user1->addRole($this->role1->id());
+    $web_user1->save();
+
+    $this->assertFalse($this->accessHandler->createAccess($this->type2->id(), $web_user1));
+    $this->accessHandler->resetCache();
+
+    // Test user with correct role can access add profile form.
+    // Expected: User can access form.
+    $web_user1->removeRole($this->role1->id());
+    $web_user1->addRole($this->role2->id());
+    $web_user1->save();
+    $this->reloadEntity($web_user1);
+
+    $this->assertTrue($this->accessHandler->createAccess($this->type2->id(), $web_user1));
+
+  }
+
+  /**
+   * Tests add profile form access for a profile type that requires users to
+   * have one of multiple roles.
+   */
+  public function testProfileWithAllRoles() {
+    // Create user with add own profile permissions.
+    $web_user1 = $this->createUser([], ["add own {$this->type3->id()} profile"]);
+
+    // Test user without role can access add profile form.
+    // Expected: User cannot access form.
+    $this->assertFalse($this->accessHandler->createAccess($this->type3->id(), $web_user1));
+    $this->accessHandler->resetCache();
+
+    // Test user with role 1 can access add profile form.
+    // Expected: User can access form.
+    $web_user1->addRole($this->role1->id());
+    $web_user1->save();
+
+    $this->assertTrue($this->accessHandler->createAccess($this->type3->id(), $web_user1));
+    $this->accessHandler->resetCache();
+
+    // Test user with both roles can access add profile form.
+    // Expected: User can access form.
+    $web_user1->addRole($this->role2->id());
+    $web_user1->save();
+
+    $this->assertTrue($this->accessHandler->createAccess($this->type3->id(), $web_user1));
+    $this->accessHandler->resetCache();
+
+    // Test user with role 2 can access add profile form.
+    // Expected: User can access form.
+    $web_user1->removeRole($this->role1->id());
+    $web_user1->save();
+
+    $this->assertTrue($this->accessHandler->createAccess($this->type3->id(), $web_user1));
+    $this->accessHandler->resetCache();
+
+    // Test user without role can access add profile form.
+    // Expected: User cannot access form.
+    $web_user1->removeRole($this->role2->id());
+    $web_user1->save();
+
+    $this->assertFalse($this->accessHandler->createAccess($this->type3->id(), $web_user1));
+  }
+
+}
