Newer
Older
namespace Drupal\Tests\project_browser\FunctionalJavascript;
use Behat\Mink\Element\NodeElement;
use Drupal\Core\Extension\MissingDependencyException;

Adam G-H
committed
use Drupal\Core\Recipe\Recipe;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\project_browser\EnabledSourceHandler;
// cspell:ignore coverageall doomer eggman quiznos statusactive statusmaintained
// cspell:ignore vetica
/**
* Provides tests for the Project Browser UI.
*

Harumi Jang
committed
* These tests rely on a module that replaces Project Browser data with
* test data.
*
* @see project_browser_test_install()
*
*/
class ProjectBrowserUiTest 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',

Harumi Jang
committed
'project_browser_test',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();

Fran Garcia-Linares
committed
$this->config('project_browser.admin_settings')->set('enabled_sources', ['project_browser_test_mock'])->save(TRUE);
$this->drupalLogin($this->drupalCreateUser([
'administer modules',

Narendra Singh Rathore
committed
'administer site configuration',
]));
}
/**
* Tests the grid view.
*/
public function testGrid(): void {
$assert_session = $this->assertSession();

Srishti Bankar
committed
$page = $this->getSession()->getPage();

Ben Mullins
committed
$this->getSession()->resizeWindow(1250, 1000);
$this->drupalGet('admin/modules/browse');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-project.pb-project--grid');
$assert_session->waitForElementVisible('css', '#pb-project-browser .pb-display__button[value="Grid"]');
$grid_text = $this->getElementText('#project-browser .pb-display__button[value="Grid"]');
$this->assertEquals('Grid', $grid_text);
$this->svelteInitHelper('text', '9 Results');

Bernardo Martinez
committed
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--grid', 9);

Ben Mullins
committed
$this->assertTrue($assert_session->waitForText('Results'));

utkarsh_33
committed
$assert_session->pageTextNotContains('No modules found');

Srishti Bankar
committed
$page->pressButton('List');

Bernardo Martinez
committed
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--list'));
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 9);

Chris DeLuca
committed
$page->pressButton('Grid');

Bernardo Martinez
committed
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--grid'));

Ben Mullins
committed
$this->getSession()->resizeWindow(1100, 1000);

Bernardo Martinez
committed
$assert_session->assertNoElementAfterWait('css', '.pb-display__button[value="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', 9);

Chris DeLuca
committed
$this->getSession()->resizeWindow(1210, 1210);

Bernardo Martinez
committed
$this->assertNotNull($assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--grid'));
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--grid', 9);

Srishti Bankar
committed
/**
* Tests the available categories.
*/
public function testCategories(): void {
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-filter__checkbox');
$assert_session->elementsCount('css', '.pb-filter__checkbox', 19);

Srishti Bankar
committed
}
/**
* Tests the clickable category functionality on module page.
*/
public function testClickableCategory(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Dancing Queen');
// Click to open module page.

Kristin Wiseman
committed
$assert_session->waitForButton('Dancing Queen')?->click();
}

narendraR
committed
/**
* Tests category filtering.
*/
public function testCategoryFiltering(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', '.pb-filter__multi-dropdown');

Andy Blum
committed
// Initial results count on page load.
$this->assertTrue($assert_session->waitForText('9 Results'));
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);

narendraR
committed
// Click 'E-commerce' checkbox.
$this->clickWithWait('#104');

Srishti Bankar
committed
$module_category_e_commerce_filter_selector = 'p.filter-applied:first-child';

Srishti Bankar
committed
// 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.

Srishti Bankar
committed
$this->assertProjectsVisible([

Fran Garcia-Linares
committed
'Cream cheese on a bagel',
'Dancing Queen',

Srishti Bankar
committed
'Kangaroo',
'9 Starts With a Higher Number',

Fran Garcia-Linares
committed
'Helvetica',

Srishti Bankar
committed
'Astronaut Simulator',
], TRUE);

Srishti Bankar
committed

Andy Blum
committed
// Clear the checkbox to verify the results revert to their initial state.
$this->clickWithWait('#104', '9 Results');
// Use blur event to close drop-down so Clear is visible.
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();
$this->pressWithWait('Clear filters', '25 Results');

Srishti Bankar
committed
// Open category drop-down again by pressing space.
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->keyDown(' ');
$this->assertSession()->waitForText('Media');

narendraR
committed
// Click 'Media' checkbox.
$this->clickWithWait('#67');

Ben Mullins
committed
// Click 'E-commerce' checkbox.
$this->clickWithWait('#104');

Ben Mullins
committed

Srishti Bankar
committed
// Make sure the 'Media' module category filter is applied.

Chris Wells
committed
$this->assertEquals('Media', $this->getElementText('p.filter-applied:nth-child(2) .filter-applied__label'));

Srishti Bankar
committed
// Assert that only media and administration module categories are shown.
$this->assertProjectsVisible([
'Jazz',
'Eggman',
'Tooth Fairy',

Fran Garcia-Linares
committed
'Vitamin&C;$?',

Srishti Bankar
committed
'Cream cheese on a bagel',
'Pinky and the Brain',

Srishti Bankar
committed
'No Scrubs',
'Soup',
'Mad About You',
'Dancing Queen',
'Kangaroo',
'9 Starts With a Higher Number',
]);
$this->assertTrue($assert_session->waitForText('20 Results'));

narendraR
committed
}

