You are here

public function OpenIDConnectTest::testConnectCurrentUser in OpenID Connect / OAuth client 2.x

Same name and namespace in other branches
  1. 8 tests/src/Unit/OpenIDConnectTest.php \Drupal\Tests\openid_connect\Unit\OpenIDConnectTest::testConnectCurrentUser()

Test the connectCurrentUser method.

@dataProvider dataProviderForConnectCurrentUser

Parameters

bool $authenticated: Whether the user is authenticated.

array $tokens: The tokens to return.

array $userData: The user data array.

array $userInfo: The user infor array.

bool $expectedResult: The expected result of the method.

File

tests/src/Unit/OpenIDConnectTest.php, line 929

Class

OpenIDConnectTest
Provides tests for the OpenID Connect module.

Namespace

Drupal\Tests\openid_connect\Unit

Code

public function testConnectCurrentUser(bool $authenticated, array $tokens, array $userData, array $userInfo, bool $expectedResult) : void {
  $pluginId = $this
    ->randomMachineName();
  $clientId = $this
    ->randomMachineName();
  $client = $this
    ->createMock(OpenIDConnectClientInterface::class);
  $clientEntity = $this
    ->createMock(OpenIDConnectClientEntityInterface::class);
  $this->currentUser
    ->expects($this
    ->once())
    ->method('isAuthenticated')
    ->willReturn($authenticated);
  if (!$authenticated) {
    $this
      ->expectException('RuntimeException');
  }
  else {
    $client
      ->expects($this
      ->once())
      ->method('usesUserInfo')
      ->willReturn(TRUE);
    $client
      ->expects($this
      ->once())
      ->method('retrieveUserInfo')
      ->with($tokens['access_token'])
      ->willReturn($userInfo);
    $clientEntity
      ->expects($this
      ->any())
      ->method('getPlugin')
      ->willReturn($client);
    $clientEntity
      ->expects($this
      ->any())
      ->method('getPluginId')
      ->willReturn($pluginId);
    $clientEntity
      ->expects($this
      ->any())
      ->method('id')
      ->willReturn($clientId);
    if (empty($userInfo) && empty($userData)) {
      $this->oidcLogger
        ->expects($this
        ->once())
        ->method('error')
        ->with('No user information provided by @provider', [
        '@provider' => $clientId,
      ]);
    }
    if (isset($userInfo['email']) && empty($userInfo['email'])) {
      $this->oidcLogger
        ->expects($this
        ->once())
        ->method('error')
        ->with('No e-mail address provided by @provider', [
        '@provider' => $clientId,
      ]);
    }
    if (isset($userData['sub']) && $userData['sub'] === 'invalid') {
      $account = $this
        ->createMock(User::class);
      $this->externalAuth
        ->expects($this
        ->once())
        ->method('load')
        ->willReturn($account);
      $this->externalAuth
        ->expects($this
        ->never())
        ->method('linkExistingAccount');
      $this->moduleHandler
        ->expects($this
        ->once())
        ->method('invokeAll')
        ->with('openid_connect_pre_authorize')
        ->willReturn([
        FALSE,
      ]);
    }
    if (isset($userData['sub']) && $userData['sub'] === 'different_account') {
      $accountId = 8675309;
      $userId = 3456;
      $this->currentUser
        ->expects($this
        ->once())
        ->method('id')
        ->willReturn($userId);
      $account = $this
        ->createMock(User::class);
      $account
        ->expects($this
        ->once())
        ->method('id')
        ->willReturn($accountId);
      $this->externalAuth
        ->expects($this
        ->once())
        ->method('load')
        ->willReturn($account);
      $this->externalAuth
        ->expects($this
        ->never())
        ->method('linkExistingAccount');
      $this->moduleHandler
        ->expects($this
        ->once())
        ->method('invokeAll')
        ->with('openid_connect_pre_authorize')
        ->willReturn([
        $account,
      ]);
      $this->messenger
        ->expects($this
        ->once())
        ->method('addError');
    }
    if (isset($userData['sub']) && $expectedResult) {
      $accountId = 8675309;
      $this->currentUser
        ->expects($this
        ->once())
        ->method('id')
        ->willReturn($accountId);
      $account = $this
        ->createMock(User::class);
      $this->userStorage
        ->expects($this
        ->once())
        ->method('load')
        ->with($accountId)
        ->willReturn($account);
      $this->externalAuth
        ->expects($this
        ->once())
        ->method('load')
        ->willReturn(FALSE);
      $this->externalAuth
        ->expects($this
        ->once())
        ->method('linkExistingAccount')
        ->with($userData['sub'], 'openid_connect.' . $clientId, $account);
      $mappings = [
        'mail' => 'mail',
        'name' => 'name',
      ];
      if ($userData['always_save'] === TRUE) {
        $fieldDefinitions = [];
        foreach ($userInfo as $key => $value) {
          $mappings[$key] = $key;
          switch ($key) {
            case 'email':
              $returnType = 'string';
              break;
            case 'field_string':
              $account
                ->expects($this
                ->once())
                ->method('set');
              $returnType = 'string';
              break;
            case 'field_string_long':
              $account
                ->expects($this
                ->once())
                ->method('set');
              $returnType = 'string_long';
              break;
            case 'field_datetime':
              $account
                ->expects($this
                ->once())
                ->method('set');
              $returnType = 'datetime';
              break;
            case 'field_image':
              $this->fileSystem
                ->expects($this
                ->once())
                ->method('basename')
                ->with($value)
                ->willReturn('test-file');
              $account
                ->expects($this
                ->once())
                ->method('set');
              $returnType = 'image';
              $mockFile = $this
                ->createMock(File::class);
              $mockFile
                ->expects($this
                ->once())
                ->method('delete');
              $fieldItem = $this
                ->createMock(FieldItemListInterface::class);
              $fieldItem
                ->expects($this
                ->once())
                ->method('__get')
                ->with('entity')
                ->willReturn($mockFile);
              $account
                ->expects($this
                ->once())
                ->method('__get')
                ->willReturn($fieldItem);
              break;
            case 'field_invalid':
              $account
                ->expects($this
                ->never())
                ->method('set');
              $this->oidcLogger
                ->expects($this
                ->once())
                ->method('error')
                ->with('Could not save user info, property type not implemented: %property_type', [
                '%property_type' => $key,
              ]);
              $returnType = $key;
              break;
            case 'field_image_exception':
              $exception = $this
                ->createMock(InvalidArgumentException::class);
              $account
                ->expects($this
                ->once())
                ->method('set')
                ->willThrowException($exception);
              $returnType = 'string';
              break;
            default:
              $returnType = $key;
              break;
          }
          $mock = $this
            ->createMock(FieldDefinitionInterface::class);
          $mock
            ->expects($this
            ->any())
            ->method('getType')
            ->willReturn($returnType);
          $fieldDefinitions[$key] = $mock;
        }
        $this->entityFieldManager
          ->expects($this
          ->once())
          ->method('getFieldDefinitions')
          ->with('user', 'user')
          ->willReturn($fieldDefinitions);
        $this->moduleHandler
          ->expects($this
          ->exactly(3))
          ->method('invokeAll')
          ->withConsecutive([
          'openid_connect_pre_authorize',
        ], [
          'openid_connect_userinfo_save',
        ], [
          'openid_connect_post_authorize',
        ])
          ->willReturnOnConsecutiveCalls([], TRUE, TRUE);
      }
      else {
        $this->moduleHandler
          ->expects($this
          ->exactly(2))
          ->method('invokeAll')
          ->withConsecutive([
          'openid_connect_pre_authorize',
        ], [
          'openid_connect_post_authorize',
        ])
          ->willReturnOnConsecutiveCalls([], TRUE);
      }
      $immutableConfig = $this
        ->createMock(ImmutableConfig::class);
      $immutableConfig
        ->expects($this
        ->atLeastOnce())
        ->method('get')
        ->withConsecutive([
        'always_save_userinfo',
      ], [
        'userinfo_mappings',
      ])
        ->willReturnOnConsecutiveCalls($userData['always_save'], $mappings);
      $this->configFactory
        ->expects($this
        ->atLeastOnce())
        ->method('get')
        ->with('openid_connect.settings')
        ->willReturn($immutableConfig);
    }
  }
  $result = $this->openIdConnect
    ->connectCurrentUser($clientEntity, $tokens);
  $this
    ->assertEquals($expectedResult, $result);
}