3 namespace Drupal\Tests\content_moderation\Kernel;
5 use Drupal\KernelTests\KernelTestBase;
6 use Drupal\node\Entity\Node;
7 use Drupal\node\Entity\NodeType;
8 use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
11 * @coversDefaultClass \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList
13 * @group content_moderation
15 class ModerationStateFieldItemListTest extends KernelTestBase {
17 use ContentModerationTestTrait;
22 public static $modules = [
32 * @var \Drupal\node\NodeInterface
39 protected function setUp() {
42 $this->installSchema('node', 'node_access');
43 $this->installEntitySchema('node');
44 $this->installEntitySchema('user');
45 $this->installEntitySchema('content_moderation_state');
46 $this->installConfig('content_moderation');
49 'type' => 'unmoderated',
52 $node_type = NodeType::create([
56 $workflow = $this->createEditorialWorkflow();
57 $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
60 $this->testNode = Node::create([
62 'title' => 'Test title',
64 $this->testNode->save();
65 \Drupal::entityTypeManager()->getStorage('node')->resetCache();
66 $this->testNode = Node::load($this->testNode->id());
70 * Test the field item list when accessing an index.
72 public function testArrayIndex() {
73 $this->assertFalse($this->testNode->isPublished());
74 $this->assertEquals('draft', $this->testNode->moderation_state[0]->value);
78 * Test the field item list when iterating.
80 public function testArrayIteration() {
82 foreach ($this->testNode->moderation_state as $item) {
83 $states[] = $item->value;
85 $this->assertEquals(['draft'], $states);
91 public function testGetValue() {
92 $this->assertEquals([['value' => 'draft']], $this->testNode->moderation_state->getValue());
98 public function testGet() {
99 $this->assertEquals('draft', $this->testNode->moderation_state->get(0)->value);
100 $this->setExpectedException(\InvalidArgumentException::class);
101 $this->testNode->moderation_state->get(2);
105 * Tests the item list when it is emptied and appended to.
107 public function testEmptyStateAndAppend() {
108 // This test case mimics the lifecycle of an entity that is being patched in
110 $this->testNode->moderation_state->setValue([]);
111 $this->assertTrue($this->testNode->moderation_state->isEmpty());
112 $this->assertEmptiedModerationFieldItemList();
114 $this->testNode->moderation_state->appendItem();
115 $this->assertEquals(1, $this->testNode->moderation_state->count());
116 $this->assertEquals(NULL, $this->testNode->moderation_state->value);
117 $this->assertEmptiedModerationFieldItemList();
121 * Test an empty value assigned to the field item.
123 public function testEmptyFieldItem() {
124 $this->testNode->moderation_state->value = '';
125 $this->assertEquals('', $this->testNode->moderation_state->value);
126 $this->assertEmptiedModerationFieldItemList();
130 * Test an empty value assigned to the field item list.
132 public function testEmptyFieldItemList() {
133 $this->testNode->moderation_state = '';
134 $this->assertEquals('', $this->testNode->moderation_state->value);
135 $this->assertEmptiedModerationFieldItemList();
139 * Test the field item when it is unset.
141 public function testUnsetItemList() {
142 unset($this->testNode->moderation_state);
143 $this->assertEquals(NULL, $this->testNode->moderation_state->value);
144 $this->assertEmptiedModerationFieldItemList();
148 * Test the field item when it is assigned NULL.
150 public function testAssignNullItemList() {
151 $this->testNode->moderation_state = NULL;
152 $this->assertEquals(NULL, $this->testNode->moderation_state->value);
153 $this->assertEmptiedModerationFieldItemList();
157 * Assert the set of expectations when the moderation state field is emptied.
159 protected function assertEmptiedModerationFieldItemList() {
160 $this->assertTrue($this->testNode->moderation_state->isEmpty());
161 // Test the empty value causes a violation in the entity.
162 $violations = $this->testNode->validate();
163 $this->assertCount(1, $violations);
164 $this->assertEquals('This value should not be null.', $violations->get(0)->getMessage());
165 // Test that incorrectly saving the entity regardless will not produce a
166 // change in the moderation state.
167 $this->testNode->save();
168 $this->assertEquals('draft', Node::load($this->testNode->id())->moderation_state->value);
172 * Test the list class with a non moderated entity.
174 public function testNonModeratedEntity() {
175 $unmoderated_node = Node::create([
176 'type' => 'unmoderated',
177 'title' => 'Test title',
179 $unmoderated_node->save();
180 $this->assertEquals(0, $unmoderated_node->moderation_state->count());
182 $unmoderated_node->moderation_state = NULL;
183 $this->assertEquals(0, $unmoderated_node->moderation_state->count());
184 $this->assertCount(0, $unmoderated_node->validate());
188 * Tests that moderation state changes also change the related entity state.
190 * @dataProvider moderationStateChangesTestCases
192 public function testModerationStateChanges($initial_state, $final_state, $first_published, $first_is_default, $second_published, $second_is_default) {
193 $this->testNode->moderation_state->value = $initial_state;
194 $this->assertEquals($first_published, $this->testNode->isPublished());
195 $this->assertEquals($first_is_default, $this->testNode->isDefaultRevision());
196 $this->testNode->save();
198 $this->testNode->moderation_state->value = $final_state;
199 $this->assertEquals($second_published, $this->testNode->isPublished());
200 $this->assertEquals($second_is_default, $this->testNode->isDefaultRevision());
204 * Data provider for ::testModerationStateChanges
206 public function moderationStateChangesTestCases() {
208 'Draft to draft' => [
216 'Draft to published' => [
224 'Published to published' => [
232 'Published to draft' => [
244 * Test updating the state for an entity without a workflow.
246 public function testEntityWithNoWorkflow() {
247 $node_type = NodeType::create([
248 'type' => 'example_no_workflow',
251 $test_node = Node::create([
252 'type' => 'example_no_workflow',
253 'title' => 'Test node with no workflow',
257 /** @var \Drupal\content_moderation\ModerationInformationInterface $content_moderation_info */
258 $content_moderation_info = \Drupal::service('content_moderation.moderation_information');
259 $workflow = $content_moderation_info->getWorkflowForEntity($test_node);
260 $this->assertNull($workflow);
262 $this->assertTrue($test_node->isPublished());
263 $test_node->moderation_state->setValue('draft');
264 // The entity is still published because there is not a workflow.
265 $this->assertTrue($test_node->isPublished());
269 * Test the moderation_state field after an entity has been serialized.
271 * @dataProvider entityUnserializeTestCases
273 public function testEntityUnserialize($state, $default, $published) {
274 $this->testNode->moderation_state->value = $state;
276 $this->assertEquals($state, $this->testNode->moderation_state->value);
277 $this->assertEquals($default, $this->testNode->isDefaultRevision());
278 $this->assertEquals($published, $this->testNode->isPublished());
280 $unserialized = unserialize(serialize($this->testNode));
282 $this->assertEquals($state, $unserialized->moderation_state->value);
283 $this->assertEquals($default, $unserialized->isDefaultRevision());
284 $this->assertEquals($published, $unserialized->isPublished());
288 * Test cases for ::testEntityUnserialize.
290 public function entityUnserializeTestCases() {
292 'Default draft state' => [
297 'Non-default published state' => [
306 * Test saving a moderated node with an existing ID.
308 * @dataProvider moderatedEntityWithExistingIdTestCases
310 public function testModeratedEntityWithExistingId($state) {
311 $node = Node::create([
312 'title' => 'Test title',
315 'moderation_state' => $state,
318 $this->assertEquals($state, $node->moderation_state->value);
322 * Test cases for ::testModeratedEntityWithExistingId.
324 public function moderatedEntityWithExistingIdTestCases() {
326 'Draft non-default state' => [
329 'Published default state' => [