utkarsh_33
committed
/**
* 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', 'Helvetica');

Kristin Wiseman
committed
$assert_session->waitForButton('Helvetica')?->click();

utkarsh_33
committed
}
/**
* Tests read-only input fields for referred commands.
*/
public function testReadonlyFields(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Helvetica');

Marcos Rios
committed

Bernardo Martinez
committed
$assert_session->waitForElementVisible('css', '.project__action_button');

Kristin Wiseman
committed
$page->pressButton('View Commands for Helvetica');
$command_boxes = $page->waitFor(10, fn ($page) => $page->findAll('css', '.command-box textarea[readonly]'));
$this->assertCount(2, $command_boxes);
// The first textarea should have the command to require the module.
$this->assertSame('composer require drupal/helvetica', $command_boxes[0]->getValue());
// And the second textarea should have the command to install it.
$this->assertStringEndsWith('drush install helvetica', $command_boxes[1]->getValue());

Marcos Rios
committed
// Tests alt text for copy command image.

Tim Plunkett
committed
$download_commands = $page->findAll('css', '.command-box img');
$this->assertCount(2, $download_commands);

Tim Plunkett
committed
$this->assertEquals('Copy the download command', $download_commands[0]->getAttribute('alt'));
$this->assertStringStartsWith('Copy the install command', $download_commands[1]->getAttribute('alt'));
}

Harumi Jang
committed
/**
* Tests paging through results.
*/
public function testPaging(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', '9 Results');
$this->assertProjectsVisible([
'Cream cheese on a bagel',
'Pinky and the Brain',
'Dancing Queen',
'Kangaroo',
'9 Starts With a Higher Number',
'Octopus',
'Helvetica',
'Unwritten&:/',
'Astronaut Simulator',
]);
$this->assertPagerItems([]);

Harumi Jang
committed
$page->pressButton('Clear filters');

Ben Mullins
committed
$this->assertTrue($assert_session->waitForText('25 Results'));
$this->assertProjectsVisible([
'Jazz',
'Eggman',
'Tooth Fairy',
'Vitamin&C;$?',
'Cream cheese on a bagel',
'Pinky and the Brain',
'Ice Ice',
'No Scrubs',
'Soup',
'Mad About You',
'Dancing Queen',
'Kangaroo',
]);

Narendra Singh Rathore
committed
$this->assertPagerItems(['1', '2', '3', 'Next', 'Last']);
$assert_session->elementExists('css', '.pager__item--active > .is-active[aria-label="Page 1"]');

Harumi Jang
committed
$this->clickWithWait('[aria-label="Next page"]');
$this->assertProjectsVisible([
'9 Starts With a Higher Number',
'Quiznos',
'Octopus',
'Helvetica',
'1 Starts With a Number',
'Ruh roh',
'Fire',
'Looper',
'Grapefruit',
'Become a Banana',
'Unwritten&:/',
'Doomer',
]);

Narendra Singh Rathore
committed
$this->assertPagerItems(['First', 'Previous', '1', '2', '3', 'Next', 'Last']);

Harumi Jang
committed
$this->clickWithWait('[aria-label="Next page"]');
$this->assertProjectsVisible([
'Astronaut Simulator',
]);

Narendra Singh Rathore
committed
$this->assertPagerItems(['First', 'Previous', '1', '2', '3']);
// 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 'Media' checkbox.
$this->clickWithWait('#67', '', TRUE);

Ben Mullins
committed
// Click 'E-commerce' checkbox.
$this->clickWithWait('#104', '', TRUE);

Ben Mullins
committed
// Click 'E-commerce' checkbox.
$this->clickWithWait('#104', '18 results');

Narendra Singh Rathore
committed
$this->assertPagerItems(['1', '2', 'Next', 'Last']);
$this->clickWithWait('[aria-label="Next page"]');

Ben Mullins
committed

Narendra Singh Rathore
committed
$this->assertPagerItems(['First', 'Previous', '1', '2']);
}
/**
* Tests paging options.
*/
public function testPagingOptions(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-project.pb-project--list');
$this->pressWithWait('Clear filters');

Eric Bremner
committed
$assert_session->waitForText('Modules per page');

Bernardo Martinez
committed
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 12);

