|
17 | 17 | use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeGeneratorServiceInterface; |
18 | 18 | use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeValidatorServiceInterface; |
19 | 19 | use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\DTO\OtpChallengeStateInterface; |
| 20 | +use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpSendPolicyServiceInterface; |
| 21 | +use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Exception\ResendCooldownException; |
20 | 22 | use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\Exception\InvalidCodeException; |
21 | 23 | use PHPUnit\Framework\Attributes\Test; |
22 | 24 | use PHPUnit\Framework\TestCase; |
@@ -177,17 +179,69 @@ public function triggerChallengeGeneratesCodeCreatesStateAndNotifies(): void |
177 | 179 | $sut->triggerChallenge(userId: $userId); |
178 | 180 | } |
179 | 181 |
|
| 182 | + #[Test] |
| 183 | + public function resendThrowsCooldownExceptionWhenSendNotAllowed(): void |
| 184 | + { |
| 185 | + $sendPolicyStub = $this->createStub(OtpSendPolicyServiceInterface::class); |
| 186 | + $sendPolicyStub->method('canSend') |
| 187 | + ->with($userId = uniqid()) |
| 188 | + ->willReturn(false); |
| 189 | + |
| 190 | + $sut = $this->getSut(sendPolicy: $sendPolicyStub); |
| 191 | + |
| 192 | + $this->expectException(ResendCooldownException::class); |
| 193 | + |
| 194 | + $sut->resend(userId: $userId); |
| 195 | + } |
| 196 | + |
| 197 | + #[Test] |
| 198 | + public function resendRefreshesStateAndNotifiesWhenAllowed(): void |
| 199 | + { |
| 200 | + $sendPolicyStub = $this->createStub(OtpSendPolicyServiceInterface::class); |
| 201 | + $sendPolicyStub->method('canSend') |
| 202 | + ->with($userId = uniqid()) |
| 203 | + ->willReturn(true); |
| 204 | + |
| 205 | + $codeGeneratorStub = $this->createStub(OtpCodeGeneratorServiceInterface::class); |
| 206 | + $codeGeneratorStub->method('generateCode') |
| 207 | + ->willReturn($code = uniqid()); |
| 208 | + |
| 209 | + $stateServiceSpy = $this->createMock(OtpChallengeStateServiceInterface::class); |
| 210 | + $stateServiceSpy->expects($this->once()) |
| 211 | + ->method('refreshChallengeState') |
| 212 | + ->with($userId, $code); |
| 213 | + |
| 214 | + $notifierSpy = $this->createMock(OtpNotifierInterface::class); |
| 215 | + $notifierSpy->expects($this->once()) |
| 216 | + ->method('notify') |
| 217 | + ->with($userId, $code); |
| 218 | + |
| 219 | + $notifierFactoryStub = $this->createStub(OtpNotifierFactoryInterface::class); |
| 220 | + $notifierFactoryStub->method('create')->willReturn($notifierSpy); |
| 221 | + |
| 222 | + $sut = $this->getSut( |
| 223 | + stateService: $stateServiceSpy, |
| 224 | + codeGenerator: $codeGeneratorStub, |
| 225 | + notifierFactory: $notifierFactoryStub, |
| 226 | + sendPolicy: $sendPolicyStub, |
| 227 | + ); |
| 228 | + |
| 229 | + $sut->resend(userId: $userId); |
| 230 | + } |
| 231 | + |
180 | 232 | private function getSut( |
181 | 233 | OtpChallengeStateServiceInterface $stateService = null, |
182 | 234 | OtpCodeValidatorServiceInterface $codeValidator = null, |
183 | 235 | OtpCodeGeneratorServiceInterface $codeGenerator = null, |
184 | 236 | OtpNotifierFactoryInterface $notifierFactory = null, |
| 237 | + OtpSendPolicyServiceInterface $sendPolicy = null, |
185 | 238 | ): OtpFacade { |
186 | 239 | return new OtpFacade( |
187 | 240 | stateService: $stateService ?? $this->createStub(OtpChallengeStateServiceInterface::class), |
188 | 241 | codeValidator: $codeValidator ?? $this->createStub(OtpCodeValidatorServiceInterface::class), |
189 | 242 | codeGenerator: $codeGenerator ?? $this->createStub(OtpCodeGeneratorServiceInterface::class), |
190 | 243 | notifierFactory: $notifierFactory ?? $this->createStub(OtpNotifierFactoryInterface::class), |
| 244 | + sendPolicy: $sendPolicy ?? $this->createStub(OtpSendPolicyServiceInterface::class), |
191 | 245 | ); |
192 | 246 | } |
193 | 247 | } |
0 commit comments