drupalLogin($this->adminUser);
// Index the content.
\Drupal::service('plugin.manager.search')
->createInstance('node_search')
->updateIndex();
search_update_totals();
// Make absolutely sure the ::$blocks variable doesn't pass information
// along between tests.
$this->blocks = [];
}
/**
* Tests various operations via the Facets' admin UI.
*/
public function testFramework() {
$facet_id = 'test_facet_name';
$facet_name = 'Test Facet Name';
// Check if the overview is empty.
$this->checkEmptyOverview();
// Add a new facet and edit it.
$this->addFacet($facet_id, $facet_name);
// Create and place a block for "Test Facet name" facet.
$this->blocks[$facet_id] = $this->createBlock($facet_id);
// Verify that the facet results are correct.
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertLink('page');
$this->assertLink('article');
// Verify that facet blocks appear as expected.
$this->assertFacetBlocksAppear();
$this->setShowAmountOfResults($facet_id, TRUE);
// Verify that the number of results per item.
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertRaw('page (19)');
$this->assertRaw('article (10)');
// Verify that the label is correct for a clicked link.
$this->clickLinkPartialName('page');
$this->assertRaw('(-) page (19)');
// To make sure we have an empty result, we truncate the search_index table
// because, for the moment, we don't have the possibility to clear the index
// from the API.
// @see https://www.drupal.org/node/326062
\Drupal::database()->truncate('search_index')->execute();
// Verify that no facet blocks appear. Empty behavior "None" is selected by
// default.
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertNoFacetBlocksAppear();
// Verify that the "empty_text" appears as expected.
$this->setEmptyBehaviorFacetText($facet_name);
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertRaw('block-test-facet-name');
$this->assertRaw('No results found for this block!');
// Delete the block.
$this->deleteBlock($facet_id);
// Delete the facet and make sure the overview is empty again.
$this->deleteUnusedFacet($facet_id, $facet_name);
$this->checkEmptyOverview();
}
/**
* Tests the "Post date" facets.
*/
public function testPostDate() {
$facet_name = 'Tardigrade';
$facet_id = 'tardigrade';
$this->addFacet($facet_id, $facet_name, 'created');
$this->blocks[$facet_id] = $this->createBlock($facet_id);
$this->setShowAmountOfResults($facet_id, TRUE);
// Assert date facets.
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertRaw('February 2016 (9)');
$this->assertRaw('March 2016 (10)');
$this->assertRaw('April 2016 (10)');
$this->assertResponse(200);
$this->clickLinkPartialName('March 2016');
$this->assertResponse(200);
$this->assertRaw('March 8, 2016 (1)');
$this->assertRaw('March 9, 2016 (2)');
$this->clickLinkPartialName('March 9');
$this->assertResponse(200);
$this->assertRaw('10 AM (1)');
$this->assertRaw('12 PM (1)');
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertRaw('April 2016 (10)');
$this->clickLinkPartialName('April 2016');
$this->assertResponse(200);
$this->assertRaw('April 1, 2016 (1)');
$this->assertRaw('April 2, 2016 (1)');
}
/**
* Tests the "Updated date" facets.
*/
public function testUpdatedDate() {
$facet_name = 'Tardigrade';
$facet_id = 'tardigrade';
$this->addFacet($facet_id, $facet_name, 'changed');
$this->blocks[$facet_id] = $this->createBlock($facet_id);
$this->setShowAmountOfResults($facet_id, TRUE);
// Update the changed date. The nodes were created on February/March 2016
// and the changed date is December 2016.
$node = Node::load(1);
$changed_date = new \DateTime('December 3 2016 1PM');
$node->changed = $changed_date->format('U');
$node->save();
// Index the content.
\Drupal::service('plugin.manager.search')
->createInstance('node_search')
->updateIndex();
search_update_totals();
$this->drupalGet('search/node', ['query' => ['keys' => 'test']]);
$this->assertRaw('December 2016 (1)');
$this->clickLinkPartialName('December 2016');
$this->assertResponse(200);
$this->assertRaw('December 3, 2016 (1)');
$this->clickLinkPartialName('December 3, 2016');
$this->assertResponse(200);
}
/**
* Tests for CRUD operations in the admin UI.
*/
public function testCrudFacet() {
$facet_name = "Test Facet name";
$facet_id = 'test_facet_name';
$this->checkEmptyOverview();
$this->addFacetCheck($facet_id, $facet_name, 'type');
$this->editFacetCheck($facet_id, $facet_name);
$this->blocks[$facet_id] = $this->createBlock($facet_id);
$this->deleteBlock($facet_id);
$this->deleteUnusedFacet($facet_id, $facet_name);
}
/**
* Creates a new facet.
*
* @param string $id
* The facet's id.
* @param string $name
* The facet's name.
* @param string $type
* The field type.
*/
protected function addFacet($id, $name, $type = 'type') {
$this->drupalGet('admin/config/search/facets/add-facet');
$form_values = [
'id' => $id,
'status' => 1,
'name' => $name,
'facet_source_id' => 'core_node_search:node_search',
'facet_source_configs[core_node_search:node_search][field_identifier]' => $type,
];
$this->drupalPostForm(NULL, ['facet_source_id' => 'core_node_search:node_search'], $this->t('Configure facet source'));
$this->drupalPostForm(NULL, $form_values, $this->t('Save'));
}
/**
* Configures the possibility to show the amount of results for facet items.
*
* @param string $facet_id
* The id of the facet.
* @param bool|TRUE $show
* Boolean to determine if we want to show the amount of results.
*/
protected function setShowAmountOfResults($facet_id, $show = TRUE) {
$facet_edit_page = '/admin/config/search/facets/' . $facet_id . '/edit';
$this->drupalGet($facet_edit_page);
$this->assertResponse(200);
$edit = [
'widget_configs[show_numbers]' => $show,
];
$this->drupalPostForm(NULL, $edit, $this->t('Save'));
}
/**
* Configures empty behavior option to show a text on empty results.
*
* @param string $facet_name
* The name of the facet.
*/
protected function setEmptyBehaviorFacetText($facet_name) {
$facet_id = $this->convertNameToMachineName($facet_name);
$facet_edit_page = '/admin/config/search/facets/' . $facet_id . '/edit';
// Go to the facet edit page and make sure "edit facet %facet" is present.
$this->drupalGet($facet_edit_page);
$this->assertResponse(200);
// Configure the text for empty results behavior.
$edit = [
'facet_settings[empty_behavior]' => 'text',
'facet_settings[empty_behavior_container][empty_behavior_text][value]' => 'No results found for this block!',
];
$this->drupalPostForm(NULL, $edit, $this->t('Save'));
}
/**
* Configures a facet to only be visible when accessing to the facet source.
*
* @param string $facet_name
* The name of the facet.
*/
protected function setOptionShowOnlyWhenFacetSourceVisible($facet_name) {
$facet_id = $this->convertNameToMachineName($facet_name);
$facet_edit_page = '/admin/config/search/facets/' . $facet_id . '/edit';
$this->drupalGet($facet_edit_page);
$this->assertResponse(200);
$edit = [
'facet_settings[only_visible_when_facet_source_is_visible]' => TRUE,
'widget' => 'links',
'widget_configs[show_numbers]' => '0',
];
$this->drupalPostForm(NULL, $edit, $this->t('Save'));
}
/**
* Get the facet overview page and make sure the overview is empty.
*/
protected function checkEmptyOverview() {
$facet_overview = '/admin/config/search/facets';
$this->drupalGet($facet_overview);
$this->assertResponse(200);
// The list overview has Field: field_name as description. This tests on the
// absence of that.
$this->assertNoText('Field:');
}
/**
* Tests adding a facet trough the interface.
*
* @param string $facet_id
* The id of the facet.
* @param string $facet_name
* The name of the facet.
* @param string $type
* The field type.
*/
protected function addFacetCheck($facet_id, $facet_name, $type) {
// Go to the Add facet page and make sure that returns a 200.
$facet_add_page = '/admin/config/search/facets/add-facet';
$this->drupalGet($facet_add_page);
$this->assertResponse(200);
$form_values = [
'name' => '',
'id' => $facet_id,
'status' => 1,
];
// Try filling out the form, but without having filled in a name for the
// facet to test for form errors.
$this->drupalPostForm($facet_add_page, $form_values, $this->t('Save'));
$this->assertText($this->t('Name field is required.'));
$this->assertText($this->t('Facet source field is required.'));
// Make sure that when filling out the name, the form error disappears.
$form_values['name'] = $facet_name;
$this->drupalPostForm(NULL, $form_values, $this->t('Save'));
$this->assertNoText($this->t('Facet name field is required.'));
// Configure the facet source by selecting one of the Search API views.
$this->drupalGet($facet_add_page);
$this->drupalPostForm(NULL, ['facet_source_id' => 'core_node_search:node_search'], $this->t('Configure facet source'));
// The facet field is still required.
$this->drupalPostForm(NULL, $form_values, $this->t('Save'));
$this->assertText($this->t('Field field is required.'));
// Fill in all fields and make sure the 'field is required' message is no
// longer shown.
$facet_source_form = [
'facet_source_configs[core_node_search:node_search][field_identifier]' => $type,
];
$this->drupalPostForm(NULL, $form_values + $facet_source_form, $this->t('Save'));
$this->assertNoText('field is required.');
// Make sure that the redirection to the display page is correct.
$this->assertRaw(t('Facet %name has been created.', ['%name' => $facet_name]));
$this->assertUrl('admin/config/search/facets/' . $facet_id . '/edit');
$this->drupalGet('admin/config/search/facets');
}
/**
* Tests editing of a facet through the UI.
*
* @param string $facet_id
* The id of the facet.
* @param string $facet_name
* The name of the facet.
*/
protected function editFacetCheck($facet_id, $facet_name) {
$facet_edit_page = '/admin/config/search/facets/' . $facet_id . '/settings';
// Go to the facet edit page and make sure "edit facet %facet" is present.
$this->drupalGet($facet_edit_page);
$this->assertResponse(200);
$this->assertRaw($this->t('Facet settings for @facet facet', ['@facet' => $facet_name]));
// Change the facet name to add in "-2" to test editing of a facet works.
$form_values = ['name' => $facet_name . ' - 2'];
$this->drupalPostForm($facet_edit_page, $form_values, $this->t('Save'));
// Make sure that the redirection back to the overview was successful and
// the edited facet is shown on the overview page.
$this->assertRaw(t('Facet %name has been updated.', ['%name' => $facet_name . ' - 2']));
// Make sure the "-2" suffix is still on the facet when editing a facet.
$this->drupalGet($facet_edit_page);
$this->assertRaw($this->t('Facet settings for @facet facet', ['@facet' => $facet_name . ' - 2']));
// Edit the form and change the facet's name back to the initial name.
$form_values = ['name' => $facet_name];
$this->drupalPostForm($facet_edit_page, $form_values, $this->t('Save'));
// Make sure that the redirection back to the overview was successful and
// the edited facet is shown on the overview page.
$this->assertRaw(t('Facet %name has been updated.', ['%name' => $facet_name]));
}
/**
* This deletes an unused facet through the UI.
*
* @param string $facet_name
* The name of the facet.
*/
protected function deleteUsedFacet($facet_name) {
$facet_id = $this->convertNameToMachineName($facet_name);
$facet_delete_page = '/admin/config/search/facets/' . $facet_id . '/delete';
// Go to the facet delete page and make the warning is shown.
$this->drupalGet($facet_delete_page);
$this->assertResponse(200);
// Check that the facet by testing for the message and the absence of the
// facet name on the overview.
$this->assertRaw($this->t("The facet is currently used in a block and thus can't be removed. Remove the block first."));
}
/**
* This deletes a facet through the UI.
*
* @param string $facet_id
* The id of the facet.
* @param string $facet_name
* The name of the facet.
*/
protected function deleteUnusedFacet($facet_id, $facet_name) {
$facet_delete_page = '/admin/config/search/facets/' . $facet_id . '/delete';
// Go to the facet delete page and make the warning is shown.
$this->drupalGet($facet_delete_page);
$this->assertResponse(200);
$this->assertText($this->t('This action cannot be undone'));
// Actually submit the confirmation form.
$this->drupalPostForm(NULL, [], $this->t('Delete'));
// Check that the facet by testing for the message and the absence of the
// facet name on the overview.
$this->assertRaw($this->t('The facet %facet has been deleted.', ['%facet' => $facet_name]));
// Refresh the page because on the previous page the $facet_name is still
// visible (in the message).
$facet_overview = '/admin/config/search/facets';
$this->drupalGet($facet_overview);
$this->assertResponse(200);
$this->assertNoText($facet_name);
}
/**
* Convert facet name to machine name.
*
* @param string $facet_name
* The name of the facet.
*
* @return string
* The facet name changed to a machine name.
*/
protected function convertNameToMachineName($facet_name) {
return preg_replace('@[^a-zA-Z0-9_]+@', '_', strtolower($facet_name));
}
/**
* Go to the Delete Facet Page using the facet name.
*
* @param string $facet_name
* The name of the facet.
*/
protected function goToDeleteFacetPage($facet_name) {
$facet_id = $this->convertNameToMachineName($facet_name);
$facet_delete_page = '/admin/config/search/facets/' . $facet_id . '/delete';
// Go to the facet delete page and make the warning is shown.
$this->drupalGet($facet_delete_page);
$this->assertResponse(200);
}
}