Eric Bremner
committed
$assert_session->waitForText('Modules per page');
$page->selectFieldOption('num-projects', '24');

Bernardo Martinez
committed
$assert_session->waitForElementVisible('css', '#project-browser .pb-project.pb-project--list');
$assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 24);

Harumi Jang
committed
}
/**
* Tests advanced filtering.
*/
public function testAdvancedFiltering(): void {
$page = $this->getSession()->getPage();
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Astronaut Simulator');
$this->pressWithWait('Clear filters');
$this->pressWithWait('Recommended filters');

Tim Plunkett
committed
$this->assertProjectsVisible([

Fran Garcia-Linares
committed
'Cream cheese on a bagel',

Tim Plunkett
committed
'Pinky and the Brain',

Fran Garcia-Linares
committed
'Dancing Queen',

Tim Plunkett
committed
'Kangaroo',
'9 Starts With a Higher Number',

Fran Garcia-Linares
committed
'Octopus',
'Helvetica',
'Unwritten&:/',

Tim Plunkett
committed
'Astronaut Simulator',
]);

Harumi Jang
committed
// Make sure the second filter applied is the security covered filter.
$this->assertEquals('Show projects covered by a security policy', $this->getElementText(self::SECURITY_OPTION_SELECTOR . self::OPTION_CHECKED));

Harumi Jang
committed
// Clear the security covered filter.
$this->clickWithWait(self::SECURITY_OPTION_SELECTOR . self::OPTION_LAST_CHILD);

Tim Plunkett
committed
$this->assertProjectsVisible([
'Jazz',

Fran Garcia-Linares
committed
'Vitamin&C;$?',
'Cream cheese on a bagel',

Tim Plunkett
committed
'Pinky and the Brain',

Fran Garcia-Linares
committed
'Ice Ice',
'No Scrubs',
'Dancing Queen',

Tim Plunkett
committed
'Kangaroo',
'9 Starts With a Higher Number',

Fran Garcia-Linares
committed
'Quiznos',
'Octopus',
'Helvetica',

Tim Plunkett
committed
]);

Narendra Singh Rathore
committed
// Check aria-labelledby property for advanced filter.
foreach ($page->findAll('css', '.filters [role="group"]') as $element) {
$this->assertSame($element->findAll('xpath', 'div')[0]->getAttribute('id'), $element->getAttribute('aria-labelledby'));
}

Fran Garcia-Linares
committed
// Click the Active filter.
$this->clickWithWait(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);

Ben Mullins
committed

Harumi Jang
committed
// Make sure the correct filter was applied.
$this->assertEquals('Show projects under active development', $this->getElementText(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_CHECKED));

Tim Plunkett
committed
$this->assertProjectsVisible([
'Jazz',

Fran Garcia-Linares
committed
'Cream cheese on a bagel',
'Ice Ice',
'No Scrubs',
'Dancing Queen',

Tim Plunkett
committed
'Kangaroo',
'9 Starts With a Higher Number',

Fran Garcia-Linares
committed
'Octopus',
'Helvetica',

Tim Plunkett
committed
'1 Starts With a Number',

Fran Garcia-Linares
committed
'Become a Banana',

Tim Plunkett
committed
'Astronaut Simulator',
]);

Harumi Jang
committed

Fran Garcia-Linares
committed
// Click the "Show all" filter for security.
$this->clickWithWait(self::SECURITY_OPTION_SELECTOR . self::OPTION_LAST_CHILD, '', TRUE);

Tim Plunkett
committed
$this->assertProjectsVisible([
'Jazz',

Fran Garcia-Linares
committed
'Cream cheese on a bagel',
'Ice Ice',
'No Scrubs',
'Dancing Queen',
'Kangaroo',
'9 Starts With a Higher Number',
'Octopus',
'Helvetica',

Tim Plunkett
committed
'1 Starts With a Number',

Fran Garcia-Linares
committed
'Become a Banana',
'Astronaut Simulator',

Tim Plunkett
committed
]);
// Clear all filters.
$this->pressWithWait('Clear filters', '25 Results');

Tim Plunkett
committed
// Click the Actively maintained filter.
$this->clickWithWait(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);
$this->assertEquals('Show actively maintained projects', $this->getElementText(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_CHECKED));

Tim Plunkett
committed
$this->assertProjectsVisible([
'Jazz',

Fran Garcia-Linares
committed
'Vitamin&C;$?',
'Cream cheese on a bagel',

Tim Plunkett
committed
'Pinky and the Brain',

Fran Garcia-Linares
committed
'Ice Ice',
'No Scrubs',
'Dancing Queen',

Tim Plunkett
committed
'Kangaroo',
'9 Starts With a Higher Number',

Fran Garcia-Linares
committed
'Quiznos',
'Octopus',
'Helvetica',

Tim Plunkett
committed
]);

Harumi Jang
committed
}

