diff --git a/src/Entity/Bug.php b/src/Entity/Bug.php index cc6972fb..564020e7 100644 --- a/src/Entity/Bug.php +++ b/src/Entity/Bug.php @@ -6,7 +6,9 @@ use DateTimeInterface; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; +use Tienvx\Bundle\MbtBundle\Entity\Bug\Video; use Tienvx\Bundle\MbtBundle\Model\Bug as BugModel; +use Tienvx\Bundle\MbtBundle\Model\Bug\VideoInterface; use Tienvx\Bundle\MbtBundle\Model\ProgressInterface; use Tienvx\Bundle\MbtBundle\Model\TaskInterface; use Tienvx\Bundle\MbtBundle\Repository\BugRepository; @@ -61,9 +63,9 @@ class Bug extends BugModel protected bool $closed = false; /** - * @ORM\Column(type="boolean") + * @ORM\Embedded(class="\Tienvx\Bundle\MbtBundle\Entity\Bug\Video") */ - protected bool $recording = false; + protected VideoInterface $video; /** * @ORM\Column(name="created_at", type="datetime") @@ -79,6 +81,7 @@ public function __construct() { parent::__construct(); $this->progress = new Progress(); + $this->video = new Video(); } /** diff --git a/src/Entity/Bug/Video.php b/src/Entity/Bug/Video.php new file mode 100644 index 00000000..cfae14bd --- /dev/null +++ b/src/Entity/Bug/Video.php @@ -0,0 +1,23 @@ +progress = new Progress(); + $this->video = new Video(); } public function setId(int $id) @@ -101,14 +104,14 @@ public function setClosed(bool $closed): void $this->closed = $closed; } - public function isRecording(): bool + public function getVideo(): VideoInterface { - return $this->recording; + return $this->video; } - public function setRecording(bool $recording): void + public function setVideo(VideoInterface $video): void { - $this->recording = $recording; + $this->video = $video; } public function setCreatedAt(DateTimeInterface $createdAt): void diff --git a/src/Model/Bug/Video.php b/src/Model/Bug/Video.php new file mode 100644 index 00000000..46a0c9fd --- /dev/null +++ b/src/Model/Bug/Video.php @@ -0,0 +1,29 @@ +recording; + } + + public function setRecording(bool $recording): void + { + $this->recording = $recording; + } + + public function getErrorMessage(): ?string + { + return $this->errorMessage; + } + + public function setErrorMessage(?string $errorMessage = null): void + { + $this->errorMessage = $errorMessage; + } +} diff --git a/src/Model/Bug/VideoInterface.php b/src/Model/Bug/VideoInterface.php new file mode 100644 index 00000000..48c1a75d --- /dev/null +++ b/src/Model/Bug/VideoInterface.php @@ -0,0 +1,14 @@ +setRecording(true); + $bug->getVideo()->setRecording(true); $this->getEntityManager()->flush(); } public function stopRecording(BugInterface $bug): void { - $bug->setRecording(false); + $bug->getVideo()->setRecording(false); // Recording bug may take long time. Reconnect to flush changes. $this->getEntityManager()->getConnection()->connect(); $this->getEntityManager()->flush(); } + + public function updateVideoErrorMessage(BugInterface $bug, string $videoErrorMessage): void + { + $bug->getVideo()->setErrorMessage($videoErrorMessage); + $this->getEntityManager()->flush(); + } } diff --git a/src/Repository/BugRepositoryInterface.php b/src/Repository/BugRepositoryInterface.php index f834c7c8..5301afda 100644 --- a/src/Repository/BugRepositoryInterface.php +++ b/src/Repository/BugRepositoryInterface.php @@ -16,4 +16,6 @@ public function increaseTotal(BugInterface $bug, int $total): void; public function startRecording(BugInterface $bug): void; public function stopRecording(BugInterface $bug): void; + + public function updateVideoErrorMessage(BugInterface $bug, string $videoErrorMessage): void; } diff --git a/src/Service/Bug/BugHelper.php b/src/Service/Bug/BugHelper.php index b8aa9e28..518cca27 100644 --- a/src/Service/Bug/BugHelper.php +++ b/src/Service/Bug/BugHelper.php @@ -4,6 +4,7 @@ use Symfony\Component\Messenger\Exception\RecoverableMessageHandlingException; use Symfony\Component\Messenger\MessageBusInterface; +use Throwable; use Tienvx\Bundle\MbtBundle\Entity\Bug; use Tienvx\Bundle\MbtBundle\Exception\ExceptionInterface; use Tienvx\Bundle\MbtBundle\Exception\UnexpectedValueException; @@ -87,14 +88,16 @@ public function recordVideo(int $bugId): void { $bug = $this->getBug($bugId, 'record video for bug'); - if ($bug->isRecording()) { + if ($bug->getVideo()->isRecording()) { throw new RecoverableMessageHandlingException( sprintf('Can not record video for bug %d: bug is recording. Will retry later', $bug->getId()) ); } $this->bugRepository->startRecording($bug); - $this->stepsRunner->run($bug->getSteps(), $bug, true); + $this->stepsRunner->run($bug->getSteps(), $bug, true, function (Throwable $throwable) use ($bug): void { + $this->bugRepository->updateVideoErrorMessage($bug, $throwable->getMessage()); + }); $this->bugRepository->stopRecording($bug); } diff --git a/tests/Entity/Bug/VideoTest.php b/tests/Entity/Bug/VideoTest.php new file mode 100644 index 00000000..5847beb8 --- /dev/null +++ b/tests/Entity/Bug/VideoTest.php @@ -0,0 +1,20 @@ +video = $this->createVideo(); + } + + public function testRecording(): void + { + $this->assertFalse($this->video->isRecording()); + $this->video->setRecording(true); + $this->assertTrue($this->video->isRecording()); + } + + public function testErrorMessage(): void + { + $this->assertNull($this->video->getErrorMessage()); + $this->video->setErrorMessage('Something wrong'); + $this->assertSame('Something wrong', $this->video->getErrorMessage()); + } + + protected function createVideo(): VideoInterface + { + return new Video(); + } +} diff --git a/tests/Model/BugTest.php b/tests/Model/BugTest.php index 8b712a2c..21b03632 100644 --- a/tests/Model/BugTest.php +++ b/tests/Model/BugTest.php @@ -4,6 +4,7 @@ use PHPUnit\Framework\TestCase; use SingleColorPetrinet\Model\Color; +use Tienvx\Bundle\MbtBundle\Entity\Bug\Video; use Tienvx\Bundle\MbtBundle\Entity\Progress; use Tienvx\Bundle\MbtBundle\Entity\Task; use Tienvx\Bundle\MbtBundle\Model\Bug; @@ -28,6 +29,7 @@ class BugTest extends TestCase protected array $steps; protected TaskInterface $task; protected ProgressInterface $progress; + protected Bug\VideoInterface $video; protected function setUp(): void { @@ -37,6 +39,7 @@ protected function setUp(): void ]; $this->task = new Task(); $this->progress = new Progress(); + $this->video = new Video(); $this->bug = $this->createBug(); $this->bug->setId(123); $this->bug->setTitle('bug title'); @@ -44,8 +47,8 @@ protected function setUp(): void $this->bug->setTask($this->task); $this->bug->setMessage('bug message'); $this->bug->setProgress($this->progress); + $this->bug->setVideo($this->video); $this->bug->setClosed(true); - $this->bug->setRecording(true); } public function testProperties(): void @@ -57,7 +60,7 @@ public function testProperties(): void $this->assertSame('bug message', $this->bug->getMessage()); $this->assertSame($this->progress, $this->bug->getProgress()); $this->assertSame(true, $this->bug->isClosed()); - $this->assertSame(true, $this->bug->isRecording()); + $this->assertSame($this->video, $this->bug->getVideo()); } protected function createBug(): BugInterface diff --git a/tests/Repository/BugRepositoryTest.php b/tests/Repository/BugRepositoryTest.php index 21d97f30..f502ce96 100644 --- a/tests/Repository/BugRepositoryTest.php +++ b/tests/Repository/BugRepositoryTest.php @@ -21,6 +21,7 @@ * @uses \Tienvx\Bundle\MbtBundle\Entity\Bug * @uses \Tienvx\Bundle\MbtBundle\Model\Bug * @uses \Tienvx\Bundle\MbtBundle\Model\Progress + * @uses \Tienvx\Bundle\MbtBundle\Model\Bug\Video */ class BugRepositoryTest extends TestCase { @@ -154,20 +155,28 @@ public function testIncreaseTotal(): void public function testStartRecordingBug(): void { - $this->bug->setRecording(false); + $this->bug->getVideo()->setRecording(false); $this->manager->expects($this->once())->method('flush'); $this->bugRepository->startRecording($this->bug); - $this->assertTrue($this->bug->isRecording()); + $this->assertTrue($this->bug->getVideo()->isRecording()); } public function testStopRecordingBug(): void { $connection = $this->createMock(Connection::class); $connection->expects($this->once())->method('connect'); - $this->bug->setRecording(true); + $this->bug->getVideo()->setRecording(true); $this->manager->expects($this->once())->method('flush'); $this->manager->expects($this->once())->method('getConnection')->willReturn($connection); $this->bugRepository->stopRecording($this->bug); - $this->assertFalse($this->bug->isRecording()); + $this->assertFalse($this->bug->getVideo()->isRecording()); + } + + public function testUpdateVideoErrorMessage(): void + { + $this->assertNull($this->bug->getVideo()->getErrorMessage()); + $this->manager->expects($this->once())->method('flush'); + $this->bugRepository->updateVideoErrorMessage($this->bug, 'Something wrong'); + $this->assertSame('Something wrong', $this->bug->getVideo()->getErrorMessage()); } } diff --git a/tests/Service/Bug/BugHelperTest.php b/tests/Service/Bug/BugHelperTest.php index 9af48b9e..ab6ee3b7 100644 --- a/tests/Service/Bug/BugHelperTest.php +++ b/tests/Service/Bug/BugHelperTest.php @@ -2,10 +2,12 @@ namespace Tienvx\Bundle\MbtBundle\Tests\Service\Bug; +use Exception; use PHPUnit\Framework\TestCase; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\RecoverableMessageHandlingException; use Symfony\Component\Messenger\MessageBusInterface; +use Throwable; use Tienvx\Bundle\MbtBundle\Entity\Bug; use Tienvx\Bundle\MbtBundle\Entity\Progress; use Tienvx\Bundle\MbtBundle\Exception\UnexpectedValueException; @@ -32,6 +34,7 @@ * @uses \Tienvx\Bundle\MbtBundle\Model\Bug * @uses \Tienvx\Bundle\MbtBundle\Model\Task * @uses \Tienvx\Bundle\MbtBundle\Model\Progress + * @uses \Tienvx\Bundle\MbtBundle\Model\Bug\Video * @uses \Tienvx\Bundle\MbtBundle\Message\ReportBugMessage * @uses \Tienvx\Bundle\MbtBundle\Message\RecordVideoMessage */ @@ -237,20 +240,50 @@ public function testRunTaskAlreadyRunning(): void { $this->expectException(RecoverableMessageHandlingException::class); $this->expectExceptionMessage('Can not record video for bug 123: bug is recording. Will retry later'); - $this->bug->setRecording(true); + $this->bug->getVideo()->setRecording(true); $this->bugRepository->expects($this->once())->method('find')->with(123)->willReturn($this->bug); $this->helper->recordVideo(123); } - public function testRecordVideo(): void + /** + * @dataProvider exceptionProvider + */ + public function testRecordVideo(?Throwable $exception, bool $updateVideoErrorMessage): void { $this->stepsRunner ->expects($this->once()) ->method('run') - ->with($this->bug->getSteps(), $this->bug, true); + ->with( + $this->bug->getSteps(), + $this->bug, + true, + $this->callback(function (callable $exceptionCallback) use ($exception) { + if ($exception) { + $exceptionCallback($exception); + } + + return true; + }) + ); + if ($exception && $updateVideoErrorMessage) { + $this->bugRepository + ->expects($this->once()) + ->method('updateVideoErrorMessage') + ->with($this->bug, $exception->getMessage()); + } else { + $this->bugRepository->expects($this->never())->method('updateVideoErrorMessage'); + } $this->bugRepository->expects($this->once())->method('find')->with(123)->willReturn($this->bug); $this->bugRepository->expects($this->once())->method('startRecording')->with($this->bug); $this->bugRepository->expects($this->once())->method('stopRecording')->with($this->bug); $this->helper->recordVideo(123); } + + public function exceptionProvider(): array + { + return [ + [null, false], + [new Exception('Something wrong'), true], + ]; + } }