ww_publish-8.x-1.x-dev/tests/src/Kernel/WwPublishImportTest.php

tests/src/Kernel/WwPublishImportTest.php
<?php

namespace Drupal\Tests\ww_publish\Kernel;

use Aws\Sns\Message;
use DirectoryIterator;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\ww_publish\Entity\SnsMessageEntity;
use Drupal\ww_publish\Entity\SnsMessageEntityInterface;
use Drupal\ww_publish\Entity\TemplateEntity;
use Symfony\Component\ErrorHandler\BufferingLogger;

/**
 * Tests Woodwing Publish cron functionality.
 *
 * @group ww_publish
 * @requires module allowed_formats
 * @requires module focal_point
 */
class WwPublishImportTest extends WwPublishTestBase {

  use MediaTypeCreationTrait;
  use NodeCreationTrait;
  use UserCreationTrait;

  /**
   * The default author user.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $author;

  /**
   * Modules to enable.
   *
   * @var array
   */
  protected static $modules = [
    'crop', 'focal_point',
  ];

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();

    $this->installEntitySchema('crop');
    $this->installConfig(['crop', 'focal_point']);

    $this->addParagraphedContentType('article');

    $this->config('ww_publish.settings')->set('content_type_field', 'article')->save();
    // Configure the Node type where the articles will be published.
    $node_type = NodeType::load('article');
    $node_type->setThirdPartySetting('ww_publish', 'paragraph_field', 'field_paragraphs');
    $node_type->setThirdPartySetting('ww_publish', 'article_storyid_field', 'field_test_ww_id');
    $node_type->setThirdPartySetting('ww_publish', 'content_station_identifier_title', 'title');
    $node_type->save();
    FieldStorageConfig::create([
      'field_name' => 'field_test_ww_id',
      'entity_type' => 'node',
      'type' => 'string',
    ])->save();
    FieldConfig::create([
      'label' => 'WW ID',
      'field_name' => 'field_test_ww_id',
      'entity_type' => 'node',
      'bundle' => 'article',
    ])->save();

    FieldStorageConfig::create([
      'field_name' => 'field_subtitle',
      'entity_type' => 'node',
      'type' => 'string',
    ])->save();
    $subtitle_field = FieldConfig::create([
      'label' => 'Subtitle',
      'field_name' => 'field_subtitle',
      'entity_type' => 'node',
      'bundle' => 'article',
    ]);
    $subtitle_field->setThirdPartySetting('ww_publish', 'content_station_identifier', 'subtitle|title');
    $subtitle_field->save();

    FieldStorageConfig::create([
      'field_name' => 'field_intro',
      'entity_type' => 'node',
      'type' => 'text_long',
    ])->save();
    $subtitle_field = FieldConfig::create([
      'label' => 'Intro',
      'field_name' => 'field_intro',
      'entity_type' => 'node',
      'bundle' => 'article',
    ]);
    $subtitle_field->setThirdPartySetting('ww_publish', 'content_station_identifier', 'intro');
    $subtitle_field->setThirdPartySetting('allowed_formats', 'allowed_formats', ['basic_html']);
    $subtitle_field->save();

    $vocabulary = Vocabulary::create([
      'vid' => 'category',
      'name' => 'Category',
    ]);
    $vocabulary->save();
    FieldStorageConfig::create([
      'field_name' => 'field_category',
      'entity_type' => 'node',
      'type' => 'entity_reference',
      'settings' => [
        'target_type' => 'taxonomy_term',
      ]
    ])->save();
    $category_field = FieldConfig::create([
      'label' => 'Category',
      'field_name' => 'field_category',
      'entity_type' => 'node',
      'bundle' => 'article',
    ]);
    $category_field->setThirdPartySetting('ww_publish', 'content_station_identifier', 'metadata:ExtraMetaData|C_ONLINERESSORT');
    $category_field->save();