Fran Garcia-Linares
committed
/**
* Tests sorting criteria.
*/
public function testSortingCriteria(): void {
$assert_session = $this->assertSession();

Fran Garcia-Linares
committed
// Clear filters.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Clear Filters');
$this->pressWithWait('Clear filters');
$assert_session->elementsCount('css', '#pb-sort option', 4);

Pamela Barone
committed
$this->assertEquals('Most popular', $this->getElementText('#pb-sort option:nth-child(1)'));
$this->assertEquals('A-Z', $this->getElementText('#pb-sort option:nth-child(2)'));
$this->assertEquals('Z-A', $this->getElementText('#pb-sort option:nth-child(3)'));

Pamela Barone
committed
$this->assertEquals('Newest first', $this->getElementText('#pb-sort option:nth-child(4)'));

Fran Garcia-Linares
committed
// Select 'A-Z' sorting order.
$this->sortBy('a_z');

Ben Mullins
committed

Fran Garcia-Linares
committed
// Assert that the projects are listed in ascending order of their titles.

Tim Plunkett
committed
$this->assertProjectsVisible([
'1 Starts With a Number',
'9 Starts With a Higher Number',
'Astronaut Simulator',
'Become a Banana',
'Cream cheese on a bagel',
'Dancing Queen',
'Doomer',
'Eggman',
'Fire',
'Grapefruit',

Tim Plunkett
committed
'Helvetica',
'Ice Ice',

Tim Plunkett
committed
]);

Fran Garcia-Linares
committed
// Select 'Z-A' sorting order.
$this->sortBy('z_a');

Ben Mullins
committed

Tim Plunkett
committed
$this->assertProjectsVisible([

Fran Garcia-Linares
committed
'Vitamin&C;$?',
'Unwritten&:/',

Tim Plunkett
committed
'Tooth Fairy',
'Soup',
'Ruh roh',
'Quiznos',
'Pinky and the Brain',
'Octopus',
'No Scrubs',
'Mad About You',
'Looper',
'Kangaroo',
]);

Fran Garcia-Linares
committed
// Select 'Active installs' option.
$this->sortBy('usage_total');

Ben Mullins
committed

Fran Garcia-Linares
committed
// Assert that the projects are listed in descending order of their usage.

Tim Plunkett
committed
$this->assertProjectsVisible([
'Jazz',
'Eggman',
'Tooth Fairy',

Fran Garcia-Linares
committed
'Vitamin&C;$?',

Tim Plunkett
committed
'Cream cheese on a bagel',
'Pinky and the Brain',
'Ice Ice',
'No Scrubs',
'Soup',
'Mad About You',
'Dancing Queen',
'Kangaroo',
]);

Fran Garcia-Linares
committed

Sakthi Shanmuga Sundaram M
committed
// Select 'Newest First' option.
$this->sortBy('created');

Ben Mullins
committed

Fran Garcia-Linares
committed
// Assert that the projects are listed in descending order of their date of
// creation.

Tim Plunkett
committed
$this->assertProjectsVisible([
'9 Starts With a Higher Number',
'Helvetica',
'Become a Banana',
'Ice Ice',
'Astronaut Simulator',
'Grapefruit',
'Fire',
'Cream cheese on a bagel',
'No Scrubs',
'Soup',
'Octopus',
'Tooth Fairy',
]);

Fran Garcia-Linares
committed
}

