You are here

class TfaRecoveryCodeTest in Two-factor Authentication (TFA) 8

@coversDefaultClass \Drupal\tfa\Plugin\TfaValidation\TfaRecoveryCode

@group tfa

Hierarchy

Expanded class hierarchy of TfaRecoveryCodeTest

File

tests/src/Unit/Plugin/TfaValidation/TfaRecoveryCodeTest.php, line 21

Namespace

Drupal\Tests\tfa\Unit\Plugin\TfaValidation
View source
class TfaRecoveryCodeTest extends UnitTestCase {

  /**
   * Mocked user data service.
   *
   * @var \Drupal\user\UserDataInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $userData;

  /**
   * Mocked encryption profile manager.
   *
   * @var \Drupal\encrypt\EncryptionProfileManagerInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $encryptionProfileManager;

  /**
   * The mocked encryption service.
   *
   * @var \Drupal\encrypt\EncryptServiceInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $encryptionService;

  /**
   * The mocked config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $configFactory;

  /**
   * The mocked TFA settings.
   *
   * @var \Drupal\Core\Config\ImmutableConfig|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $tfaSettings;

  /**
   * A mocked encryption profile.
   *
   * @var \Drupal\encrypt\EncryptionProfileInterface|\Prophecy\Prophecy\ObjectProphecy
   */
  protected $encryptionProfile;

  /**
   * Default configuration for the plugin.
   *
   * @var array
   */
  protected $configuration = [
    'uid' => 3,
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();

    // Stub out default mocked services. These can be overridden prior to
    // calling ::getFixture().
    $this->userData = $this
      ->prophesize(UserDataInterface::class);
    $this->encryptionProfileManager = $this
      ->prophesize(EncryptionProfileManagerInterface::class);
    $this->encryptionService = $this
      ->prophesize(EncryptServiceInterface::class);
    $this->tfaSettings = $this
      ->prophesize(ImmutableConfig::class);
    $this->configFactory = $this
      ->prophesize(ConfigFactoryInterface::class);
    $this->encryptionProfile = $this
      ->prophesize(EncryptionProfileInterface::class);
  }

  /**
   * Helper method to construct the test fixture.
   *
   * @return \Drupal\tfa\Plugin\TfaValidation\TfaRecoveryCode
   *   Recovery code.
   *
   * @throws \Exception
   */
  protected function getFixture() {

    // The plugin calls out to the global \Drupal object, so mock that here.
    $this->configFactory
      ->get('tfa.settings')
      ->willReturn($this->tfaSettings
      ->reveal());
    $container = new ContainerBuilder();
    $container
      ->set('config.factory', $this->configFactory
      ->reveal());
    $container
      ->set('string_translation', $this
      ->getStringTranslationStub());
    \Drupal::setContainer($container);
    return new TfaRecoveryCode($this->configuration, 'tfa_recovery_code', [], $this->userData
      ->reveal(), $this->encryptionProfileManager
      ->reveal(), $this->encryptionService
      ->reveal(), $container
      ->get('config.factory'));
  }

  /**
   * @covers ::ready
   * @covers ::getCodes
   * @covers ::validate
   */
  public function testReadyCodesValidate() {

    // No codes, means it isn't ready.
    $fixture = $this
      ->getFixture();
    $this
      ->assertFalse($fixture
      ->ready());

    // Fake some codes for user 3.
    $this->userData
      ->get('tfa', 3, 'tfa_recovery_code')
      ->willReturn([
      'foo',
      'bar',
    ]);
    $this->encryptionService
      ->decrypt('foo', $this->encryptionProfile
      ->reveal())
      ->willReturn('foo_decrypted');
    $this->encryptionService
      ->decrypt('bar', $this->encryptionProfile
      ->reveal())
      ->willReturn('bar_decrypted');
    $this->tfaSettings
      ->get('validation_plugin_settings.tfa_recovery_code.recovery_codes_amount')
      ->willReturn(10);
    $this->tfaSettings
      ->get('encryption')
      ->willReturn('foo');
    $this->tfaSettings
      ->get('default_validation_plugin')
      ->willReturn('bar');
    $this->encryptionProfileManager
      ->getEncryptionProfile('foo')
      ->willReturn($this->encryptionProfile
      ->reveal());
    $fixture = $this
      ->getFixture();
    $this
      ->assertTrue($fixture
      ->ready());
    $this
      ->assertEquals([
      'foo_decrypted',
      'bar_decrypted',
    ], $fixture
      ->getCodes());

    // Validate with a bad code. Prophecy doesn't support reference returns.
    $this->userData
      ->delete('tfa', 3, 'tfa_recovery_code')
      ->shouldBeCalled();
    $fixture = $this
      ->getFixture();
    $form_state = new FormState();
    $form_state
      ->setValues([
      'code' => 'bad_code',
    ]);
    $this
      ->assertFalse($fixture
      ->validateForm([], $form_state));
    $this
      ->assertCount(1, $fixture
      ->getErrorMessages());

    // Validate with a good code. This will remove the code and re-encrypt the
    // remaining code 'bar_decrypted'.
    $this->encryptionService
      ->encrypt('bar_decrypted', $this->encryptionProfile
      ->reveal())
      ->willReturn('bar');
    $this->userData
      ->set('tfa', 3, 'tfa_recovery_code', [
      1 => 'bar',
    ])
      ->shouldBeCalled();
    $fixture = $this
      ->getFixture();
    $form_state
      ->setValues([
      'code' => 'foo_decrypted',
    ]);
    $this
      ->assertTrue($fixture
      ->validateForm([], $form_state));
    $this
      ->assertEmpty($fixture
      ->getErrorMessages());
  }

}

Members

Namesort descending Modifiers Type Description Overrides
PhpunitCompatibilityTrait::getMock Deprecated public function Returns a mock object for the specified class using the available method.
PhpunitCompatibilityTrait::setExpectedException Deprecated public function Compatibility layer for PHPUnit 6 to support PHPUnit 4 code.
TfaRecoveryCodeTest::$configFactory protected property The mocked config factory.
TfaRecoveryCodeTest::$configuration protected property Default configuration for the plugin.
TfaRecoveryCodeTest::$encryptionProfile protected property A mocked encryption profile.
TfaRecoveryCodeTest::$encryptionProfileManager protected property Mocked encryption profile manager.
TfaRecoveryCodeTest::$encryptionService protected property The mocked encryption service.
TfaRecoveryCodeTest::$tfaSettings protected property The mocked TFA settings.
TfaRecoveryCodeTest::$userData protected property Mocked user data service.
TfaRecoveryCodeTest::getFixture protected function Helper method to construct the test fixture.
TfaRecoveryCodeTest::setUp protected function Overrides UnitTestCase::setUp
TfaRecoveryCodeTest::testReadyCodesValidate public function @covers ::ready @covers ::getCodes @covers ::validate
UnitTestCase::$randomGenerator protected property The random generator.
UnitTestCase::$root protected property The app root. 1
UnitTestCase::assertArrayEquals protected function Asserts if two arrays are equal by sorting them first.
UnitTestCase::getBlockMockWithMachineName Deprecated protected function Mocks a block with a block plugin. 1
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getConfigStorageStub public function Returns a stub config storage that returns the supplied configuration.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getRandomGenerator protected function Gets the random generator for the utility methods.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::randomMachineName public function Generates a unique random string containing letters and numbers.