    Vocabulary::create([
      'vid' => 'publication',
      'name' => 'Publication',
    ])->save();
    FieldStorageConfig::create([
      'field_name' => 'field_publication',
      'entity_type' => 'node',
      'type' => 'entity_reference',
      'settings' => [
        'target_type' => 'taxonomy_term',
      ]
    ])->save();
    $publication_field = FieldConfig::create([
      'label' => 'Publication',
      'field_name' => 'field_publication',
      'entity_type' => 'node',
      'bundle' => 'article',
    ]);
    $publication_field->setThirdPartySetting('ww_publish', 'content_station_identifier', 'metadata:BasicMetaData|Publication|Name');
    $publication_field->save();

    FieldStorageConfig::create([
        'field_name' => 'field_image',
        'entity_type' => 'node',
        'type' => 'entity_reference',
        'settings' => [
          'target_type' => 'media',
        ],
      ]
    )->save();
    $field_image = FieldConfig::create([
      'label' => 'Image',
      'field_name' => 'field_image',
      'entity_type' => 'node',
      'bundle' => 'article',
      'settings' => [
        'handler_settings' => [
          'target_bundles' => [
            'image' => 'image',
          ],
        ],
      ],
    ]);
    $field_image->setThirdPartySetting('ww_publish', 'content_station_identifier', 'image|image');
    $field_image->save();

    // Create the image media bundle.
    $media_type = $this->createMediaType('image', ['id' => 'image']);
    $media_type->setThirdPartySetting('ww_publish', 'id_field', 'field_image_ww_id');
    $media_type->save();
    FieldStorageConfig::create([
      'field_name' => 'field_image_ww_id',
      'entity_type' => 'media',
      'type' => 'string',
    ])->save();

    FieldConfig::create([
      'label' => 'WW ID',
      'field_name' => 'field_image_ww_id',
      'entity_type' => 'media',
      'bundle' => 'image',
    ])->save();

    // Create paragraph types and their fields.
    $this->addParagraphsType('text');
    FieldStorageConfig::create([
      'field_name' => 'field_text',
      'entity_type' => 'paragraph',
      'type' => 'text_long',
    ])->save();
    $field_config = FieldConfig::create([
      'label' => 'Text',
      'field_name' => 'field_text',
      'entity_type' => 'paragraph',
      'bundle' => 'text',
      'settings' => [],
    ]);
    $field_config->setThirdPartySetting('ww_publish', 'content_station_identifier', 'body,crosshead,embed');
    $field_config->save();

    $this->addParagraphsType('url');
    FieldStorageConfig::create([
      'field_name' => 'field_link',
      'entity_type' => 'paragraph',
      'type' => 'link',
    ])->save();
    $field_config = FieldConfig::create([
      'label' => 'Link',
      'field_name' => 'field_link',
      'entity_type' => 'paragraph',
      'bundle' => 'url',
      'settings' => [],
    ]);
    $field_config->setThirdPartySetting('ww_publish', 'content_station_identifier', 'social-media|media|url,video|media|url');
    $field_config->save();

    $this->addParagraphsType('image');
    FieldStorageConfig::create([
      'field_name' => 'field_image',
      'entity_type' => 'paragraph',
      'type' => 'entity_reference',
      'settings' => [
        'target_type' => 'media',
      ],
    ]
    )->save();
    $field_image = FieldConfig::create([
      'label' => 'Image',
      'field_name' => 'field_image',
      'entity_type' => 'paragraph',
      'bundle' => 'image',
      'settings' => [
        'handler_settings' => [
          'target_bundles' => [
            'image' => 'image',
          ],
        ],
      ],
    ]);
    $field_image->setThirdPartySetting('ww_publish', 'content_station_identifier', 'image');
    $field_image->save();

    // @todo Support reusing the same paragraph type for multiple identifiers.
    $this->addParagraphsType('quote');
    $field_config = FieldConfig::create([
      'label' => 'Quote',
      'field_name' => 'field_text',
      'entity_type' => 'paragraph',
      'bundle' => 'quote',
      'settings' => [],
    ]);
    $field_config->setThirdPartySetting('ww_publish', 'content_station_identifier', 'quote');
    $field_config->save();