Fran Garcia-Linares
committed
/**
* Tests search with strings that need URI encoding.
*/
public function testSearchForSpecialChar(): void {
// Clear filters.
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', '9 Results');
$this->pressWithWait('Clear filters', '25 Results');

Ben Mullins
committed

utkarsh_33
committed
// Tests for the presence of search bar placeholder text.
$search_field = $this->getSession()->getPage()->find('css', '#pb-text');

Fran Garcia-Linares
committed
// Fill in the search field.
$this->inputSearchField('', TRUE);

Libbna Mathew
committed
$this->inputSearchField('&', TRUE);
$this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();

Fran Garcia-Linares
committed
$this->assertProjectsVisible([
'Vitamin&C;$?',
'Unwritten&:/',
]);
// Fill in the search field.
$this->inputSearchField('', TRUE);

Libbna Mathew
committed
$this->inputSearchField('n&', TRUE);
$this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();

Fran Garcia-Linares
committed
$this->assertProjectsVisible([
'Vitamin&C;$?',
'Unwritten&:/',
]);
$this->inputSearchField('', TRUE);

Libbna Mathew
committed
$this->inputSearchField('$', TRUE);
$this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();

Fran Garcia-Linares
committed
$this->assertProjectsVisible([
'Vitamin&C;$?',
]);
$this->inputSearchField('', TRUE);

Libbna Mathew
committed
$this->inputSearchField('?', TRUE);
$this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();

Fran Garcia-Linares
committed
$this->assertProjectsVisible([
'Vitamin&C;$?',
]);
$this->inputSearchField('', TRUE);

Libbna Mathew
committed
$this->inputSearchField('&:', TRUE);
$this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();

Fran Garcia-Linares
committed
$this->assertProjectsVisible([
'Unwritten&:/',
]);
$this->inputSearchField('', TRUE);

Libbna Mathew
committed
$this->inputSearchField('$?', TRUE);
$this->assertSession()->waitForElementVisible('css', ".search__search-submit")->click();

Fran Garcia-Linares
committed
$this->assertProjectsVisible([
'Vitamin&C;$?',
]);
}

Srishti Bankar
committed
/**
* Tests the detail page.
*/
public function testDetailPage(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Helvetica');

Kristin Wiseman
committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
$assert_session->waitForButton('Helvetica')?->click();
// Check the detail modal displays.
$assert_session->waitForElementVisible('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Helvetica"]');
$assert_session->elementExists('css', 'button.project__action_button');
// Close the modal.
$assert_session->waitForButton('Close')?->click();
$assert_session->elementNotExists('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Helvetica"]');
}
/**
* Tests the detail page.
*/
public function testReopenDetailModal(): void {
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Helvetica');
$assert_session->waitForButton('Helvetica')?->click();
// Check the detail modal displays.
$assert_session->waitForElementVisible('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Helvetica"]');
$assert_session->elementExists('css', 'button.project__action_button');
// Close the modal and check it no longer exists.
$assert_session->waitForButton('Close')?->click();
$assert_session->elementNotExists('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Helvetica"]');
// Check that a different module modal can be opened.
$assert_session->waitForButton('Octopus')->click();
$assert_session->waitForElementVisible('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Octopus"]');
$assert_session->waitForButton('Close')?->click();
$assert_session->elementNotExists('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Octopus"]');
// Check that first detail modal can be reopened.
$assert_session->waitForElementVisible('xpath', '//span[contains(@class, "ui-dialog-title") and text()="Helvetica"]');
$assert_session->elementExists('css', 'button.project__action_button');

Srishti Bankar
committed
}

