Forked from
project / project_browser
177 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ProjectBrowserUiTestJsonApi.php 27.30 KiB
<?php
declare(strict_types=1);
namespace Drupal\Tests\project_browser\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
// cspell:ignore Blazy Cardless Colorbox Сontact ctools Fivestar Flipbook
// cspell:ignore Fontawesome Iconpicker IMCE Micon Plupload Statusactive
// cspell:ignore Statusmaintained Tagify Webform Zotero Zurb ZURB
/**
* ProjectBrowserUITest refactored to use the Drupal.org JSON API endpoint.
*
* @group project_browser
*/
class ProjectBrowserUiTestJsonApi extends WebDriverTestBase {
use ProjectBrowserUiTestTrait;
// Could be moved into trait under PHP 8.3.
protected const SECURITY_OPTION_SELECTOR = 'select[name="securityCoverage"] ';
protected const MAINTENANCE_OPTION_SELECTOR = 'select[name="maintenanceStatus"] ';
protected const DEVELOPMENT_OPTION_SELECTOR = 'select[name="developmentStatus"] ';
protected const OPTION_CHECKED = 'option:checked';
protected const OPTION_FIRST_CHILD = 'option:first-child';
protected const OPTION_LAST_CHILD = 'option:last-child';
/**
* {@inheritdoc}
*/
protected static $modules = [
'project_browser',
'project_browser_test',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->config('project_browser.admin_settings')->set('enabled_sources', ['drupalorg_jsonapi'])->save(TRUE);
$this->drupalLogin($this->drupalCreateUser([
'administer modules',
'administer site configuration',
]));
}
/**
* Tests the grid view.
*/
public function testGrid(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->getSession()->resizeWindow(1250, 1000);
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-project.pb-project--grid');
$assert_session->waitForElementVisible('css', '#project-browser .pb-display__button[value="Grid"]');
$grid_text = $this->getElementText('#project-browser .pb-display__button[value="Grid"]');
$this->assertEquals('Grid', $grid_text);
$this->assertTrue($assert_session->waitForText('Results'));
$assert_session->pageTextNotContains('No records available');
$page->pressButton('List');
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--list'));
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 12);
$page->pressButton('Grid');
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--grid'));
$this->getSession()->resizeWindow(1100, 1000);
$assert_session->assertNoElementAfterWait('css', '.toggle.list-button');
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--list'));
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 12);
$this->getSession()->resizeWindow(1210, 1210);
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--grid'));
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--grid', 12);
}
/**
* Tests the available categories.
*/
public function testCategories(): void {
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown input[type="checkbox"]');
$assert_session->elementsCount('css', '.pb-filter__multi-dropdown input[type="checkbox"]', 54);
}
/**
* Tests the clickable category functionality.
*/
public function testClickableCategory(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Token');
$page->clickLink('Token');
}
/**
* Tests category filtering.
*/
public function testCategoryFiltering(): void {
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown');
// Initial results count on page load.
$this->assertTrue($assert_session->waitForText('4,523 Results'));
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);
$this->svelteInitHelper('css', '#acc38507-ac85-43e6-8f32-beb3febea93f');
// Click 'E-commerce' checkbox.
$this->clickWithWait('#acc38507-ac85-43e6-8f32-beb3febea93f');
// Use blur event to close drop-down so Clear is visible.
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();
$module_category_e_commerce_filter_selector = 'p.filter-applied:nth-child(1)';
// Make sure the 'E-commerce' module category filter is applied.
$this->assertEquals('E-commerce', $this->getElementText("$module_category_e_commerce_filter_selector .filter-applied__label"));
// This call has the second argument, `$reload`, set to TRUE due to it
// failing on ~2% of GitLabCI test runs. It is not entirely clear why this
// specific call intermittently fails while others do not. It's known the
// Svelte app has occasional initialization problems on GitLabCI that are
// reliably fixed by a page reload, so we allow that here to prevent random
// failures that are not representative of real world use.
$this->assertProjectsVisible([
'Commerce Core', 'AddToAny Share Buttons', 'Fivestar', 'Commerce Shipping', 'Physical Fields', 'Commerce Stock', 'Entity Registration', 'Commerce Feeds', 'Currency', 'Commerce Migrate', 'Payment', 'Commerce Stripe',
], TRUE);
// Clear the checkbox to verify the results revert to their initial state.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);
$this->svelteInitHelper('css', '#acc38507-ac85-43e6-8f32-beb3febea93f');
$this->clickWithWait('#acc38507-ac85-43e6-8f32-beb3febea93f', '4,523 Results');
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();
$this->pressWithWait('Clear filters', '7,236 Results');
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);
// Click 'Media' checkbox.
$this->clickWithWait('#ee0200ec-4920-411e-9768-2cc588deaa38');
// Click 'Commerce/Advertising' checkbox.
$this->clickWithWait('#23d470f6-ffde-4034-a6ef-492b7121b9cf');
// Make sure the 'Media' module category filter is applied.
$this->assertEquals('Media', $this->getElementText('p.filter-applied:nth-child(2) .filter-applied__label'));
// Assert that only media and administration module categories are shown.
$this->assertProjectsVisible([
'IMCE', 'CKEditor - WYSIWYG HTML editor', 'Video Embed Field', 'Flex Slider', 'Entity Browser', 'Crop API', 'Embed', 'Entity Embed', 'Plupload integration', 'Slick Carousel', 'Focal Point', 'Blazy',
]);
$this->assertTrue($assert_session->waitForText('828 Results'));
}
/**
* Tests the Target blank functionality.
*/
public function testTargetBlank(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Token');
$page->clickLink('Token');
}
/**
* Tests paging through results.
*/
public function testPaging(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', '4,523 Results');
$this->assertProjectsVisible([
'Chaos Tool Suite (ctools)', 'Token', 'Pathauto', 'Libraries API', 'Entity API', 'Webform', 'Metatag', 'Field Group', 'IMCE', 'CAPTCHA', 'Google Analytics', 'Redirect',
]);
$this->assertPagerItems(['1', '2', '3', '4', '5', '…', 'Next', 'Last']);
$page->pressButton('Clear filters');
$this->assertTrue($assert_session->waitForText('7,236 Results'));
$this->assertProjectsVisible([
'Chaos Tool Suite (ctools)', 'Token', 'Pathauto', 'Libraries API', 'Entity API', 'Webform', 'Metatag', 'Field Group', 'IMCE', 'CAPTCHA', 'Google Analytics', 'Redirect',
]);
$this->assertPagerItems(['1', '2', '3', '4', '5', '…', 'Next', 'Last']);
$assert_session->elementExists('css', '.pager__item--active > .is-active[aria-label="Page 1"]');
$this->clickWithWait('[aria-label="Next page"]');
$this->assertProjectsVisible([
'Module Filter', 'CKEditor - WYSIWYG HTML editor', 'Admin Toolbar', 'Views Bulk Operations (VBO)', 'Colorbox', 'XML sitemap', 'Features', 'Backup and Migrate', 'Devel', 'Rules', 'Paragraphs', 'Mail System',
]);
$this->assertPagerItems(['First', 'Previous', '1', '2', '3', '4', '5', '6', '…', 'Next', 'Last']);
$this->clickWithWait('[aria-label="Next page"]');
$this->assertProjectsVisible([
'Menu Block', 'Entity Reference Revisions', 'reCAPTCHA', 'Better Exposed Filters', 'File Entity (fieldable files)', 'Panels', 'Views Slideshow', 'Block Class', 'Inline Entity Form', 'Honeypot', 'SMTP Authentication Support', 'Search API',
]);
$this->assertPagerItems(['First', 'Previous', '1', '2', '3', '4', '5', '6', '7', '…', 'Next', 'Last']);
// Ensure that when the number of projects is even divisible by the number
// shown on a page, the pager has the correct number of items.
$this->clickWithWait('[aria-label="First page"]');
// Open category drop-down.
$assert_session->elementExists('css', '.pb-filter__multi-dropdown')->click();
// Click 'Commerce/Advertising' checkbox.
$this->clickWithWait('#23d470f6-ffde-4034-a6ef-492b7121b9cf', '', TRUE);
// Click 'E-commerce' checkbox.
$this->clickWithWait('#acc38507-ac85-43e6-8f32-beb3febea93f', bypass_wait: TRUE);
// Click 'Utility' checkbox.
$this->clickWithWait('#fddb4569-cb89-42f5-8699-182b10234dfa', '1,630 Results', TRUE);
$this->assertPagerItems(['1', '2', '3', '4', '5', '…', 'Next', 'Last']);
}
/**
* Tests advanced filtering.
*/
public function testAdvancedFiltering(): void {
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Token');
$this->pressWithWait('Clear filters');
$this->pressWithWait('Recommended filters');
$this->assertProjectsVisible([
'Chaos Tool Suite (ctools)', 'Token', 'Pathauto', 'Libraries API', 'Entity API', 'Webform', 'Metatag', 'Field Group', 'IMCE', 'CAPTCHA', 'Google Analytics', 'Redirect',
]);
// Make sure the second filter applied is the security covered filter.
$option = $assert_session->optionExists('securityCoverage', '1');
$this->assertSame('Show projects covered by a security policy', $option->getText());
$this->assertTrue($option->isSelected());
// Clear the security covered filter.
$this->clickWithWait(self::SECURITY_OPTION_SELECTOR . self::OPTION_LAST_CHILD);
$this->assertProjectsVisible([
'Chaos Tool Suite (ctools)', 'Token', 'Pathauto', 'Libraries API', 'Entity API', 'Webform', 'Metatag', 'Field Group', 'IMCE', 'CAPTCHA', 'Google Analytics', 'Redirect',
]);
// Click the Active filter.
$assert_session->waitForElementVisible('css', self::DEVELOPMENT_OPTION_SELECTOR);
$this->clickWithWait(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);
// Make sure the correct filter was applied.
$this->assertEquals('Show projects under active development', $this->getElementText(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_CHECKED));
$assert_session->waitForText('No records available');
// Clear all filters.
$this->pressWithWait('Clear filters', 'Results');
// Click the Actively maintained filter.
$this->clickWithWait(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_FIRST_CHILD, '6,749 Results');
$this->assertEquals('Show actively maintained projects', $this->getElementText(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_CHECKED));
$this->assertProjectsVisible([
'Chaos Tool Suite (ctools)', 'Token', 'Pathauto', 'Libraries API', 'Entity API', 'Webform', 'Metatag', 'Field Group', 'IMCE', 'CAPTCHA', 'Google Analytics', 'Redirect',
]);
}
/**
* Tests sorting criteria.
*/
public function testSortingCriteria(): void {
// Clear filters.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Clear Filters');
$this->pressWithWait('Clear filters');
// Select 'A-Z' sorting order.
$this->sortBy('a_z');
// Assert that the projects are listed in ascending order of their titles.
$this->assertProjectsVisible([
'(Entity Reference) Field Formatters', '@font-your-face', '*.ics field', '1000 to 1k', '200WAD API', '2mee Human Hologram Player', '3D Flipbook', '3D Image', '403 to 404', 'A Simple Timeline', 'A-Frame Extra', 'A/B Test JS',
]);
// Select 'Z-A' sorting order.
$this->sortBy('z_a');
$this->assertProjectsVisible([
'ЮMoney (Yandex Money) Donations', 'Сontact Mail', 'ZURB TwentyTwenty', 'ZURB Orbit', 'ZURB Foundation Sites (Library)', 'ZURB Foundation Container Layouts', 'ZURB Foundation Companion', 'Zurb Foundation 6 Paragraphs', 'Zotero CiteProc JS Server Integration', 'Zooming', 'Zoom Detect', 'Zoom API',
]);
// Select 'Active installs' option.
$this->sortBy('usage_total');
// Assert that the projects are listed in descending order of their usage.
$this->assertProjectsVisible([
'Chaos Tool Suite (ctools)', 'Token', 'Pathauto', 'Libraries API', 'Entity API', 'Webform', 'Metatag', 'Field Group', 'IMCE', 'CAPTCHA', 'Google Analytics', 'Redirect',
]);
// Select 'Recently created' option.
$this->sortBy('created');
// Assert that the projects are listed in descending order of their date of
// creation.
$this->assertProjectsVisible([
'CKEditor Glossary', 'Relative Date Facets', 'External Entities BrAPI Storage plugin', 'Logout After Password Change', 'Image webp toolkit', 'Tagify', 'Webform Sign PDF Example', 'Zookeeper input filter', 'Key Dropbox', 'Fontawesome Iconpicker to Micon Converter', 'Monolog Loki for Drupal', 'Telegram Media Type',
]);
}
/**
* Tests search with strings that need URI encoding.
*/
public function testSearchForSpecialChar(): void {
$this->markTestSkipped('We are using mocks of real data from Drupal.org, what we currently have does not have content suitable for this test.');
}
/**
* Tests the detail page.
*/
public function testDetailPage(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Token');
$page->clickLink('Token');
}
/**
* Tests that filtering, sorting, paging persists.
*/
public function testPersistence(): void {
$this->markTestSkipped('Testing this with the JSON Api endpoint is not needed. The feature is not source dependent.');
}
/**
* Tests recommended filters.
*/
public function testRecommendedFilter(): void {
$assert_session = $this->assertSession();
// Clear filters.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Clear Filters');
$this->pressWithWait('Clear filters', 'Results');
$this->pressWithWait('Recommended filters');
// Check that the actively maintained tag is present.
$maintenance_checked_option = $this->assertSession()->optionExists('maintenanceStatus', '1');
$this->assertTrue($maintenance_checked_option->isSelected());
$this->assertEquals('Show actively maintained projects', $maintenance_checked_option->getText());
// Make sure the second filter applied is the security covered filter.
$assert_session->fieldValueEquals('securityCoverage', '1');
$this->assertTrue($assert_session->waitForText('4,523 Results'));
}
/**
* Tests multiple source plugins at once.
*/
public function testMultiplePlugins(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
// Enable module for extra source plugin.
$this->container->get('module_installer')->install(['project_browser_devel']);
// Test categories with multiple plugin enabled.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown input[type="checkbox"]');
$assert_session->elementsCount('css', '.pb-filter__multi-dropdown input[type="checkbox"]', 54);
$this->svelteInitHelper('css', '#project-browser .pb-project');
// Count tabs.
$tab_count = $page->findAll('css', '.pb-tabs__link');
$this->assertCount(2, $tab_count);
// Get result count for first tab.
$assert_session->pageTextContains('4,523 Results');
// Get second tab text.
$second_tab_text = $assert_session->buttonExists('random_data')->getText();
// Apply filters in project_browser_test_mock(first tab).
$assert_session->waitForElement('css', '.search__filter-button');
$this->pressWithWait('Clear filters', '7,236 Results');
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);
// Click 'E-commerce' checkbox.
$this->clickWithWait('#acc38507-ac85-43e6-8f32-beb3febea93f', '357 Results');
// Clicking the 'Commerce/Advertising' checkbox updates first tab results.
$this->clickWithWait('#23d470f6-ffde-4034-a6ef-492b7121b9cf', '557 Results');
// Applying filters will not change second tab results.
$this->assertSame($second_tab_text, $assert_session->buttonExists('random_data')->getText());
// Use blur event to close drop-down so Clear is visible.
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();
$this->assertSame('Commerce/Advertising, E-commerce', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());
// Click other tab.
$this->pressWithWait('random_data');
$assert_session->waitForElementVisible('css', '#project-browser .pb-project');
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', '', TRUE);
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown input[type="checkbox"]');
$assert_session->elementsCount('css', '.pb-filter__multi-dropdown input[type="checkbox"]', 20);
// Apply the second module category filter.
$second_category_filter_selector = '.pb-filter__multi-dropdown .pb-filter__checkbox-label:nth-child(2) input[type="checkbox"]';
$this->clickWithWait("$second_category_filter_selector");
// Assert that the filters persist.
$dropdown_items = $page->find('css', '.pb-filter__multi-dropdown__items');
$labels = $dropdown_items->findAll('css', '.pb-filter__checkbox-label-txt');
$second_label_text = $labels[1]->getText();
$this->assertSame($second_label_text, $page->find('css', '.pb-filter__multi-dropdown__label')->getText());
// Save the filter applied in second tab.
$applied_filter = $this->getElementText('p.filter-applied:nth-child(1) .filter-applied__label');
// Save the number of results.
$results_before = count($page->findAll('css', '#project-browser .pb-project.pb-project--list'));
// Switch back to first tab.
$page->pressButton('drupalorg_jsonapi');
$this->assertTrue($this->assertSession()->waitForText('Commerce/Advertising'));
$first_filter_element = $page->find('css', 'p.filter-applied:nth-child(1)');
$this->assertEquals('Commerce/Advertising', $first_filter_element->find('css', '.filter-applied__label')->getText());
$second_filter_element = $page->find('css', 'p.filter-applied:nth-child(2)');
$this->assertEquals('E-commerce', $second_filter_element->find('css', '.filter-applied__label')->getText());
$this->assertSame('Commerce/Advertising, E-commerce', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());
// Again switch to second tab.
$page->pressButton('random_data');
// Assert that the filters persist.
$this->assertEquals($applied_filter, $this->getElementText('p.filter-applied:nth-child(1) .filter-applied__label'));
$this->assertSame($second_label_text, $page->find('css', '.pb-filter__multi-dropdown__label')->getText());
// Assert that the number of results is the same.
$results_after = count($page->findAll('css', '#project-browser .pb-project.pb-project--list'));
$this->assertEquals($results_before, $results_after);
// Switch back to first tab.
$this->pressWithWait('drupalorg_jsonapi');
// Filter by search text.
$this->inputSearchField('th');
$this->assertTrue($assert_session->waitForText('2 Results'));
$this->assertProjectsVisible([
'GDPR OneTrust',
'Commerce GoCardless Client',
]);
// Again switch to second tab.
$this->pressWithWait('random_data');
// Switch back to first tab.
$this->pressWithWait('drupalorg_jsonapi');
$this->svelteInitHelper('css', '#project-browser .pb-project');
// Assert that the filters persist.
$this->assertTrue($assert_session->waitForText('2 Results'));
$this->assertProjectsVisible([
'GDPR OneTrust',
'Commerce GoCardless Client',
]);
}
/**
* Tests filters are displayed if they are defined by source.
*/
public function testFiltersShownIfDefinedBySource(): void {
if (version_compare(\Drupal::VERSION, '10.3', '<')) {
$this->markTestSkipped('This test requires Drupal 10.3 or later.');
}
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
// Enable module for extra source plugin.
$this->container->get('module_installer')->install(['project_browser_devel']);
$this->config('project_browser.admin_settings')
->set('enabled_sources', ['recipes', 'project_browser_test_mock'])
->save();
$this->drupalGet('admin/modules/browse');
$this->assertTrue($assert_session->waitForText('Recipes'));
$page->pressButton('Recipes');
// Recipes doesn't define any filters so no filters are displayed.
$this->assertNull($assert_session->waitForElementVisible('css', '.search__form-filters-container'));
// Set the names of filters which will be defined by the test mock.
// @see \Drupal\project_browser_test\Plugin\ProjectBrowserSource\ProjectBrowserTestMock::getFilterDefinitions()
$filters_to_define = ['maintenanceStatus', 'securityCoverage'];
\Drupal::state()->set('filters_to_define', $filters_to_define);
$this->drupalGet('admin/modules/browse');
$this->assertTrue($assert_session->waitForText('Project Browser Mock Plugin'));
$page->pressButton('Project Browser Mock Plugin');
// Drupal.org test mock defines only two filters (actively maintained filter
// and security coverage filter).
$assert_session->waitForElementVisible('css', '.search__form-filters-container');
$this->assertTrue($assert_session->waitForText('Maintenance Status'));
$assert_session->waitForElementVisible('css', self::MAINTENANCE_OPTION_SELECTOR);
$this->assertTrue($assert_session->waitForText('Security Advisory Coverage'));
$assert_session->waitForElementVisible('css', self::SECURITY_OPTION_SELECTOR);
// Make sure no other filters are displayed.
$this->assertFalse($assert_session->waitForText('Development Status'));
$this->assertNull($assert_session->waitForElementVisible('css', self::DEVELOPMENT_OPTION_SELECTOR));
$this->assertFalse($assert_session->waitForText('Filter by category'));
// Make sure category filter element is not visible.
$this->assertNull($assert_session->waitForElementVisible('css', 'div.search__form-filters-container > div.search__form-filters > section > fieldset > div'));
}
/**
* Tests the view mode toggle keeps its state.
*/
public function testToggleViewState(): void {
$page = $this->getSession()->getPage();
$viewSwitches = [
[
'selector' => '.pb-display__button[value="Grid"]',
'value' => 'Grid',
], [
'selector' => '.pb-display__button[value="List"]',
'value' => 'List',
],
];
$this->getSession()->resizeWindow(1300, 1300);
foreach ($viewSwitches as $selector) {
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', $selector['selector']);
$this->getSession()->getPage()->pressButton($selector['value']);
$this->svelteInitHelper('text', 'Token');
$page->clickLink('Token');
$this->svelteInitHelper('text', 'Back to Browsing');
$this->clickWithWait('#project-browser a[href$="/admin/modules/browse"]');
$this->assertSession()->elementExists('css', $selector['selector'] . '.pb-display__button--selected');
}
}
/**
* Tests tabledrag on configuration page.
*/
public function testTabledrag(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->container->get('module_installer')->install(['project_browser_devel']);
$this->drupalGet('admin/modules/browse');
$assert_session->waitForElementVisible('css', '.pb-display__button');
// Count tabs.
$tab_count = $page->findAll('css', '.pb-tabs__link');
$this->assertCount(2, $tab_count);
// Verify that the mock plugin is first tab.
$first_tab = $page->find('css', '.pb-tabs__link:nth-child(1)');
$this->assertEquals('drupalorg_jsonapi', $first_tab->getValue());
// Re-order plugins.
$this->drupalGet('admin/config/development/project_browser');
$first_plugin = $page->find('css', '#source--drupalorg_jsonapi');
$second_plugin = $page->find('css', '#source--random_data');
$first_plugin->find('css', '.tabledrag-handle')->dragTo($second_plugin);
$this->assertTableRowWasDragged($first_plugin);
$this->submitForm([], 'Save');
// Verify that Random data is first tab.
$this->drupalGet('admin/modules/browse');
$assert_session->waitForElementVisible('css', '#project-browser .pb-project');
$first_tab = $page->find('css', '.pb-tabs__link:nth-child(1)');
$this->assertEquals('random_data', $first_tab->getValue());
// Disable the mock plugin.
$this->drupalGet('admin/config/development/project_browser');
$enabled_row = $page->find('css', '#source--drupalorg_jsonapi');
$disabled_region_row = $page->find('css', '.status-title-disabled');
$enabled_row->find('css', '.handle')->dragTo($disabled_region_row);
$this->assertTableRowWasDragged($enabled_row);
$this->submitForm([], 'Save');
$assert_session->pageTextContains('The configuration options have been saved.');
// Verify that only Random data plugin is enabled.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown input[type="checkbox"]');
$assert_session->elementsCount('css', '.pb-filter__multi-dropdown input[type="checkbox"]', 20);
$this->config('project_browser.admin_settings')->set('enabled_sources', ['project_browser_test_mock'])->save(TRUE);
$this->drupalGet('admin/config/development/project_browser');
$this->assertTrue($assert_session->optionExists('edit-enabled-sources-project-browser-test-mock-status', 'enabled')->isSelected());
$this->assertTrue($assert_session->optionExists('edit-enabled-sources-random-data-status', 'disabled')->isSelected());
// Verify that only the mock plugin is enabled.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown input[type="checkbox"]');
$assert_session->elementsCount('css', '.pb-filter__multi-dropdown input[type="checkbox"]', 19);
}
}