Newer
Older
<?php
namespace Drupal\filter\Tests;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Unicode;
Alex Pott
committed
use Drupal\filter\Entity\FilterFormat;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\simpletest\WebTestBase;
use Drupal\user\RoleInterface;
Jennifer Hodgdon
committed
/**
* Thoroughly test the administrative interface of the filter module.
*
* @group filter
Jennifer Hodgdon
committed
*/
class FilterAdminTest extends WebTestBase {
Jennifer Hodgdon
committed
/**
Dries Buytaert
committed
* {@inheritdoc}
Jennifer Hodgdon
committed
*/
public static $modules = ['block', 'filter', 'node', 'filter_test_plugin', 'dblog'];
/**
* An user with administration permissions.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* An user with permissions to create pages.
*
* @var \Drupal\user\UserInterface
*/
protected $webUser;
Dries Buytaert
committed
/**
* {@inheritdoc}
*/
Alex Pott
committed
protected function setUp() {
parent::setUp();
Dries Buytaert
committed
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
// Set up the filter formats used by this test.
$basic_html_format = FilterFormat::create(array(
Dries Buytaert
committed
'format' => 'basic_html',
'name' => 'Basic HTML',
'filters' => array(
'filter_html' => array(
'status' => 1,
'settings' => array(
'allowed_html' => '<p> <br> <strong> <a> <em>',
),
),
),
));
$basic_html_format->save();
$restricted_html_format = FilterFormat::create(array(
Dries Buytaert
committed
'format' => 'restricted_html',
'name' => 'Restricted HTML',
'filters' => array(
'filter_html' => array(
'status' => TRUE,
'weight' => -10,
'settings' => array(
'allowed_html' => '<p> <br> <strong> <a> <em> <h4>',
),
),
'filter_autop' => array(
'status' => TRUE,
'weight' => 0,
),
'filter_url' => array(
'status' => TRUE,
'weight' => 0,
),
'filter_htmlcorrector' => array(
'status' => TRUE,
'weight' => 10,
),
),
));
$restricted_html_format->save();
$full_html_format = FilterFormat::create(array(
Dries Buytaert
committed
'format' => 'full_html',
'name' => 'Full HTML',
'weight' => 1,
'filters' => array(),
));
$full_html_format->save();
$this->adminUser = $this->drupalCreateUser(array(
'administer filters',
$basic_html_format->getPermissionName(),
$restricted_html_format->getPermissionName(),
$full_html_format->getPermissionName(),
Alex Pott
committed
'access site reports',
));
$this->webUser = $this->drupalCreateUser(array('create page content', 'edit own page content'));
Dries Buytaert
committed
user_role_grant_permissions('authenticated', array($basic_html_format->getPermissionName()));
user_role_grant_permissions('anonymous', array($restricted_html_format->getPermissionName()));
$this->drupalLogin($this->adminUser);
$this->drupalPlaceBlock('local_actions_block');
Jennifer Hodgdon
committed
/**
* Tests the format administration functionality.
*/
function testFormatAdmin() {
// Add text format.
$this->drupalGet('admin/config/content/formats');
$this->clickLink('Add text format');
$format_id = Unicode::strtolower($this->randomMachineName());
Alex Pott
committed
$name = $this->randomMachineName();
$edit = array(
'format' => $format_id,
'name' => $name,
);
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
// Verify default weight of the text format.
$this->drupalGet('admin/config/content/formats');
Jennifer Hodgdon
committed
$this->assertFieldByName("formats[$format_id][weight]", 0, 'Text format weight was saved.');
// Change the weight of the text format.
$edit = array(
"formats[$format_id][weight]" => 5,
);
$this->drupalPostForm('admin/config/content/formats', $edit, t('Save'));
Jennifer Hodgdon
committed
$this->assertFieldByName("formats[$format_id][weight]", 5, 'Text format weight was saved.');
// Edit text format.
$this->drupalGet('admin/config/content/formats');
Alex Pott
committed
// Cannot use the assertNoLinkByHref method as it does partial url matching
// and 'admin/config/content/formats/manage/' . $format_id . '/disable'
// exists.
// @todo: See https://www.drupal.org/node/2031223 for the above.
Alex Pott
committed
$edit_link = $this->xpath('//a[@href=:href]', array(
Angie Byron
committed
':href' => \Drupal::url('entity.filter_format.edit_form', ['filter_format' => $format_id])
Alex Pott
committed
));
$this->assertTrue($edit_link, format_string('Link href %href found.',
array('%href' => 'admin/config/content/formats/manage/' . $format_id)
));
$this->drupalGet('admin/config/content/formats/manage/' . $format_id);
$this->drupalPostForm(NULL, array(), t('Save configuration'));
// Verify that the custom weight of the text format has been retained.
$this->drupalGet('admin/config/content/formats');
Jennifer Hodgdon
committed
$this->assertFieldByName("formats[$format_id][weight]", 5, 'Text format weight was retained.');
// Disable text format.
$this->assertLinkByHref('admin/config/content/formats/manage/' . $format_id . '/disable');
$this->drupalGet('admin/config/content/formats/manage/' . $format_id . '/disable');
$this->drupalPostForm(NULL, array(), t('Disable'));
// Verify that disabled text format no longer exists.
$this->drupalGet('admin/config/content/formats/manage/' . $format_id);
Jennifer Hodgdon
committed
$this->assertResponse(404, 'Disabled text format no longer exists.');
// Attempt to create a format of the same machine name as the disabled
// format but with a different human readable name.
$edit = array(
'format' => $format_id,
'name' => 'New format',
);
$this->drupalPostForm('admin/config/content/formats/add', $edit, t('Save configuration'));
$this->assertText('The machine-readable name is already in use. It must be unique.');
// Attempt to create a format of the same human readable name as the
// disabled format but with a different machine name.
$edit = array(
'format' => 'new_format',
'name' => $name,
);
$this->drupalPostForm('admin/config/content/formats/add', $edit, t('Save configuration'));
$this->assertRaw(t('Text format names must be unique. A format named %name already exists.', array(
'%name' => $name,
)));
}
/**
Jennifer Hodgdon
committed
* Tests filter administration functionality.
*/
function testFilterAdmin() {
$first_filter = 'filter_autop';
$second_filter = 'filter_url';
Angie Byron
committed
$basic = 'basic_html';
$restricted = 'restricted_html';
$full = 'full_html';
$plain = 'plain_text';
// Check that the fallback format exists and cannot be disabled.
Jennifer Hodgdon
committed
$this->assertTrue($plain == filter_fallback_format(), 'The fallback format is set to plain text.');
$this->drupalGet('admin/config/content/formats');
$this->assertNoRaw('admin/config/content/formats/manage/' . $plain . '/disable', 'Disable link for the fallback format not found.');
$this->drupalGet('admin/config/content/formats/manage/' . $plain . '/disable');
Jennifer Hodgdon
committed
$this->assertResponse(403, 'The fallback format cannot be disabled.');
// Verify access permissions to Full HTML format.
$full_format = FilterFormat::load($full);
$this->assertTrue($full_format->access('use', $this->adminUser), 'Admin user may use Full HTML.');
$this->assertFalse($full_format->access('use', $this->webUser), 'Web user may not use Full HTML.');
// Add an additional tag.
$edit = array();
$edit['filters[filter_html][settings][allowed_html]'] = '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <quote>';
$this->drupalPostForm('admin/config/content/formats/manage/' . $restricted, $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
$this->drupalGet('admin/config/content/formats/manage/' . $restricted);
Jennifer Hodgdon
committed
$this->assertFieldByName('filters[filter_html][settings][allowed_html]', $edit['filters[filter_html][settings][allowed_html]'], 'Allowed HTML tag added.');
$elements = $this->xpath('//select[@name=:first]/following::select[@name=:second]', array(
':first' => 'filters[' . $first_filter . '][weight]',
':second' => 'filters[' . $second_filter . '][weight]',
));
Jennifer Hodgdon
committed
$this->assertTrue(!empty($elements), 'Order confirmed in admin interface.');
// Reorder filters.
$edit = array();
$edit['filters[' . $second_filter . '][weight]'] = 1;
$edit['filters[' . $first_filter . '][weight]'] = 2;
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
$this->drupalGet('admin/config/content/formats/manage/' . $restricted);
Jennifer Hodgdon
committed
$this->assertFieldByName('filters[' . $second_filter . '][weight]', 1, 'Order saved successfully.');
$this->assertFieldByName('filters[' . $first_filter . '][weight]', 2, 'Order saved successfully.');
$elements = $this->xpath('//select[@name=:first]/following::select[@name=:second]', array(
':first' => 'filters[' . $second_filter . '][weight]',
':second' => 'filters[' . $first_filter . '][weight]',
));
Jennifer Hodgdon
committed
$this->assertTrue(!empty($elements), 'Reorder confirmed in admin interface.');
$filter_format = FilterFormat::load($restricted);
foreach ($filter_format->filters() as $filter_name => $filter) {
Angie Byron
committed
if ($filter_name == $second_filter || $filter_name == $first_filter) {
$filters[] = $filter_name;
}
}
// Ensure that the second filter is now before the first filter.
$this->assertEqual($filter_format->filters($second_filter)->weight + 1, $filter_format->filters($first_filter)->weight, 'Order confirmed in configuration.');
// Add format.
$edit = array();
$edit['format'] = Unicode::strtolower($this->randomMachineName());
Alex Pott
committed
$edit['name'] = $this->randomMachineName();
$edit['roles[' . RoleInterface::AUTHENTICATED_ID . ']'] = 1;
$edit['filters[' . $second_filter . '][status]'] = TRUE;
$edit['filters[' . $first_filter . '][status]'] = TRUE;
$this->drupalPostForm('admin/config/content/formats/add', $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
Jennifer Hodgdon
committed
$this->assertRaw(t('Added text format %format.', array('%format' => $edit['name'])), 'New filter created.');
filter_formats_reset();
$format = FilterFormat::load($edit['format']);
Jennifer Hodgdon
committed
$this->assertNotNull($format, 'Format found in database.');
$this->drupalGet('admin/config/content/formats/manage/' . $format->id());
$this->assertFieldByName('roles[' . RoleInterface::AUTHENTICATED_ID . ']', '', 'Role found.');
Jennifer Hodgdon
committed
$this->assertFieldByName('filters[' . $second_filter . '][status]', '', 'Line break filter found.');
catch
committed
$this->assertFieldByName('filters[' . $first_filter . '][status]', '', 'URL filter found.');
// Disable new filter.
$this->drupalPostForm('admin/config/content/formats/manage/' . $format->id() . '/disable', array(), t('Disable'));
$this->assertUrl('admin/config/content/formats');
Jennifer Hodgdon
committed
$this->assertRaw(t('Disabled text format %format.', array('%format' => $edit['name'])), 'Format successfully disabled.');
// Allow authenticated users on full HTML.
$format = FilterFormat::load($full);
$edit = array();
$edit['roles[' . RoleInterface::ANONYMOUS_ID . ']'] = 0;
$edit['roles[' . RoleInterface::AUTHENTICATED_ID . ']'] = 1;
$this->drupalPostForm('admin/config/content/formats/manage/' . $full, $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
$this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->label())), 'Full HTML format successfully updated.');
// Switch user.
$this->drupalLogin($this->webUser);
$this->drupalGet('node/add/page');
Jennifer Hodgdon
committed
$this->assertRaw('<option value="' . $full . '">Full HTML</option>', 'Full HTML filter accessible.');
Angie Byron
committed
// Use basic HTML and see if it removes tags that are not allowed.
Alex Pott
committed
$body = '<em>' . $this->randomMachineName() . '</em>';
$extra_text = 'text';
$text = $body . '<random>' . $extra_text . '</random>';
$edit = array();
Alex Pott
committed
$edit['title[0][value]'] = $this->randomMachineName();
Angie Byron
committed
$edit['body[0][value]'] = $text;
$edit['body[0][format]'] = $basic;
$this->drupalPostForm('node/add/page', $edit, t('Save'));
$this->assertText(t('Basic page @title has been created.', array('@title' => $edit['title[0][value]'])), 'Filtered node created.');
// Verify that the creation message contains a link to a node.
$view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', array(':href' => 'node/'));
$this->assert(isset($view_link), 'The message area contains a link to a node');
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
Jennifer Hodgdon
committed
$this->assertTrue($node, 'Node found in database.');
$this->drupalGet('node/' . $node->id());
Jennifer Hodgdon
committed
$this->assertRaw($body . $extra_text, 'Filter removed invalid tag.');
// Use plain text and see if it escapes all tags, whether allowed or not.
Angie Byron
committed
// In order to test plain text, we have to enable the hidden variable for
// "show_fallback_format", which displays plain text in the format list.
$this->config('filter.settings')
Angie Byron
committed
->set('always_show_fallback_choice', TRUE)
->save();
$edit = array();
Angie Byron
committed
$edit['body[0][format]'] = $plain;
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
$this->drupalGet('node/' . $node->id());
$this->assertEscaped($text, 'The "Plain text" text format escapes all HTML tags.');
$this->config('filter.settings')
Angie Byron
committed
->set('always_show_fallback_choice', FALSE)
->save();
// Switch user.
$this->drupalLogin($this->adminUser);
// Clean up.
// Allowed tags.
$edit = array();
$edit['filters[filter_html][settings][allowed_html]'] = '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>';
$this->drupalPostForm('admin/config/content/formats/manage/' . $basic, $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
$this->drupalGet('admin/config/content/formats/manage/' . $basic);
Jennifer Hodgdon
committed
$this->assertFieldByName('filters[filter_html][settings][allowed_html]', $edit['filters[filter_html][settings][allowed_html]'], 'Changes reverted.');
// Full HTML.
$edit = array();
$edit['roles[' . RoleInterface::AUTHENTICATED_ID . ']'] = FALSE;
$this->drupalPostForm('admin/config/content/formats/manage/' . $full, $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
$this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->label())), 'Full HTML format successfully reverted.');
$this->drupalGet('admin/config/content/formats/manage/' . $full);
$this->assertFieldByName('roles[' . RoleInterface::AUTHENTICATED_ID . ']', $edit['roles[' . RoleInterface::AUTHENTICATED_ID . ']'], 'Changes reverted.');
// Filter order.
$edit = array();
$edit['filters[' . $second_filter . '][weight]'] = 2;
$edit['filters[' . $first_filter . '][weight]'] = 1;
$this->drupalPostForm('admin/config/content/formats/manage/' . $basic, $edit, t('Save configuration'));
$this->assertUrl('admin/config/content/formats');
$this->drupalGet('admin/config/content/formats/manage/' . $basic);
Jennifer Hodgdon
committed
$this->assertFieldByName('filters[' . $second_filter . '][weight]', $edit['filters[' . $second_filter . '][weight]'], 'Changes reverted.');
$this->assertFieldByName('filters[' . $first_filter . '][weight]', $edit['filters[' . $first_filter . '][weight]'], 'Changes reverted.');
}
/**
* Tests the URL filter settings form is properly validated.
*/
function testUrlFilterAdmin() {
// The form does not save with an invalid filter URL length.
$edit = array(
Alex Pott
committed
'filters[filter_url][settings][filter_url_length]' => $this->randomMachineName(4),
$this->drupalPostForm('admin/config/content/formats/manage/basic_html', $edit, t('Save configuration'));
Angie Byron
committed
$this->assertNoRaw(t('The text format %format has been updated.', array('%format' => 'Basic HTML')));
Alex Pott
committed
/**
* Tests whether filter tips page is not HTML escaped.
*/
function testFilterTipHtmlEscape() {
$this->drupalLogin($this->adminUser);
global $base_url;
$site_name_with_markup = 'Filter test <script>alert(\'here\');</script> site name';
$this->config('system.site')->set('name', $site_name_with_markup)->save();
Alex Pott
committed
// It is not possible to test the whole filter tip page.
// Therefore we test only some parts.
$link = '<a href="' . $base_url . '">' . Html::escape($site_name_with_markup) . '</a>';
Alex Pott
committed
$ampersand = '&';
$link_as_code = '<code>' . Html::escape($link) . '</code>';
$ampersand_as_code = '<code>' . Html::escape($ampersand) . '</code>';
Alex Pott
committed
$this->drupalGet('filter/tips');
$this->assertRaw('<td class="type">' . $link_as_code . '</td>');
$this->assertRaw('<td class="get">' . $link . '</td>');
$this->assertRaw('<td class="type">' . $ampersand_as_code . '</td>');
$this->assertRaw('<td class="get">' . $ampersand . '</td>');
}
Alex Pott
committed
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
/**
* Tests whether a field using a disabled format is rendered.
*/
public function testDisabledFormat() {
// Create a node type and add a standard body field.
$node_type = NodeType::create(['type' => Unicode::strtolower($this->randomMachineName())]);
$node_type->save();
node_add_body_field($node_type, $this->randomString());
// Create a text format with a filter that returns a static string.
$format = FilterFormat::create([
'name' => $this->randomString(),
'format' => $format_id = Unicode::strtolower($this->randomMachineName()),
]);
$format->setFilterConfig('filter_static_text', ['status' => TRUE]);
$format->save();
// Create a new node of the new node type.
$node = Node::create([
'type' => $node_type->id(),
'title' => $this->randomString(),
]);
$body_value = $this->randomString();
$node->body->value = $body_value;
$node->body->format = $format_id;
$node->save();
// The format is used and we should see the static text instead of the body
// value.
$this->drupalGet($node->urlInfo());
$this->assertText('filtered text');
// Disable the format.
$format->disable()->save();
$this->drupalGet($node->urlInfo());
// The format is not used anymore.
$this->assertNoText('filtered text');
// The text is not displayed unfiltered or escaped.
$this->assertNoRaw($body_value);
$this->assertNoEscaped($body_value);
// Visit the dblog report page.
$this->drupalLogin($this->adminUser);
$this->drupalGet('admin/reports/dblog');
// The correct message has been logged.
$this->assertRaw(sprintf('Disabled text format: %s.', $format_id));
// Programmatically change the text format to something random so we trigger
// the missing text format message.
$format_id = $this->randomMachineName();
$node->body->format = $format_id;
$node->save();
$this->drupalGet($node->urlInfo());
// The text is not displayed unfiltered or escaped.
$this->assertNoRaw($body_value);
$this->assertNoEscaped($body_value);
// Visit the dblog report page.
$this->drupalGet('admin/reports/dblog');
// The missing text format message has been logged.
$this->assertRaw(sprintf('Missing text format: %s.', $format_id));
}