Harumi Jang
committed
/**
* Tests that filtering, sorting, paging persists.
*/
public function testPersistence(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Clear Filters');
$this->pressWithWait('Clear filters');

Ben Mullins
committed
// Select 'Z-A' sorting order.
$this->sortBy('z_a');

Ben Mullins
committed

Harumi Jang
committed
// Select the active development status filter.
$assert_session->waitForElementVisible('css', self::DEVELOPMENT_OPTION_SELECTOR);
$this->clickWithWait(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);
// Open category drop-down.
$assert_session->elementExists('css', '.pb-filter__multi-dropdown')->click();

Ben Mullins
committed
// Select the E-commerce filter.
$assert_session->waitForElementVisible('css', '#104');
$this->clickWithWait('#104', '', TRUE);

Ben Mullins
committed

Harumi Jang
committed
// Select the Media filter.
$assert_session->waitForElementVisible('css', '#67');
$this->clickWithWait('#67', '', TRUE);

Ben Mullins
committed
$this->assertTrue($assert_session->waitForText('15 Results'));

Harumi Jang
committed
$this->assertProjectsVisible([
'Octopus',
'No Scrubs',
'Mad About You',
'Kangaroo',
'Jazz',

Harumi Jang
committed
'Grapefruit',
'Eggman',
'Doomer',
'Dancing Queen',
'Cream cheese on a bagel',

Harumi Jang
committed
]);

Ben Mullins
committed
$this->clickWithWait('[aria-label="Next page"]');

Harumi Jang
committed
$this->assertProjectsVisible([
'Astronaut Simulator',
'9 Starts With a Higher Number',
'1 Starts With a Number',
]);
$this->getSession()->reload();
// Should still be on second results page.

Bernardo Martinez
committed
$this->svelteInitHelper('css', '#project-browser .pb-project');

Harumi Jang
committed
$this->assertProjectsVisible([
'Astronaut Simulator',
'9 Starts With a Higher Number',
'1 Starts With a Number',
]);
$this->assertTrue($assert_session->waitForText('15 Results'));
$this->assertEquals('E-commerce', $this->getElementText('p.filter-applied:first-child .filter-applied__label'));
$this->assertEquals('Media', $this->getElementText('p.filter-applied:nth-child(2) .filter-applied__label'));
$this->clickWithWait('[aria-label="First page"]');

Harumi Jang
committed
$this->assertProjectsVisible([
'Octopus',
'No Scrubs',
'Mad About You',
'Kangaroo',
'Jazz',

Harumi Jang
committed
'Grapefruit',
'Eggman',
'Doomer',
'Dancing Queen',
'Cream cheese on a bagel',
'Become a Banana',
], TRUE);
$this->assertEquals('E-commerce', $this->getElementText('p.filter-applied:first-child .filter-applied__label'));
$this->assertEquals('Media', $this->getElementText('p.filter-applied:nth-child(2) .filter-applied__label'));

Harumi Jang
committed
}
/**
* 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', '25 Results');
$this->pressWithWait('Recommended filters');
// Check that the actively maintained tag is present.
$this->assertEquals('Show actively maintained projects', $this->getElementText(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_CHECKED));
// Make sure the second filter applied is the security covered filter.
$this->assertEquals('Show projects covered by a security policy', $this->getElementText(self::SECURITY_OPTION_SELECTOR . self::OPTION_CHECKED));

Ben Mullins
committed
$this->assertTrue($assert_session->waitForText('9 Results'));
}

Narendra Singh Rathore
committed
/**
* 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'], TRUE);
// Test categories with multiple plugin enabled.
$this->drupalGet('admin/modules/browse');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-filter__checkbox');
$assert_session->elementsCount('css', '.pb-filter__checkbox', 19);

Narendra Singh Rathore
committed

Bernardo Martinez
committed
$this->svelteInitHelper('css', '#project-browser .pb-project');

Narendra Singh Rathore
committed
// Count tabs.

Bernardo Martinez
committed
$tab_count = $page->findAll('css', '.pb-tabs__link');

Narendra Singh Rathore
committed
$this->assertCount(2, $tab_count);
// Get result count for first tab.

Bernardo Martinez
committed
$this->assertEquals('9 Results', $this->getElementText('.pb-search-results'));

Andy Blum
committed
// Get second tab text.
$second_tab_text = $assert_session->buttonExists('random_data')->getText();

Srishti Bankar
committed

Fran Garcia-Linares
committed
// Apply filters in project_browser_test_mock(first tab).

Srishti Bankar
committed
$assert_session->waitForElement('css', '.views-exposed-form__item input[type="checkbox"]');
$this->pressWithWait('Clear filters', '25 Results');

Andy Blum
committed
// Removing/applying filters will not change second tab results.
$this->assertSame($second_tab_text, $assert_session->buttonExists('random_data')->getText());

Srishti Bankar
committed
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);

Srishti Bankar
committed
// Click 'E-commerce' checkbox.
$this->clickWithWait('#104');

Andy Blum
committed
// Click 'Media' checkbox. It will change results on first tab.

Srishti Bankar
committed
$this->clickWithWait('#67', '20 Results');

Andy Blum
committed
// Applying filters will not change second tab results.
$this->assertSame($second_tab_text, $assert_session->buttonExists('random_data')->getText());

Srishti Bankar
committed
// Use blur event to close drop-down so Clear is visible.
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->blur();

utkarsh_33
committed
$this->assertSame('2 categories selected', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());

Narendra Singh Rathore
committed
// Click other tab.
$this->pressWithWait('random_data');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-filter__checkbox');
$assert_session->elementsCount('css', '.pb-filter__checkbox', 20);
$assert_session->waitForElementVisible('css', '#project-browser .pb-project');
$this->assertNotEquals('9 Results Sorted by Active installs', $this->getElementText('.pb-search-results'));

Andy Blum
committed
// Switching tab will not change result count.
$this->assertEquals($second_tab_text . ' (active tab)', $page->findButton('random_data')->getText());
// Open category drop-down again by pressing space.
$this->assertSession()->elementExists('css', '.pb-filter__multi-dropdown')->keyDown(' ');

Srishti Bankar
committed
// Apply the second module category filter.

Narendra Singh Rathore
committed
$second_category_filter_selector = '.pb-filter__multi-dropdown__items > .pb-filter__checkbox-label:nth-child(2) input';

Srishti Bankar
committed
$this->clickWithWait("$second_category_filter_selector");

Andy Blum
committed
// Applying filter on second tab will change result count.
$this->assertNotSame($second_tab_text, $assert_session->buttonExists('random_data')->getText());

utkarsh_33
committed
$this->assertSame('1 category selected', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());

Srishti Bankar
committed
// Save the filter applied in second tab.

Chris Wells
committed
$applied_filter = $this->getElementText('p.filter-applied:nth-child(1) .filter-applied__label');

Srishti Bankar
committed
// Save the number of results.

Bernardo Martinez
committed
$results_before = count($page->findAll('css', '#project-browser .pb-project.list'));

Srishti Bankar
committed
// Switch back to first tab.

Fran Garcia-Linares
committed
$this->pressWithWait('project_browser_test_mock');

utkarsh_33
committed
$this->assertSame('2 categories selected', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());

Chris Wells
committed
$first_filter_element = $page->find('css', 'p.filter-applied:nth-child(1)');
$this->assertEquals('E-commerce', $first_filter_element->find('css', '.filter-applied__label')->getText());

Chris Wells
committed
$second_filter_element = $page->find('css', 'p.filter-applied:nth-child(2)');
$this->assertEquals('Media', $second_filter_element->find('css', '.filter-applied__label')->getText());

Srishti Bankar
committed
// Again switch to second tab.

Narendra Singh Rathore
committed
$this->pressWithWait('random_data');

Srishti Bankar
committed
// Assert that the filters persist.

Chris Wells
committed
$this->assertEquals($applied_filter, $this->getElementText('p.filter-applied:nth-child(1) .filter-applied__label'));

utkarsh_33
committed
$this->assertSame('1 category selected', $page->find('css', '.pb-filter__multi-dropdown__label')->getText());

Srishti Bankar
committed
// Assert that the number of results is the same.

Bernardo Martinez
committed
$results_after = count($page->findAll('css', '#project-browser .pb-project.list'));

Srishti Bankar
committed
$this->assertEquals($results_before, $results_after);

Andy Blum
committed
// Switch back to first tab.
$this->pressWithWait('project_browser_test_mock');
// Filter by search text.

Libbna Mathew
committed
$this->inputSearchField('Number', TRUE);
$assert_session->waitForElementVisible('css', ".search__search-submit")->click();

Andy Blum
committed
$this->assertTrue($assert_session->waitForText('2 Results'));
$this->assertProjectsVisible([
'9 Starts With a Higher Number',
'1 Starts With a Number',
]);
// Again switch to second tab.
$this->pressWithWait('random_data');
$this->pressWithWait('Clear filters');
// Switch back to first tab.
$this->pressWithWait('project_browser_test_mock');
$this->svelteInitHelper('css', '#project-browser .pb-project');
// Assert that the filters persist.
$this->assertTrue($assert_session->waitForText('2 Results'));
$this->assertProjectsVisible([
'9 Starts With a Higher Number',
'1 Starts With a Number',
]);

Narendra Singh Rathore
committed
}
/**
* Tests the view mode toggle keeps its state.
*/
public function testToggleViewState(): void {

Kristin Wiseman
committed
$assert_session = $this->assertSession();
$viewSwitches = [
[

Bernardo Martinez
committed
'selector' => '.pb-display__button[value="Grid"]',
'value' => 'Grid',
], [

Bernardo Martinez
committed
'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', 'Helvetica');

Kristin Wiseman
committed
$assert_session->waitForButton('Helvetica')?->click();
$this->svelteInitHelper('text', 'Close');
$assert_session->waitForButton('Close')?->click();

Bernardo Martinez
committed
$this->assertSession()->elementExists('css', $selector['selector'] . '.pb-display__button--selected');
}
}

