You are here

SmartlingTest.php in TMGMT Translator Smartling 8

File

src/Tests/SmartlingTest.php
View source
<?php

/**
 * @file
 * Contains \Drupal\tmgmt_smartling\Tests\SmartlingTest.
 */
namespace Drupal\tmgmt_smartling\Tests;

use Drupal;
use Drupal\node\Entity\Node;
use Drupal\tmgmt\Entity\Job;
use Drupal\tmgmt\JobInterface;
use Drupal\tmgmt\Tests\TMGMTTestBase;
use Drupal\tmgmt_smartling\Smartling\SmartlingApi;
use Drupal\tmgmt_smartling\Smartling\SmartlingApiException;

/**
 * Basic tests for the Smartling translator.
 *
 * @group tmgmt_smartling
 */
class SmartlingTest extends TMGMTTestBase {

  /**
   * Name of file that contains settings for test Smartling project.
   *
   * @var string
   */
  const SETTINGS_FILE_NAME = 'tmgmt_smartling.simpletest.settings.php';

  /**
   * Smartling test project settings.
   *
   * @var array
   */
  private $smartlingPluginProviderSettings = [];

  /**
   * Modules to enable.
   *
   * @var array
   */
  public static $modules = [
    'tmgmt',
    'tmgmt_demo',
    'tmgmt_smartling',
    'tmgmt_smartling_context_debug',
    'tmgmt_smartling_test',
    'dblog',
  ];

  /**
   * @var int
   */
  private $testNodeId = 3;

  /**
   * @var string
   */
  private $testNodeTitle;

  /**
   * @var string
   */
  private $testNodeBody;

  /**
   * @var string
   */
  private $targetLanguage = 'fr';

  /**
   * @var string
   */
  private $sourceLanguage = 'en';

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    parent::setUp();
    $settings_file_path = __DIR__ . '/../../' . self::SETTINGS_FILE_NAME;

    // Include settings from external file.
    if (file_exists($settings_file_path) && empty($this->smartlingPluginProviderSettings)) {
      require_once $settings_file_path;

      // Fetch needed data.
      $this->smartlingPluginProviderSettings = $settings;
      $test_node = Node::load($this->testNodeId);
      $this->testNodeTitle = $test_node
        ->get('title')->value;
      $this->testNodeBody = trim(strip_tags($test_node
        ->get('body')->value));
    }