    // Add a container paragraph type.
    $this->addParagraphsType('container');
    $this->addParagraphsField('container', 'field_paragraphs', 'paragraph');
    $field_container = FieldConfig::loadByName('paragraph', 'container', 'field_paragraphs');
    $field_container->setThirdPartySetting('ww_publish', 'content_station_identifier', 'container|main');
    $field_container->set('settings', ['handler_settings' => ['target_bundles' => ['text' => 'text', 'image' => 'image', 'quite' => 'quote', 'url' => 'url']]])->save();
    $field_container->save();

    $field_config = FieldConfig::loadByName('node', 'article', 'field_paragraphs');
    $field_config->set('settings', ['handler_settings' => ['target_bundles' => ['text' => 'text', 'image' => 'image', 'quite' => 'quote', 'url' => 'url', 'container' => 'container']]])->save();

    // Add a mapping field to users.
    FieldStorageConfig::create([
      'field_name' => 'field_ww_author_name',
      'entity_type' => 'user',
      'type' => 'string',
    ])->save();
    $field_config = FieldConfig::create([
      'label' => 'WW Author name',
      'field_name' => 'field_ww_author_name',
      'entity_type' => 'user',
      'bundle' => 'user',
    ]);
    $field_config->setThirdPartySetting('ww_publish', 'content_station_identifier', 'ExtraMetaData|C_ONLINEAUTOR');
    $field_config->save();

    // Create an author user.
    $this->author = $this->createUser();
    $this->config('ww_publish.settings')
      ->set('ww_user', $this->author->id())
      ->set('ww_user_field', 'field_ww_author_name')
      ->save();

    // Set up necessary templates.
    $bold = TemplateEntity::create([
      'id' => 'bold',
      'name' => 'Attribute: Bold',
      'type' => 'attribute',
      'target' => 'bold',
      'template' => '<strong>{{insert}}</strong>'
    ]);
    $bold->save();

