test(TaskProcessing): Add test for user-facing error messages

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
pull/55713/head
Marcel Klehr 2025-10-13 13:16:19 +07:00
parent 7373f11af6
commit e12c0ed7a3
1 changed files with 94 additions and 0 deletions

@ -260,6 +260,69 @@ class FailingSyncProvider implements IProvider, ISynchronousProvider {
}
}
class FailingSyncProviderWithUserFacingError implements IProvider, ISynchronousProvider {
public const ERROR_MESSAGE = 'Failure';
public const USER_FACING_ERROR_MESSAGE = 'User-facing Failure';
public function getId(): string {
return 'test:sync:fail:user-facing';
}
public function getName(): string {
return self::class;
}
public function getTaskTypeId(): string {
return TextToText::ID;
}
public function getExpectedRuntime(): int {
return 10;
}
public function getOptionalInputShape(): array {
return [
'optionalKey' => new ShapeDescriptor('optional Key', 'AN optional key', EShapeType::Text),
];
}
public function getOptionalOutputShape(): array {
return [
'optionalKey' => new ShapeDescriptor('optional Key', 'AN optional key', EShapeType::Text),
];
}
public function process(?string $userId, array $input, callable $reportProgress): array {
$e = new ProcessingException(self::ERROR_MESSAGE);
$e->setUserFacingMessage(self::USER_FACING_ERROR_MESSAGE);
throw $e;
}
public function getInputShapeEnumValues(): array {
return [];
}
public function getInputShapeDefaults(): array {
return [];
}
public function getOptionalInputShapeEnumValues(): array {
return [];
}
public function getOptionalInputShapeDefaults(): array {
return [];
}
public function getOutputShapeEnumValues(): array {
return [];
}
public function getOptionalOutputShapeEnumValues(): array {
return [];
}
}
class BrokenSyncProvider implements IProvider, ISynchronousProvider {
public function getId(): string {
return 'test:sync:broken-output';
@ -547,6 +610,7 @@ class TaskProcessingTest extends \Test\TestCase {
$this->providers = [
SuccessfulSyncProvider::class => new SuccessfulSyncProvider(),
FailingSyncProvider::class => new FailingSyncProvider(),
FailingSyncProviderWithUserFacingError::class => new FailingSyncProviderWithUserFacingError(),
BrokenSyncProvider::class => new BrokenSyncProvider(),
AsyncProvider::class => new AsyncProvider(),
AudioToImage::class => new AudioToImage(),
@ -726,6 +790,36 @@ class TaskProcessingTest extends \Test\TestCase {
self::assertEquals(FailingSyncProvider::ERROR_MESSAGE, $task->getErrorMessage());
}
public function testProviderShouldBeRegisteredAndFailWithUserFacingMessage(): void {
$this->registrationContext->expects($this->any())->method('getTaskProcessingProviders')->willReturn([
new ServiceRegistration('test', FailingSyncProviderWithUserFacingError::class)
]);
self::assertCount(1, $this->manager->getAvailableTaskTypes());
self::assertCount(1, $this->manager->getAvailableTaskTypeIds());
self::assertTrue($this->manager->hasProviders());
$task = new Task(TextToText::ID, ['input' => 'Hello'], 'test', null);
self::assertNull($task->getId());
self::assertEquals(Task::STATUS_UNKNOWN, $task->getStatus());
$this->manager->scheduleTask($task);
self::assertNotNull($task->getId());
self::assertEquals(Task::STATUS_SCHEDULED, $task->getStatus());
$this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new IsInstanceOf(TaskFailedEvent::class));
$backgroundJob = new SynchronousBackgroundJob(
Server::get(ITimeFactory::class),
$this->manager,
$this->jobList,
Server::get(LoggerInterface::class),
);
$backgroundJob->start($this->jobList);
$task = $this->manager->getTask($task->getId());
self::assertEquals(Task::STATUS_FAILED, $task->getStatus());
self::assertEquals(FailingSyncProviderWithUserFacingError::ERROR_MESSAGE, $task->getErrorMessage());
self::assertEquals(FailingSyncProviderWithUserFacingError::USER_FACING_ERROR_MESSAGE, $task->getUserFacingErrorMessage());
}
public function testProviderShouldBeRegisteredAndFailOutputValidation(): void {
$this->registrationContext->expects($this->any())->method('getTaskProcessingProviders')->willReturn([
new ServiceRegistration('test', BrokenSyncProvider::class)