    // Additional permission: access to "Recent log messages" page and
    // access for manual context sending.
    $this
      ->loginAsAdmin([
      'access site reports',
      'send context smartling',
    ]);
  }

  /**
   * Removes test file from Smartling dashboard.
   *
   * @param $fileName
   */
  private function deleteTestFile($fileName) {
    try {
      $smartlingApi = new SmartlingApi($this->smartlingPluginProviderSettings['settings[key]'], $this->smartlingPluginProviderSettings['settings[project_id]'], Drupal::getContainer()
        ->get('http_client'), $this->smartlingPluginProviderSettings['settings[api_url]']);
      $smartlingApi
        ->deleteFile($fileName);
    } catch (SmartlingApiException $e) {

      // File not found.
    }
  }

  /**
   * Sets up Smartling provider settings and returns translator plugin.
   *
   * @param array $providerSettings
   *
   * @return \Drupal\tmgmt\TranslatorInterface
   */
  private function setUpSmartlingProviderSettings(array $providerSettings) {
    $translator = $this
      ->createTranslator([
      'plugin' => 'smartling',
      'auto_accept' => $providerSettings['auto_accept'],
      'settings' => [
        'api_url' => $providerSettings['settings[api_url]'],
        'project_id' => $providerSettings['settings[project_id]'],
        'key' => $providerSettings['settings[key]'],
        'orgID' => $providerSettings['settings[orgID]'],
        'contextUsername' => $providerSettings['settings[contextUsername]'],
        'context_silent_user_switching' => $providerSettings['settings[context_silent_user_switching]'],
        'retrieval_type' => $providerSettings['settings[retrieval_type]'],
        'auto_authorize_locales' => $providerSettings['settings[auto_authorize_locales]'],
        'callback_url_use' => $providerSettings['settings[callback_url_use]'],
        'scheme' => $providerSettings['settings[scheme]'],
        'custom_regexp_placeholder' => $providerSettings['settings[custom_regexp_placeholder]'],
        'export_format' => $providerSettings['settings[export_format]'],
      ],
    ]);
    return $translator;
  }

  /**
   * Requests translation for a given node.
   *
   * @param $nid
   * @param $language
   * @param $translator
   *
   * @return \Drupal\tmgmt\JobInterface
   */
  private function requestTranslationForNode($nid, $language, $translator) {
    $job = $this
      ->createJob($this->sourceLanguage, $language, 1, [
      'label' => 'Job for ' . $nid,
      'job_type' => Job::TYPE_NORMAL,
    ]);
    $job->translator = $translator;
    $job
      ->addItem('content', 'node', $nid);
    $job
      ->setState(JobInterface::STATE_ACTIVE);
    $job
      ->requestTranslation();
    return $job;
  }

  /**
   * Checks if generated file exists and correct.
   *
   * @param $fileName
   * @param $nodeTitle
   */
  private function checkGeneratedFile($fileName, $nodeTitle) {
    $url = \Drupal::service('stream_wrapper_manager')
      ->getViaUri(file_default_scheme() . "://tmgmt_sources/{$fileName}")
      ->getExternalUrl();
    $this
      ->drupalGet($url);
    $this
      ->assertResponse(200);
    $this
      ->assertRaw($nodeTitle);
  }

  /**
   * Checks if download was successful.
   *
   * @param $jobId
   * @param $fileName
   * @throws \Exception
   */
  private function downloadAndCheckTranslatedFile($jobId, $fileName) {
    $this
      ->drupalPostForm("admin/tmgmt/jobs/{$jobId}", [], t('Download'));
    $this
      ->drupalGet('admin/reports/dblog');
    $this
      ->assertResponse(200);

    // TODO: don't know why assertLink and assertRaw doesn't work with quoted
    // strings.
    $this
      ->assertRaw('Translation for');
    $this
      ->assertRaw($fileName);
    $this
      ->assertRaw('was successfully downloaded.');
  }

  /**
   * Test Smartling provider plugin form validation.
   */
  public function testSmartlingProviderSettingsFormValidation() {

    // Validation with wrong parameters.
    $settings = $this->smartlingPluginProviderSettings;
    $settings['settings[project_id]'] = $this
      ->randomString();
    $settings['settings[key]'] = $this
      ->randomString();
    $translator = $this
      ->setUpSmartlingProviderSettings($settings);
    $supported_remote_languages = $translator
      ->getPlugin()
      ->getSupportedRemoteLanguages($translator);
    $this
      ->assertEqual(0, count($supported_remote_languages));

    // Validation with correct parameters
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $supported_remote_languages = $translator
        ->getPlugin()
        ->getSupportedRemoteLanguages($translator);
      $this
        ->assertNotEqual(0, count($supported_remote_languages));
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test upload and download translation.
   */
  public function testUploadFileAndDownloadTranslation() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->checkGeneratedFile($fileName, $this->testNodeTitle);

      // Check fr node title before translation (should be same as en title).
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertText($this->testNodeTitle);

      // Download translated file.
      $this
        ->downloadAndCheckTranslatedFile($job
        ->id(), $fileName);

      // Check translation.
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertNoText($this->testNodeTitle);
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test manual context sending.
   */
  public function testManualContextSending() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->drupalPostForm('admin/tmgmt/job_items', [
        'action' => 'tmgmt_smartling_send_context',
        'tmgmt_job_item_bulk_form[0]' => 'WyJ1bmQiLCIxIl0=',
      ], t('Apply to selected items'), [
        'query' => [
          'state' => 'All',
          'source_language' => 'All',
          'target_language' => 'All',
        ],
      ]);
      $this
        ->drupalPostForm(NULL, [], t('Send Context to Smartling'));
      $this
        ->drupalGet('admin/reports/dblog');
      $this
        ->assertRaw('We are about to switch user');
      $this
        ->assertRaw('User was successfully switched');
      $this
        ->assertRaw(t('Context upload for file @filename completed successfully.', [
        '@filename' => $fileName,
      ]));
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test context sending by cron.
   */
  public function testContextSendingByCron() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->cronRun();
      $this
        ->drupalGet('admin/reports/dblog');
      $this
        ->assertRaw('We are about to switch user');
      $this
        ->assertRaw('User was successfully switched');
      $this
        ->assertRaw(t('Context upload for file @filename completed successfully.', [
        '@filename' => $fileName,
      ]));
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test Smartling context debugger: show context.
   */
  public function testSmartlingContextDebuggerShowContext() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      global $base_url;
      $this
        ->drupalPostForm('admin/tmgmt/smartling-context-debug', [
        'do_direct_output' => TRUE,
        'url' => $base_url . '/node/' . $this->testNodeId,
      ], t('Test context'));
      $this
        ->assertText($this->testNodeTitle);
      $this
        ->assertText($this->testNodeBody);
      $this
        ->drupalGet('admin/reports/dblog');
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test Smartling context debugger: send context.
   */
  public function testSmartlingContextDebuggerSendContext() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      global $base_url;

      // Workaround: TmgmtSmartlingContextDebugForm::submitForm() uses global
      // config not provider config:
      // \Drupal::config('tmgmt.translator.smartling')->get('settings');
      $this
        ->drupalPostForm('admin/tmgmt/translators/manage/smartling', $this->smartlingPluginProviderSettings, t('Save'));
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->checkGeneratedFile($fileName, $this->testNodeTitle);
      $this
        ->drupalPostForm('admin/tmgmt/smartling-context-debug', [
        'do_direct_output' => FALSE,
        'filename' => $fileName,
        'url' => $base_url . '/node/' . $this->testNodeId,
      ], t('Test context'));
      $this
        ->assertNoText($this->testNodeTitle);
      $this
        ->assertNoText($this->testNodeBody);
      $this
        ->assertText('Smartling response');
      $this
        ->drupalGet('admin/reports/dblog');
      $this
        ->assertRaw(t('Context upload for file @filename completed successfully.', [
        '@filename' => $fileName,
      ]));
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test context uploading with turned off "Silent switching mode" feature.
   */
  public function testSilentSwitchingOff() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->cronRun();
      $this
        ->drupalGet('admin/reports/dblog');
      $this
        ->assertRaw('We are about to switch user');
      $this
        ->assertRaw(t('User @name has logged out.', [
        '@name' => 'Anonymous',
      ]));
      $this
        ->assertRaw(t('User @name has logged in.', [
        '@name' => $this->smartlingPluginProviderSettings['settings[contextUsername]'],
      ]));
      $this
        ->assertRaw('User was successfully switched');
      $this
        ->assertRaw(t('Context upload for file @filename completed successfully.', [
        '@filename' => $fileName,
      ]));
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test context uploading with turned on "Silent switching mode" feature.
   */
  public function testSilentSwitchingOn() {
    if (!empty($this->smartlingPluginProviderSettings)) {

      // Set up silent user switching mode.
      $plugin_settings = $this->smartlingPluginProviderSettings;
      $plugin_settings['settings[context_silent_user_switching]'] = TRUE;
      $translator = $this
        ->setUpSmartlingProviderSettings($plugin_settings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->cronRun();
      $this
        ->drupalGet('admin/reports/dblog');
      $this
        ->assertRaw('We are about to switch user');
      $this
        ->assertNoRaw(t('User @name has logged out.', [
        '@name' => 'Anonymous',
      ]));
      $this
        ->assertNoRaw(t('User @name has logged in.', [
        '@name' => $this->smartlingPluginProviderSettings['settings[contextUsername]'],
      ]));
      $this
        ->assertRaw('User was successfully switched');
      $this
        ->assertRaw(t('Context upload for file @filename completed successfully.', [
        '@filename' => $fileName,
      ]));
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test push back controller.
   */
  public function testPushBackController() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->checkGeneratedFile($fileName, $this->testNodeTitle);

      // Try to push back un-existing job.
      $this
        ->drupalGet("tmgmt-smartling-callback/100500", [
        'query' => [
          'fileUri' => $fileName,
          'locale' => 'fr-FR',
        ],
      ]);
      $this
        ->assertResponse(404);

      // Try to push back existing job without locale and fileUri parameters.
      $this
        ->drupalGet("tmgmt-smartling-callback/{$job->id()}");
      $this
        ->assertResponse(404);

      // Try to push back existing job without locale parameter.
      $this
        ->drupalGet("tmgmt-smartling-callback/{$job->id()}", [
        'query' => [
          'fileUri' => $fileName,
        ],
      ]);
      $this
        ->assertResponse(404);

      // Try to push back existing job without fileUri parameter.
      $this
        ->drupalGet("tmgmt-smartling-callback/{$job->id()}", [
        'query' => [
          'locale' => 'fr-FR',
        ],
      ]);
      $this
        ->assertResponse(404);

      // Check fr node title before translation (should be same as en title).
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertText($this->testNodeTitle);

      // Try to push back existing job.
      $this
        ->drupalGet("tmgmt-smartling-callback/{$job->id()}", [
        'query' => [
          'fileUri' => $fileName,
          'locale' => 'fr-FR',
        ],
      ]);
      $this
        ->assertResponse(200);

      // Check fr node title after translation (should be same as en title).
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertNoText($this->testNodeTitle);
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test uploading/downloading xml file: rely on file name in tmgmt_job.
   */
  public function testUploadXmlChangeToXlfDownloadXml() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $translator = $this
        ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->checkGeneratedFile($fileName, $this->testNodeTitle);

      // Check fr node title before translation (should be same as en title).
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertText($this->testNodeTitle);

      // Change export format to xlf and download translated file.
      $translator
        ->setSetting('export_format', 'xlf');
      $translator
        ->save();
      $this
        ->downloadAndCheckTranslatedFile($job
        ->id(), $fileName);

      // Check translation.
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertNoText($this->testNodeTitle);
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  /**
   * Test uploading/downloading xlf file: rely on file name in tmgmt_job.
   */
  public function testUploadXlfChangeToXmlDownloadXlf() {
    if (!empty($this->smartlingPluginProviderSettings)) {
      $providerSettings = $this->smartlingPluginProviderSettings;
      $providerSettings['settings[export_format]'] = 'xlf';
      $translator = $this
        ->setUpSmartlingProviderSettings($providerSettings);
      $job = $this
        ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
      $fileName = $job
        ->getTranslatorPlugin()
        ->getFileName($job);
      $this
        ->checkGeneratedFile($fileName, $this->testNodeTitle);

      // Check fr node title before translation (should be same as en title).
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertText($this->testNodeTitle);

      // Change export format to xml and download translated file.
      $translator
        ->setSetting('export_format', 'xml');
      $translator
        ->save();
      $this
        ->downloadAndCheckTranslatedFile($job
        ->id(), $fileName);

      // Check translation.
      $this
        ->drupalGet("{$this->targetLanguage}/node/{$this->testNodeId}");
      $this
        ->assertResponse(200);
      $this
        ->assertNoText($this->testNodeTitle);
      $this
        ->deleteTestFile($fileName);
    }
    else {
      $this
        ->fail("Smartling settings file for simpletests not found.");
    }
  }

  // TODO: identical filename task.

  /**
   * Test different file names for different jobs.
   */
  public function testTwoJobsDifferentFileName() {
    $translator = $this
      ->setUpSmartlingProviderSettings($this->smartlingPluginProviderSettings);
    $job = $this
      ->requestTranslationForNode($this->testNodeId, $this->targetLanguage, $translator);
    $fileName = $job
      ->getTranslatorPlugin()
      ->getFileName($job);
    $this
      ->assertEqual($fileName, 'JobID1_en_fr.xml');
    $newJob = $this
      ->requestTranslationForNode($this->testNodeId, 'de', $translator);
    $newFileName = $newJob
      ->getTranslatorPlugin()
      ->getFileName($newJob);
    $this
      ->assertEqual($newFileName, 'JobID2_en_de.xml');
    $this
      ->assertNotEqual($job
      ->id(), $newJob
      ->id());
    $this
      ->assertNotEqual($fileName, $newFileName);
  }

}

Classes

Namesort descending Description
SmartlingTest Basic tests for the Smartling translator.