Tim Plunkett
committed
/**
* 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'], TRUE);
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('text', 'Random data');

Tim Plunkett
committed
// Count tabs.

Bernardo Martinez
committed
$tab_count = $page->findAll('css', '.pb-tabs__link');

Tim Plunkett
committed
$this->assertCount(2, $tab_count);

Fran Garcia-Linares
committed
// Verify that the mock plugin is first tab.

Bernardo Martinez
committed
$first_tab = $page->find('css', '.pb-tabs__link:nth-child(1)');

Fran Garcia-Linares
committed
$this->assertEquals('project_browser_test_mock', $first_tab->getValue());

Tim Plunkett
committed
// Re-order plugins.
$this->drupalGet('admin/config/development/project_browser');

Fran Garcia-Linares
committed
$first_plugin = $page->find('css', '#source--project_browser_test_mock');

Tim Plunkett
committed
$second_plugin = $page->find('css', '#source--random_data');
$first_plugin->find('css', '.handle')->dragTo($second_plugin);
$this->assertTableRowWasDragged($first_plugin);

Tim Plunkett
committed
$this->submitForm([], 'Save');
// Verify that Random data is first tab.
$this->drupalGet('admin/modules/browse');

Fran Garcia-Linares
committed
$this->svelteInitHelper('text', 'Project Browser Mock Plugin');

Bernardo Martinez
committed
$first_tab = $page->find('css', '.pb-tabs__link:nth-child(1)');

Tim Plunkett
committed
$this->assertEquals('random_data', $first_tab->getValue());

Fran Garcia-Linares
committed
// Disable the mock plugin.

Tim Plunkett
committed
$this->drupalGet('admin/config/development/project_browser');

Fran Garcia-Linares
committed
$enabled_row = $page->find('css', '#source--project_browser_test_mock');

Tim Plunkett
committed
$disabled_region_row = $page->find('css', '.status-title-disabled');
$enabled_row->find('css', '.handle')->dragTo($disabled_region_row);
$this->assertTableRowWasDragged($enabled_row);

Tim Plunkett
committed
$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');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-filter__checkbox');
$assert_session->elementsCount('css', '.pb-filter__checkbox', 20);

Tim Plunkett
committed

Fran Garcia-Linares
committed
$this->config('project_browser.admin_settings')->set('enabled_sources', ['project_browser_test_mock'])->save(TRUE);

Tim Plunkett
committed
$this->drupalGet('admin/config/development/project_browser');

Fran Garcia-Linares
committed
$this->assertTrue($assert_session->optionExists('edit-enabled-sources-project-browser-test-mock-status', 'enabled')->isSelected());

Tim Plunkett
committed
$this->assertTrue($assert_session->optionExists('edit-enabled-sources-random-data-status', 'disabled')->isSelected());

Fran Garcia-Linares
committed
// Verify that only the mock plugin is enabled.

Tim Plunkett
committed
$this->drupalGet('admin/modules/browse');

Bernardo Martinez
committed
$this->svelteInitHelper('css', '.pb-filter__checkbox');
$assert_session->elementsCount('css', '.pb-filter__checkbox', 19);

Tim Plunkett
committed
}

utkarsh_33
committed
/**
* Tests the visibility of categories in list and grid view.
*/
public function testCategoriesVisibility(): void {
$assert_session = $this->assertSession();
$view_options = [
[

Bernardo Martinez
committed
'selector' => '.pb-display__button[value="Grid"]',

utkarsh_33
committed
'value' => 'Grid',
], [

Bernardo Martinez
committed
'selector' => '.pb-display__button[value="List"]',

utkarsh_33
committed
'value' => 'List',
],
];
$this->getSession()->resizeWindow(1300, 1300);
// Check visibility of categories in each view.
foreach ($view_options as $selector) {
$this->drupalGet('admin/modules/browse');
$this->svelteInitHelper('css', $selector['selector']);
$this->getSession()->getPage()->pressButton($selector['value']);
$this->svelteInitHelper('text', 'Helvetica');

Bernardo Martinez
committed
$assert_session->elementsCount('css', '#project-browser .pb-layout__main ul li:nth-child(7) .pb-project-categories ul li', 1);
$grid_text = $this->getElementText('#project-browser .pb-layout__main ul li:nth-child(7) .pb-project-categories ul li:nth-child(1)');

utkarsh_33
committed
$this->assertEquals('E-commerce', $grid_text);

Bernardo Martinez
committed
$assert_session->elementsCount('css', '#project-browser .pb-layout__main ul li:nth-child(9) .pb-project-categories ul li', 2);
$grid_text = $this->getElementText('#project-browser .pb-layout__main ul li:nth-child(7) .pb-project-categories ul li:nth-child(1)');
$this->assertEquals('E-commerce', $grid_text);

Bernardo Martinez
committed
$grid_text = $this->getElementText('#project-browser .pb-layout__main ul li:nth-child(9) .pb-project-categories ul li:nth-child(2)');

utkarsh_33
committed
$this->assertEquals('E-commerce', $grid_text);
}
}
/**
* Tests the pagination and filtering.
*/
public function testPaginationWithFilters(): void {
$assert_session = $this->assertSession();
$this->drupalGet('admin/modules/browse');
$this->pressWithWait('Clear filters');
$this->assertProjectsVisible([
'Jazz',
'Eggman',
'Tooth Fairy',
'Vitamin&C;$?',
'Cream cheese on a bagel',
'Pinky and the Brain',
'Ice Ice',
'No Scrubs',
'Soup',
'Mad About You',
'Dancing Queen',
'Kangaroo',
]);

Narendra Singh Rathore
committed
$this->assertPagerItems(['1', '2', '3', 'Next', 'Last']);
$this->clickWithWait('[aria-label="Last page"]');
$this->assertProjectsVisible([
'Astronaut Simulator',
]);
// Open category drop-down.
$this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE);
// Click 'Media' checkbox.
$this->clickWithWait('#67');