function WorkspacePublisherTest::testPublishThrowableRollback

Same name and namespace in other branches
  1. 11.x core/modules/workspaces/tests/src/Kernel/WorkspacePublisherTest.php \Drupal\Tests\workspaces\Kernel\WorkspacePublisherTest::testPublishThrowableRollback()

Tests that a throwable during publish is logged and rolls back the save.

Attributes

#[DataProvider('providerPublishThrowableRollback')]

File

core/modules/workspaces/tests/src/Kernel/WorkspacePublisherTest.php, line 129

Class

WorkspacePublisherTest
Tests workspace publishing.

Namespace

Drupal\Tests\workspaces\Kernel

Code

public function testPublishThrowableRollback(string $thrown) : void {
  $logger = new TestLogger();
  $this->container
    ->get(LoggerChannelFactoryInterface::class)
    ->get('workspaces')
    ->addLogger($logger);
  // Create two nodes in Live and capture their default revision IDs.
  $node_1 = $this->createNode([
    'title' => 'node_1 live',
  ]);
  $node_2 = $this->createNode([
    'title' => 'node_2 live',
  ]);
  $node_1_live_vid = $node_1->getRevisionId();
  $node_2_live_vid = $node_2->getRevisionId();
  // Create a workspace and add a workspace-specific revision for each node.
  $workspace = Workspace::create([
    'id' => 'stage',
    'label' => 'Stage',
  ]);
  $workspace->save();
  $this->switchToWorkspace('stage');
  $storage = $this->entityTypeManager
    ->getStorage('node');
  foreach ([
    $node_1,
    $node_2,
  ] as $node) {
    $edited = $storage->loadUnchanged($node->id());
    $edited->title = 'workspace edit';
    $edited->save();
  }
  // Throw on the second presave inside the publisher's save loop, so the
  // first node's save has already happened inside the open transaction. The
  // data provider covers both \Exception and \Error subclasses; the
  // publisher's catch block must handle any \Throwable.
  $this->throwOnNodePresaveClass = $thrown;
  try {
    $workspace->publish();
  } catch (\Throwable) {
  }
  // Rollback proof: the first node's in-flight save was undone.
  $this->switchToLive();
  $this->assertSame($node_1_live_vid, $storage->loadUnchanged($node_1->id())
    ->getRevisionId());
  $this->assertSame($node_2_live_vid, $storage->loadUnchanged($node_2->id())
    ->getRevisionId());
  // The publisher logged the throwable on its channel.
  $this->assertTrue($logger->hasRecordThatPasses(static fn(array $record): bool => ($record['context']['@message'] ?? '') === 'Simulated node presave failure.', RfcLogLevel::ERROR));
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.