    // Tests the BC layer for the insert placeholder.
    $bold = TemplateEntity::create([
      'id' => 'intro',
      'name' => 'Component: Intro',
      'type' => 'component',
      'target' => 'intro',
      'template' => '<strong>{{insert}}</strong>'
    ]);
    $bold->save();
    $bold = TemplateEntity::create([
      'id' => 'crosshead',
      'name' => 'Component: Crosshead',
      'type' => 'component',
      'target' => 'crosshead',
      'template' => '<h2>{{text}}</h2>'
    ]);
    $bold->save();
    $bold = TemplateEntity::create([
      'id' => 'quote',
      'name' => 'Component: Quote',
      'type' => 'component',
      'target' => 'quote',
      'template' => '<blockquote><p>{{text}}</p><footer>{{author}}, {{function}}</footer></blockquote>'
    ]);
    $bold->save();
  }

  /**
   * Tests a successful import using the StoryID field.
   */
  public function testImport() {
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);

    $sport = Term::create([
      'name' => 'Sport',
      'vid' => 'category',
    ]);
    $sport->save();

    $lorem_publication = Term::create([
      'name' => 'Lorem Ipsum',
      'vid' => 'publication',
    ]);
    $lorem_publication->save();

    $message = SnsMessageEntity::create([
      'id' => '1',
      'name' => 'test',
      'url' => $this->getFixturePath('test_article', 'article.zip'),
      'metadata_url' => $this->getFixturePath('test_article', 'metadata.json'),
      'article_json_url' => $this->getFixturePath('test_article', 'article.json'),
      'tenant_id' => '1',
      'brand' => 'test',
    ]);
    $message->save();
    \ww_publish_cron();

    $message = SnsMessageEntity::load($message->id());
    $this->assertTrue($message->isExecuted());

    $logs = $logger->cleanLogs();

    $node = $this->getNodeByTitle('This is the title > of the article');

    $this->assertEquals('The following article has been created: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[0][1]);
    $this->assertEquals('This is the title > of the article', $logs[0][2]['@node_title']);
    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $logs[0][2]['@ww_id']);
    $this->assertEquals($node->id(), $logs[0][2]['@node_id']);

    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $node->get('field_test_ww_id')->value);
    $this->assertTrue($node->isPublished());
    $this->assertEquals($this->author->id(), $node->getOwnerId());
    $this->assertEquals('The subtitle', $node->get('field_subtitle')->value);
    $this->assertEquals($sport->id(), $node->get('field_category')->target_id);
    $this->assertEquals($lorem_publication->id(), $node->get('field_publication')->target_id);
    $this->assertEquals('<strong>This is the intro &gt; text. Lorem ipsum dolor sit amet, consetetur sadipscing elitr.</strong>', $node->get('field_intro')->value);
    $this->assertEquals('basic_html', $node->get('field_intro')->format);

    $this->assertCount(8, $node->get('field_paragraphs'));

    /** @var \Drupal\media\MediaInterface $media */
    $media = $node->get('field_paragraphs')->get(0)->entity->get('field_image')->entity;
    $this->assertEquals('20180921145938948.jpeg', $media->label());
    $this->assertEquals('Lorem ipsum dolor sit amet, consetetur sadipscing elitr.', $media->get('field_media_image')->alt);
    $this->assertEmpty($media->get('field_media_image')->title);
    $this->assertEquals($this->author->id(), $media->getOwnerId());

    /** @var \Drupal\file\FileInterface $image */
    $image = $media->get('field_media_image')->entity;
    $this->assertEquals('20180921145938948.jpeg', $image->getFilename());
    $this->assertEquals('public://woodwing/' . date('Y-m') . '/20180921145938948.jpeg', $image->getFileUri());
    $this->assertTrue(\file_exists($image->getFileUri()));

    $crop = \Drupal::service('focal_point.manager')->getCropEntity($image, 'focal_point');
    $this->assertEquals('8', $crop->x->value);
    $this->assertEquals('6', $crop->y->value);

    // The same media is also added on the node media field.
    $this->assertEquals($media->id(), $node->get('field_image')->target_id);

    $this->assertEquals('quote', $node->get('field_paragraphs')->get(1)->entity->bundle());
    $this->assertEquals('<blockquote><p>Lorem &gt; ipsum dolor sit amet, consetetur sadipscing elitr.</p><footer>John &gt; Doe, Lorem &lt; ipsum</footer></blockquote>', $node->get('field_paragraphs')->get(1)->entity->get('field_text')->value);
    $this->assertEquals('text', $node->get('field_paragraphs')->get(2)->entity->bundle());
    $this->assertEquals('Lorem ipsum dolor sit amet, consetetur sadipscing elitr.', $node->get('field_paragraphs')->get(2)->entity->get('field_text')->value);
    $this->assertEquals('full_html', $node->get('field_paragraphs')->get(2)->entity->get('field_text')->format);

    $this->assertEquals('text', $node->get('field_paragraphs')->get(3)->entity->bundle());
    $this->assertEquals('<h2>This is a subtitle</h2>', $node->get('field_paragraphs')->get(3)->entity->get('field_text')->value);
    $this->assertEquals('full_html', $node->get('field_paragraphs')->get(3)->entity->get('field_text')->format);

    $this->assertEquals('url', $node->get('field_paragraphs')->get(4)->entity->bundle());
    $this->assertEquals('youtube.com/watch?v=DF4P0cjStkM', $node->get('field_paragraphs')->get(4)->entity->get('field_link')->uri);

    $this->assertEquals('url', $node->get('field_paragraphs')->get(5)->entity->bundle());
    $this->assertEquals('https://twitter.com/POTUS/status/1376700955295686667', $node->get('field_paragraphs')->get(5)->entity->get('field_link')->uri);

    $this->assertEquals('text', $node->get('field_paragraphs')->get(6)->entity->bundle());
    $this->assertEquals('<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2..." width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"></iframe>', $node->get('field_paragraphs')->get(6)->entity->get('field_text')->value);

    // Asserting the container.
    /** @var \Drupal\paragraphs\ParagraphInterface $container */
    $container = $node->get('field_paragraphs')->get(7)->entity;
    $this->assertEquals('container', $container->bundle());
    $this->assertCount(1, $container->get('field_paragraphs'));
    $this->assertEquals('Diam nonumy eirmod <strong>tempor &gt;</strong> invidunt ut labore &gt; et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', $container->get('field_paragraphs')->get(0)->entity->get('field_text')->value);

    // Check the temp folder is empty after publishing the article.
    $fileSystem = \Drupal::service('file_system');
    foreach (new DirectoryIterator($fileSystem->getTempDirectory()) as $fileInfo) {
      if ($fileInfo->isDot()) {
        continue;
      }
      $this->fail('Unexpected temporary file: ' . $fileInfo->getFilename());
    }

    // Create a specific user with a referenced WW author name.
    $update_user = $this->createUser();
    $update_user->set('field_ww_author_name', 'Author 1');
    $update_user->save();

    // Create a new message to update the article and re-run the import.
    $update_message = SnsMessageEntity::create([
      'id' => '2',
      'name' => 'test',
      'url' => $this->getFixturePath('test_article_update', 'article.zip'),
      'metadata_url' => $this->getFixturePath('test_article_update', 'metadata.json'),
      'article_json_url' => $this->getFixturePath('test_article_update', 'article.json'),
      'tenant_id' => '1',
      'brand' => 'test',
    ]);
    $update_message->save();
    \ww_publish_cron();

    $update_message = SnsMessageEntity::load($update_message->id());
    $this->assertTrue($update_message->isExecuted());

    $logs = $logger->cleanLogs();

    $updated_node = $this->getNodeByTitle('This is the title of the article UPDATE');
    $this->assertEquals($node->id(), $updated_node->id());
    $this->assertEquals($update_user->id(), $node->getOwnerId());
    $this->assertEquals($update_user->id(), $node->getRevisionUserId());

    $this->assertEquals('The following article has been updated: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[0][1]);
    $this->assertEquals('This is the title of the article UPDATE', $logs[0][2]['@node_title']);
    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $logs[0][2]['@ww_id']);
    $this->assertEquals($updated_node->id(), $logs[0][2]['@node_id']);

    $this->assertTrue($node->isPublished());
    $this->assertEquals('The subtitle UPDATE', $node->get('field_subtitle')->value);

    $this->assertCount(8, $node->get('field_paragraphs'));

    // The existing media was reused.
    /** @var \Drupal\media\MediaInterface $updated_media */
    $updated_media = $node->get('field_paragraphs')->get(0)->entity->get('field_image')->entity;
    $this->assertEquals($media->id(), $updated_media->id());

    $this->assertEquals('quote', $node->get('field_paragraphs')->get(1)->entity->bundle());
    $this->assertEquals('<blockquote><p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr UPDATE.</p><footer>John Doe, Lorem ipsum</footer></blockquote>', $node->get('field_paragraphs')->get(1)->entity->get('field_text')->value);
    $this->assertEquals('text', $node->get('field_paragraphs')->get(2)->entity->bundle());
    $this->assertEquals('Lorem ipsum dolor sit amet, consetetur sadipscing elitr.', $node->get('field_paragraphs')->get(2)->entity->get('field_text')->value);

    $container = $node->get('field_paragraphs')->get(7)->entity;
    $this->assertEquals('container', $container->bundle());
    $this->assertCount(1, $container->get('field_paragraphs'));
    $this->assertEquals('UPDATE: Diam nonumy eirmod <strong>tempor</strong> invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.', $container->get('field_paragraphs')->get(0)->entity->get('field_text')->value);
  }

  /**
   * Tests cropped images.
   */
  public function testCroppedImages() {
    // Create a new message with a cropped image.
    $cropped_message = SnsMessageEntity::create([
      'id' => '3',
      'name' => 'test',
      'url' => $this->getFixturePath('test_article_cropped', 'article.zip'),
      'metadata_url' => $this->getFixturePath('test_article_cropped', 'metadata.json'),
      'article_json_url' => $this->getFixturePath('test_article_cropped', 'article.json'),
      'tenant_id' => '1',
      'brand' => 'test',
    ]);
    $cropped_message->save();
    \ww_publish_cron();

    $cropped_message = SnsMessageEntity::load($cropped_message->id());
    $this->assertTrue($cropped_message->isExecuted());

    $node = $this->getNodeByTitle('This is the title > of the cropped article');
    $file = $node->get('field_image')->entity->get('field_media_image')->entity;
    $this->assertEquals('20180921145938948.jpeg', $file->getFilename());
    $this->assertEmpty(file_validate_image_resolution($file, '328x205', '326x203'));
  }

  /**
   * Tests a successful import using only the ID field.
   */
  public function testImportIdField() {
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);

    $node_type = NodeType::load('article');
    $node_type->setThirdPartySetting('ww_publish', 'article_storyid_field', '');
    $node_type->setThirdPartySetting('ww_publish', 'article_id_field', 'field_test_ww_id');
    $node_type->save();

    $message = SnsMessageEntity::create(
      [
        'id' => '1',
        'name' => 'test',
        'url' => $this->getFixturePath('test_article', 'article.zip'),
        'metadata_url' => $this->getFixturePath('test_article', 'metadata.json'),
        'article_json_url' => $this->getFixturePath('test_article', 'article.json'),
        'tenant_id' => '1',
        'brand' => 'test',
      ]
    );
    $message->save();
    \ww_publish_cron();

    $message = SnsMessageEntity::load($message->id());
    $this->assertTrue($message->isExecuted());

    $logs = $logger->cleanLogs();

    $node = $this->getNodeByTitle('This is the title > of the article');

    $this->assertEquals('The following article has been created: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[0][1]);
    $this->assertEquals('This is the title > of the article', $logs[0][2]['@node_title']);
    $this->assertEquals('156', $logs[0][2]['@ww_id']);
    $this->assertEquals($node->id(), $logs[0][2]['@node_id']);

    $this->assertEquals('156', $node->get('field_test_ww_id')->value);
  }

  /**
   * Tests a successful import with an existing article using the ID.
   */
  public function testImportExistingID() {
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);

    $node_type = NodeType::load('article');
    $node_type->setThirdPartySetting('ww_publish', 'article_id_field', 'field_test_ww_id');
    $node_type->save();

    $node = Node::create([
      'type' => 'article',
      'title' => 'Article with old ID',
      'field_test_ww_id' => 156,
    ]);
    $node->save();

    $message = SnsMessageEntity::create(
      [
        'id' => '1',
        'name' => 'test',
        'url' => $this->getFixturePath('test_article', 'article.zip'),
        'metadata_url' => $this->getFixturePath('test_article', 'metadata.json'),
        'article_json_url' => $this->getFixturePath('test_article', 'article.json'),
        'tenant_id' => '1',
        'brand' => 'test',
      ]
    );
    $message->save();
    \ww_publish_cron();

    $message = SnsMessageEntity::load($message->id());
    $this->assertTrue($message->isExecuted());

    $logs = $logger->cleanLogs();

    $updated_node = $this->getNodeByTitle('This is the title > of the article');

    $this->assertEquals('The following article has been updated: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[0][1]);
    $this->assertEquals('This is the title > of the article', $logs[0][2]['@node_title']);
    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $logs[0][2]['@ww_id']);
    $this->assertEquals($updated_node->id(), $logs[0][2]['@node_id']);

    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $updated_node->get('field_test_ww_id')->value);
    $this->assertEquals($node->id(), $updated_node->id());
  }

  /**
   * Tests Article importing with missing templates.
   */
  public function testImportWithMissingTemplates() {
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);
    $message = SnsMessageEntity::create([
      'id' => '1',
      'name' => 'test',
      'url' => $this->getFixturePath('test_article_attributes', 'article.zip'),
      'metadata_url' => $this->getFixturePath('test_article_attributes', 'metadata.json'),
      'article_json_url' => $this->getFixturePath('test_article_attributes', 'article.json'),
      'tenant_id' => '1',
      'brand' => 'test',
    ]);
    $message->save();
    \ww_publish_cron();

    $message = SnsMessageEntity::load($message->id());
    $this->assertTrue($message->isExecuted());

    $logs = $logger->cleanLogs();
    $node = $this->getNodeByTitle('This is the title of the article WITH MISSING TEMPLATES');

    $this->assertEquals('No template entity found with target: @target and type: @type.', $logs[0][1]);
    $this->assertEquals('attribute', $logs[0][2]['@type']);
    $this->assertEquals('background-color', $logs[0][2]['@target']);
    $this->assertEquals('No template entity found with target: @target and type: @type.', $logs[1][1]);
    $this->assertEquals('attribute', $logs[1][2]['@type']);
    $this->assertEquals('color', $logs[1][2]['@target']);
    $this->assertEquals('The following article has been created: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[2][1]);
    $this->assertEquals('This is the title of the article WITH MISSING TEMPLATES', $logs[2][2]['@node_title']);
    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $logs[2][2]['@ww_id']);
    $this->assertEquals($node->id(), $logs[2][2]['@node_id']);
    $this->assertCount(1, $node->get('field_paragraphs'));

    $this->assertEquals('text', $node->get('field_paragraphs')->get(0)->entity->bundle());
    $this->assertEquals('Lorem ipsum dolor sit amet, consetetur sadipscing elitr.', $node->get('field_paragraphs')->get(0)->entity->get('field_text')->value);
    $this->assertEquals('full_html', $node->get('field_paragraphs')->get(0)->entity->get('field_text')->format);
  }

  /**
   * Tests articles publishing with cron mode disabled.
   */
  public function testDestructibleService() {
    $this->config('ww_publish.settings')
      ->set('cron_mode', FALSE)
      ->set('topic_arn', ['test:ecs-export-topic:test', 'test2:ecs-export-topic2:test2'])
      ->save();
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);
    $data = [
      'MessageId' => '1',
      'Timestamp' => '',
      'TopicArn' => 'test:ecs-export-topic:test',
      'Type' => 'Notification',
      'Signature' => '',
      'SigningCertURL' => '',
      'SignatureVersion' => '',
      'Message' => \json_encode([
        'id' => '1',
        'name' => 'name',
        'url' => $this->getFixturePath('test_article', 'article.zip'),
        'metadataUrl' => $this->getFixturePath('test_article', 'metadata.json'),
        'articleJsonUrl' => $this->getFixturePath('test_article', 'article.json'),
        'tenantId' => '1',
        'brand' => 'test',
      ])
    ];

    $message = new Message($data);
    \Drupal::service('amazon_sns.message_dispatcher')->dispatch($message);
    $this->assertFalse($this->getNodeByTitle('This is the title > of the article'));
    \Drupal::service('ww_publish.notification_logger_subscriber')->destruct();
    $logs = $logger->cleanLogs();

    $node = $this->getNodeByTitle('This is the title > of the article');
    $this->assertEquals('The following article has been created: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[0][1]);

    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $node->get('field_test_ww_id')->value);
  }

  /**
   * Tests articles publishing race conditions with immediate import.
   */
  public function testDestructibleServiceRaceCondition() {
    $this->config('ww_publish.settings')
      ->set('cron_mode', FALSE)
      ->set('topic_arn', ['test:ecs-export-topic:test'])
      ->save();
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);
    $data = [
      'MessageId' => '1',
      'Timestamp' => '',
      'TopicArn' => 'test:ecs-export-topic:test',
      'Type' => 'Notification',
      'Signature' => '',
      'SigningCertURL' => '',
      'SignatureVersion' => '',
      'Message' => \json_encode([
        'id' => '1',
        'name' => 'name',
        'url' => $this->getFixturePath('test_article', 'article.zip'),
        'metadataUrl' => $this->getFixturePath('test_article', 'metadata.json'),
        'articleJsonUrl' => $this->getFixturePath('test_article', 'article.json'),
        'tenantId' => '1',
        'brand' => 'test',
      ])
    ];

    $message = new Message($data);
    \Drupal::service('amazon_sns.message_dispatcher')->dispatch($message);
    $this->assertFalse($this->getNodeByTitle('This is the title > of the article'));

    // Simulate a cron call that happens before destruct is called. Ensure
    // that only a single log entry is logged for creating the article and
    // no update.
    \ww_publish_cron();

    \Drupal::service('ww_publish.notification_logger_subscriber')->destruct();
    $logs = $logger->cleanLogs();
    $this->assertCount(1, $logs);

    $node = $this->getNodeByTitle('This is the title > of the article');
    $this->assertEquals('The following article has been created: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[0][1]);

    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $node->get('field_test_ww_id')->value);
  }

  /**
   * Tests validation messages.
   */
  public function testValidate() {
    FieldStorageConfig::create([
      'field_name' => 'field_messages',
      'entity_type' => 'node',
      'type' => 'string_long',
      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
    ])->save();
    $subtitle_field = FieldConfig::create([
      'label' => 'Intro',
      'field_name' => 'field_messages',
      'entity_type' => 'node',
      'bundle' => 'article',
    ]);
    $subtitle_field->save();
    $this->config('ww_publish.settings')->set('error_messages_field', 'field_messages')->save();

    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);

    $sport = Term::create([
      'name' => 'Sport',
      'vid' => 'category',
    ]);
    $sport->save();

    $lorem_publication = Term::create([
      'name' => 'Lorem Ipsum',
      'vid' => 'publication',
    ]);
    $lorem_publication->save();

    $message = SnsMessageEntity::create([
      'id' => '1',
      'name' => 'test',
      'url' => $this->getFixturePath('test_article', 'article.zip'),
      'metadata_url' => $this->getFixturePath('test_article', 'metadata.json'),
      'article_json_url' => $this->getFixturePath('test_article_validate', 'article.json'),
      'tenant_id' => '1',
      'brand' => 'test',
    ]);
    $message->save();
    \ww_publish_cron();
    $logs = $logger->cleanLogs();
    $this->assertCount(2, $logs);


    $node = $this->getNodeByTitle('Validate example');
    $this->assertEquals('The value which should be saved in the field <strong>@field_name</strong> is too long.<br> Maximum length: <strong>@max_length<br> Shortened value: <i>@value</i>', $logs[0][1]);
    $this->assertEquals('The following article has been created: @node_title (WW ID: @ww_id, Drupal ID: @node_id)', $logs[1][1]);

    $this->assertEquals('f4c16641-f483-5b66-b5bc-cf485e658e4b', $node->get('field_test_ww_id')->value);

    $message = SnsMessageEntity::load($message->id());
    $this->assertTrue($message->isExecuted());
    $this->assertEquals(SnsMessageEntityInterface::IMPORTED, $message->getStatus());

    $this->assertCount(3, $node->get('field_messages'));
    $this->assertStringContainsString("The value which should be saved in the field field_subtitle is too long.\nMaximum length: 255\nShortened value: Lorem", $node->get('field_messages')->value);
    $this->assertStringContainsString("field_paragraphs.0.field_link.0: The path 'not-a-url' is invalid.", $node->get('field_messages')[1]->value);
    $this->assertStringContainsString('field_paragraphs.0.field_link.0.uri: This value should be of the correct primitive type.', $node->get('field_messages')[2]->value);
  }

  /**
   * Tests a failed import.
   */
  public function testFailed() {
    $this->enableModules(['node_test_exception']);
    $logger = new BufferingLogger();
    $this->container->get('logger.factory')->addLogger($logger);

    $sport = Term::create([
      'name' => 'Sport',
      'vid' => 'category',
    ]);
    $sport->save();

    $lorem_publication = Term::create([
      'name' => 'Lorem Ipsum',
      'vid' => 'publication',
    ]);
    $lorem_publication->save();

    $message = SnsMessageEntity::create([
      'id' => '1',
      'name' => 'test',
      'url' => $this->getFixturePath('test_article', 'article.zip'),
      'metadata_url' => $this->getFixturePath('test_article', 'metadata.json'),
      'article_json_url' => $this->getFixturePath('test_article_exception', 'article.json'),
      'tenant_id' => '1',
      'brand' => 'test',
    ]);
    $message->save();
    \ww_publish_cron();
    $logs = $logger->cleanLogs();
    $this->assertCount(2, $logs);

    $this->assertEquals('A node could not be created. @message in %function (line %line of %file).', $logs[1][1]);
    $this->assertEquals('Test exception for rollback.', $logs[1][2]['@message']);

    $message = SnsMessageEntity::load($message->id());
    $this->assertTrue($message->isExecuted());
    $this->assertEquals(SnsMessageEntityInterface::FAILED, $message->getStatus());
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc