drupalGet(''); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('200 University Avenue West'); $disabled_modules = [ 'big_pipe', 'help', 'search', ]; // If uw_site_dev is disabled when fresh install a site, // dblog module should be disabled. $uw_site_dev_enabled = \Drupal::moduleHandler()->moduleExists('uw_site_dev'); if (!$uw_site_dev_enabled) { $disabled_modules[] = 'dblog'; } foreach ($disabled_modules as $module) { $enabled = \Drupal::moduleHandler()->moduleExists($module); $this->assertFalse($enabled, 'Module ' . $module . ' is not enabled.'); } $this->createUsers(); $this->layoutSectionConfigurationFormTest(); $this->webformTests(); $this->createContent(); $this->taxonomies(); $this->catalogTest(); $this->schemaTest(); $this->configBlockTest(); $this->previewButtonTest(); $this->layoutBuilderBrowserTest(); $this->globalFooterTest(); $this->menusTest(); $this->dashboardTest(); $this->ctaBlockTest(); // Testing permissions is very time-consuming. So, normally do not run it. // @code // $this->permissionsTest(); // @endcode $this->realnameTest(); $this->contactContentTypeTest(); $this->profileContentTypeTest(); $this->ffBlockTest(); $this->mediaTypesTest(); $this->redirectsTest(); $this->uwLdapTest(); $this->ckeditorButtonsTest(); $this->bannerBlockTest(); $this->ofisTest(); } /** * Tests for Custom block banner. */ private function bannerBlockTest() { $this->drupalLogin($this->drupalUsers['uw_role_site_manager']); $this->drupalGet('node/1/layout'); $this->assertSession()->statusCodeEquals(200); $this->clickLink('Add block'); $this->clickLink('Banner images'); // Check 'Banner' group. // Banner is required. $banner_required = $this->getSession()->getPage()->find('xpath', "//strong[contains(text(), 'Banner')]"); $this->assertEquals('form-required', $banner_required->getAttribute('class')); $this->assertEquals('edit-settings-block-form-field-uw-banner-item', $banner_required->getParent()->getAttribute('data-drupal-selector')); // 'No Banner added yet' exists. $this->assertSession()->pageTextContains('No Banner added yet.'); // The help texts exist. $this->assertSession()->pageTextContains('You may add 1 to 8 banners. If more than one banner is added, they will be displayed in a carousel. For ideal display, all banners should have the same dimensions.'); $this->assertSession()->pageTextContains('Note that all options beyond a single image banner are unsupported at this time, and are provided for future use.'); // Check 'Add Image banner', 'Add Local video banner' // and 'Add Vimeo video banner'. $elements = [ 'Image', 'Local video', 'Vimeo video', ]; foreach ($elements as $element) { $this->assertTrue($this->xpath('//input[@type="submit" and @value="Add ' . $element . ' banner"]'), 'Add banner using ' . $element); } // Check 'Settings' group. // 'Settings' is required. $settings_required = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Settings')]"); $classes = explode(' ', $settings_required->getParent()->getParent()->getAttribute('class')); $class_required_fields = in_array('required-fields', $classes); $this->assertTrue($class_required_fields); // 'Slide speed' is required. $slide_speed_required = $this->getSession()->getPage()->find('xpath', "//label[contains(text(), 'Slide speed')]"); $this->assertEquals('js-form-required form-required', $slide_speed_required->getAttribute('class')); $this->assertFieldByXPath('//input[@value="7000" and @name="settings[block_form][field_uw_slide_speed][0][value]"]', NULL, 'Default value is 7000ms.'); $this->assertSession()->pageTextContains('Enter the time, in milliseconds, that should elapse between slides when the slideshow is playing.'); // 'Transition speed' is required. $slide_speed_required = $this->getSession()->getPage()->find('xpath', "//label[contains(text(), 'Transition speed')]"); $this->assertEquals('js-form-required form-required', $slide_speed_required->getAttribute('class')); $this->assertFieldByXPath('//input[@value="400" and @name="settings[block_form][field_uw_transition_speed][0][value]"]', NULL, 'Default value is 400ms.'); $this->assertSession()->pageTextContains('Enter the time, in milliseconds, the banner transition should take to complete.'); // Autoplay is checked by default. $this->assertSession()->checkboxChecked('edit-settings-block-form-field-uw-autoplay-value'); $this->assertSession()->pageTextContains('Controls whether or not the slideshow starts immediately on page load.'); // 'Text overlay style' is required. $text_style = $this->getSession()->getPage()->find('xpath', "//label[contains(text(), 'Text overlay style')]"); $this->assertEquals('js-form-required form-required', $text_style->getAttribute('class')); // The selected list match the expected list. $expected_options = [ 'full-width' => 'Full banner width, bottom, theme colour background ("FDSU" style)', 'inset' => 'Inset from banner, bottom, black background ("home page" style)', 'split' => 'Split top and bottom, black and white backgrounds ("single page" style)', 'full-overlay' => 'Full black overlay, centered text ("conference" style)', ]; $options = $this->getOptions('settings[block_form][field_uw_text_overlay_style]'); foreach ($expected_options as $key => $expected_option) { $this->assertEqual($options[$key], $expected_option); } // Full banner is selected as default. $this->assertFieldByXPath('//option[@value="full-width" and @selected="selected"]', NULL, 'Full banner width, bottom, theme colour background ("FDSU" style) is selected.'); $this->assertSession()->pageTextContains('Note that all options other than "FDSU" style are unsupported at this time, and are provided for future use.'); // Click 'Add Image banner'. $this->click('#edit-settings-block-form-field-uw-banner-item-add-more-add-more-button-uw-para-image-banner'); $image = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Image')]"); $this->assertEquals('fieldset-legend js-form-required form-required', $image->getAttribute('class')); $this->assertSession()->pageTextContains('No media items are selected.'); $this->assertSession()->buttonExists('Add media'); $fields = [ 'Link' => 'Provide an optional link for this banner.', 'Big text' => 'Big text appears at a larger size, and, if both are set, above the small text.', 'Small text' => 'Small text appears at a smaller size, and, if both are set, below the big text.', ]; foreach ($fields as $key => $field) { $this->assertSession()->fieldExists($key); $this->assertSession()->pageTextContains($field); } // Click 'Add Local video banner'. $this->click('#edit-settings-block-form-field-uw-banner-item-add-more-add-more-button-uw-para-local-video-banner'); $local_video = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Video')]"); $this->assertEquals('fieldset-legend js-form-required form-required', $local_video->getAttribute('class')); $this->assertSession()->pageTextContains('No media items are selected.'); $this->assertSession()->buttonExists('Add media'); $fallback_iamge = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Fallback image')]"); $this->assertEquals('fieldset-legend js-form-required form-required', $fallback_iamge->getAttribute('class')); $this->assertSession()->pageTextContains('No media items are selected.'); $this->assertSession()->buttonExists('Add media'); $fields = [ 'Link' => 'Provide an optional link for this banner.', 'Big text' => 'Big text appears at a larger size, and, if both are set, above the small text.', 'Small text' => 'Small text appears at a smaller size, and, if both are set, below the big text.', ]; foreach ($fields as $key => $field) { $this->assertSession()->fieldExists($key); $this->assertSession()->pageTextContains($field); } // Click 'Add Vimeo video banner'. $this->click('#edit-settings-block-form-field-uw-banner-item-add-more-add-more-button-uw-para-vimeo-video-banner'); $vimeo_video = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Vimeo video')]"); $this->assertEquals('fieldset-legend js-form-required form-required', $vimeo_video->getAttribute('class')); $this->assertSession()->pageTextContains('No media items are selected.'); $this->assertSession()->buttonExists('Add media'); $this->assertSession()->linkExists('media add page'); $vimeo_video = $this->getSession()->getPage()->find('xpath', "//label[contains(text(), 'Use existing media')]"); $this->assertEquals('js-form-required form-required', $vimeo_video->getAttribute('class')); $this->assertSession()->fieldExists('settings[block_form][field_uw_banner_item][2][subform][field_uw_ban_fallback_image][0][target_id]'); $this->assertSession()->linkExists('media list'); $fields = [ 'Link' => 'Provide an optional link for this banner.', 'Big text' => 'Big text appears at a larger size, and, if both are set, above the small text.', 'Small text' => 'Small text appears at a smaller size, and, if both are set, below the big text.', ]; foreach ($fields as $key => $field) { $this->assertSession()->fieldExists($key); $this->assertSession()->pageTextContains($field); } } /** * Test Webforms. */ private function webformTests() { // Create test Webform. $this->drupalLogin($this->drupalUsers['uw_role_form_editor']); $edit = [ 'id' => 'test_form', 'title' => 'Test Form', 'status' => 'open', ]; $this->drupalPostForm('admin/structure/webform/add', $edit, 'Save'); // The variable $test_paths stores Drupal paths and permission information. // In this array, the keys are paths. If the value is TRUE, everyone has // access. Otherwise, the value must be an array of roles that have access. // Other roles do not have access. $test_paths = [ '' => TRUE, 'admin' => [ 'uw_role_site_owner', 'uw_role_site_manager', 'uw_role_content_editor', 'uw_role_content_author', ], // Webform. 'admin/structure/webform' => [ 'uw_role_form_editor', 'uw_role_form_results_access', ], 'admin/structure/webform/add' => ['uw_role_form_editor'], 'admin/structure/webform/addons' => ['uw_role_form_editor'], 'admin/structure/webform/config' => ['uw_role_form_editor'], 'admin/structure/webform/config/advanced' => ['uw_role_form_editor'], 'admin/structure/webform/config/elements' => ['uw_role_form_editor'], 'admin/structure/webform/config/exporters' => ['uw_role_form_editor'], 'admin/structure/webform/config/handlers' => ['uw_role_form_editor'], 'admin/structure/webform/config/libraries' => ['uw_role_form_editor'], 'admin/structure/webform/config/options/manage' => ['uw_role_form_editor'], 'admin/structure/webform/config/submissions' => ['uw_role_form_editor'], 'admin/structure/webform/config/variants' => ['uw_role_form_editor'], 'admin/structure/webform/help' => TRUE, 'admin/structure/webform/submissions/manage' => [ 'uw_role_form_editor', 'uw_role_form_results_access', ], // Test Webform. 'admin/structure/webform/manage/test_form' => ['uw_role_form_editor'], 'admin/structure/webform/manage/test_form/results/submissions' => [ 'uw_role_form_editor', 'uw_role_form_results_access', ], 'admin/structure/webform/manage/test_form/settings' => ['uw_role_form_editor'], 'form/test-form' => TRUE, 'webform/test_form/test' => ['uw_role_form_editor'], ]; // Test these paths with each user. foreach ($this->drupalUsers as $role => $user) { // Admin always has access so there is no point testing. if ($role === 'administrator') { continue; } if ($user) { $this->drupalLogin($user); } elseif ($this->loggedInUser) { $this->drupalLogout(); } foreach ($test_paths as $path => $permissions) { // Get the expected HTTP response code. $expected_code = ($permissions === TRUE || in_array($role, $permissions, TRUE)) ? 200 : 403; // Test this path for the HTTP response code. $this->drupalGet($path); $this_code = $this->getSession()->getStatusCode(); $message = sprintf('Response status code for %s on path %s is %d; %d expected.', $role, $path, $this_code, $expected_code); $this->assert(intval($this_code) === $expected_code, $message); } } } /** * Populate $drupalUsers with an array of users with various roles. */ private function createUsers() { // Test if property is already populated. if ($this->drupalUsers) { return; } // Create users. $this->drupalUsers = ['anonymous user' => NULL]; $roles = [ 'authenticated user', 'administrator', 'uw_role_site_owner', 'uw_role_site_manager', 'uw_role_content_editor', 'uw_role_content_author', 'uw_role_form_editor', 'uw_role_form_results_access', ]; foreach ($roles as $role) { $user = [ 'roles' => [$role], 'edit-field-uw-first-name-0-value' => $this->randomString(), 'edit-field-uw-last-name-0-value' => $this->randomString(), ]; $this->drupalUsers[$role] = $this->createUser([], $role, FALSE, $user); } } /** * Test content creation. */ private function createContent() { $this->drupalLogin($this->drupalUsers['uw_role_content_author']); // Make sure audience taxonomy to blog, catalog, // event and news item content types. $types = [ 'blog' => 'node/add/uw_ct_blog', 'catalog' => 'node/add/uw_ct_catalog_item', 'event' => 'node/add/uw_ct_event', 'news-item' => 'node/add/uw_ct_news_item', ]; foreach ($types as $key => $type) { $this->drupalGet($type); $this->assertSession()->statusCodeEquals(200); // Blog, event, news item have taxonomies fieldset. if ($key != 'catalog') { $taxonomies = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Taxonomies')]"); $this->assertEquals('edit-group-uw-' . $key . '-tags', $taxonomies->getParent()->getParent()->getAttribute('id')); $audience = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Audience')]"); $this->assertEquals('edit-field-uw-audience--wrapper', $audience->getParent()->getParent()->getAttribute('id')); } else { // The message is displayed when creating a catalog item // without a catalog term created. $this->assertSession()->pageTextContains('You must create at least one catalog before adding a catalog item.'); } } // Test field_uw_event_map exists. $this->drupalGet('node/add/uw_ct_event'); $this->assertSession()->statusCodeEquals(200); $this->assertFieldByXPath('//input[@type="url" and @id="edit-field-uw-event-map-0-uri"]', NULL, 'Map link field exists.'); $this->assertSession()->pageTextContains('Optional: provide a link to a map with the event location (e.g. https://uwaterloo.ca/map/)'); // Create a catalog term in order to create a catalog item. $edit = [ 'edit-name-0-value' => $this->randomString(), ]; $this->drupalPostForm('admin/structure/taxonomy/manage/uw_vocab_catalogs/add', $edit, $this->t('Save')); // Array of content types. // Keys: Content types. // Values: Array of extra fields and their types. $content_types = [ 'uw_ct_web_page' => [], 'uw_ct_site_footer' => [], 'uw_ct_blog' => ['edit-field-uw-blog-summary-0-value' => 'string'], 'uw_ct_news_item' => ['edit-field-uw-news-summary-0-value' => 'string'], 'uw_ct_event' => [ 'edit-field-uw-event-summary-0-value' => 'string', 'edit-field-uw-event-date-0-value-date' => 'date', 'edit-field-uw-event-date-0-value-time' => 'time', 'edit-field-uw-event-date-0-end-value-date' => 'date', 'edit-field-uw-event-date-0-end-value-time' => 'time', ], 'uw_ct_catalog_item' => [], // uw_ct_sidebar is tested separately below. ]; $content_nids = []; foreach ($content_types as $content_type => $extra_fields) { // Create node. $edit = [ 'edit-title-0-value' => $this->randomString(), ]; foreach ($extra_fields as $field => $type) { switch ($type) { case 'date': $edit[$field] = date('Y-m-d'); break; case 'time': $edit[$field] = date('H:i:s'); break; default: $edit[$field] = $this->randomString(); } } $this->drupalPostForm('node/add/' . $content_type, $edit, 'Save'); // Make sure no 'Revert to default' on the above content type layout page. $this->assertSession()->buttonNotExists('Revert to defaults'); // Get the node ID of the newly-created node, store in $content_nids. $nid = $this->xpath('//a[text() = "View"]'); preg_match('/^node\/(\d+)$/', $nid[0]->getAttribute('data-drupal-link-system-path'), $matches); $nid = (int) $matches[1]; $this->assert($nid > 0, 'Positive nid found.'); $content_nids[$content_type] = $nid; // On node creation, the user is redirected to the layout edit page. $this->assertSession()->addressMatches('/^\/[a-z0-9-\/]+\/layout$/'); // Check node title. $this->assertSession()->pageTextContains('Edit layout for ' . $edit['edit-title-0-value']); // Check that there is no moderation form. $this->assertSession()->linkByHrefNotExists('/admin/uw-content-moderation/'); // On node edit, the user is not redirected to the layout edit page. $this->clickLink('Edit'); // Store edit link for later use. $url = $this->getSession()->getCurrentUrl(); // Save edit form without making changes. $this->submitForm([], 'Save'); // Verify that we are not on the layout edit page. $this->assertSession()->pageTextContains($edit['edit-title-0-value'] . ' has been updated'); $this->assertSession()->pageTextNotContains('Edit layout for'); // All content types except footer have moderation form. if ($content_type !== 'uw_ct_site_footer') { $this->assertSession()->linkByHrefExists('/admin/uw-content-moderation/'); } // Test "Menu Settings", "Place in site hierarchy" and "Add menu link". // This is custom WCMS functionality in uw_sites_all. if ($content_type === 'uw_ct_web_page') { $title = $edit['edit-title-0-value']; // This part done as admin. $this->drupalLogin($this->drupalUsers['administrator']); // By default, "Place in site hierarchy" is unchecked. There should be // no menu item. $this->drupalGet('admin/structure/menu/manage/main'); $this->assertSession()->pageTextNotContains($title); // Check "Place in site hierarchy", creating enabled menu item. $edit = [ 'menu[enabled]' => TRUE, // The title defaults via JS to the page title. Specify since no JS. 'menu[title]' => $title, ]; $this->drupalPostForm($url, $edit, 'Save'); $this->drupalGet('admin/structure/menu/manage/main'); $this->assertSession()->pageTextContains($title); $this->assertSession()->pageTextNotContains($title . ' (disabled)'); // Uncheck "Add menu link", making menu item be disabled. $edit = ['menu[place_in_menu]' => FALSE]; $this->drupalPostForm($url, $edit, 'Save'); $this->drupalGet('admin/structure/menu/manage/main'); $this->assertSession()->pageTextContains($title . ' (disabled)'); // Check that home page menu entry can be edited by admin. $this->assertSession()->elementExists('css', '#edit-links-menu-plugin-iduw-base-profilefront-page-enabled'); $this->assertSession()->elementExists('css', '#edit-links-menu-plugin-iduw-base-profilefront-page-weight'); $this->assertSession()->elementExists('css', 'a[href$="/admin/structure/menu/link/uw_base_profile.front_page/edit"]'); // Return to content author. $this->drupalLogin($this->drupalUsers['uw_role_content_author']); // Check that home page menu entry cannot be edited by content author. $this->drupalGet('admin/structure/menu/manage/main'); $this->assertSession()->elementNotExists('css', '#edit-links-menu-plugin-iduw-base-profilefront-page-enabled'); $this->assertSession()->elementNotExists('css', '#edit-links-menu-plugin-iduw-base-profilefront-page-weight'); $this->assertSession()->elementNotExists('css', 'a[href$="/admin/structure/menu/link/uw_base_profile.front_page/edit"]'); } } // Test uw_ct_sidebar. There is no title in the content type, only a node // reference field. $edit = [ // The actual title is ignored, but has to be present. The number in // brackets is used as the nid of the page to attach this sidebar to. 'edit-field-uw-attach-page-0-target-id' => 'Title (1)', ]; $this->drupalPostForm('node/add/uw_ct_sidebar', $edit, 'Save'); // Make sure no 'Revert to defaults' button on sidebar layout page. $this->assertSession()->buttonNotExists('Revert to defaults'); // Verify that the user is redirected to the layout edit page. $this->assertSession()->addressMatches('/^\/[a-z0-9-\/]+\/layout$/'); $this->assertSession()->pageTextContains('You are editing the layout for this Sidebar content item.'); // On home page, most users do not have content moderation link. $this->drupalGet(''); $this->assertSession()->linkByHrefNotExists('/admin/uw-content-moderation/'); // Grant permission and the user has access. user_role_grant_permissions('uw_role_content_author', ['bypass home page protection']); $this->drupalGet(''); $this->assertSession()->linkByHrefExists('/admin/uw-content-moderation/'); // On home page, admin has content moderation link. $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet(''); $this->assertSession()->linkByHrefExists('/admin/uw-content-moderation/'); // Check access for moderation form. $this->clickLink('Unpublish this content'); $this->assertSession()->statusCodeEquals(200); $url = $this->getSession()->getCurrentUrl(); // Check that moderation form URL is in the expected format. $match = preg_match(',/admin/uw-content-moderation/\d+/\d+/\d+$,', $url); $this->assert($match, 'Moderation form URL is in the expected format.'); // Test home page protection. // // Login as Site Manager. Test that various controls are available, then // make the page the home page and test again. Also test // UWService::nodeIsHomePage(). $this->drupalLogin($this->drupalUsers['uw_role_site_manager']); $this->assert(!UWService::nodeIsHomePage($content_nids['uw_ct_web_page']), 'UWService::nodeIsHomePage() correctly identifies page as not the home page.'); // Test that certain options are available when not editing home page. $this->drupalGet('node/' . $content_nids['uw_ct_web_page'] . '/edit'); $this->assertSession()->elementExists('css', '#edit-path-0'); // Cannot test for #edit-menu because an empty 'div' with that exists. $this->assertSession()->elementExists('css', '#edit-menu-enabled'); $this->assertSession()->elementExists('css', '#edit-menu-place-in-menu'); // Test that the home page cannot be the parent of any item. $this->assertSession()->elementNotExists('css', 'option[value="main:uw_base_profile.front_page"]'); // Delete link exists. $this->assertSession()->elementExists('css', 'a#edit-delete'); // Access to delete page. $this->drupalGet('node/' . $content_nids['uw_ct_web_page'] . '/delete'); $this->assertSession()->statusCodeEquals(200); // Make the page the home page. $path = \Drupal::service('path_alias.manager')->getAliasByPath('/node/' . $content_nids['uw_ct_web_page']); \Drupal::service('config.factory')->getEditable('system.site')->set('page.front', $path)->save(); $this->assert(UWService::nodeIsHomePage($content_nids['uw_ct_web_page']), 'UWService::nodeIsHomePage() correctly identifies page as the home page.'); // Test that certain options are not available when editing home page. $this->drupalGet('node/' . $content_nids['uw_ct_web_page'] . '/edit'); $this->assertSession()->elementNotExists('css', '#edit-path-0'); $this->assertSession()->elementNotExists('css', '#edit-promote-wrapper'); $this->assertSession()->elementNotExists('css', '#edit-sticky-wrapper'); // Cannot test for #edit-menu because an empty 'div' with that exists. $this->assertSession()->elementNotExists('css', '#edit-menu-enabled'); $this->assertSession()->elementNotExists('css', '#edit-menu-place-in-menu'); // Test that the home page cannot be the parent of any item. $this->assertSession()->elementNotExists('css', 'option[value="main:uw_base_profile.front_page"]'); // No delete link. $this->assertSession()->elementNotExists('css', 'a#edit-delete'); // No access to delete page. $this->drupalGet('node/' . $content_nids['uw_ct_web_page'] . '/delete'); $this->assertSession()->statusCodeEquals(403); // Test that admin has access to all Layout Builder configuration paths // and site manager has access to only some paths. $layout_builder_lock_test_users = [ 'administrator', 'uw_role_site_manager', ]; $layout_builder_lock_test_content_types = [ 'uw_ct_blog', 'uw_ct_event', 'uw_ct_news_item', ]; foreach ($layout_builder_lock_test_users as $user) { $this->drupalLogin($this->drupalUsers[$user]); foreach ($layout_builder_lock_test_content_types as $content_type) { $nid = $content_nids[$content_type]; $this->drupalGet('node/' . $nid . '/layout'); $paths = [ 'layout_builder/choose/section/overrides/node.' . $nid . '/0' => FALSE, 'layout_builder/choose/section/overrides/node.' . $nid . '/1' => TRUE, 'layout_builder/choose/section/overrides/node.' . $nid . '/2' => TRUE, 'layout_builder/choose/section/overrides/node.' . $nid . '/3' => FALSE, 'layout_builder/configure/section/overrides/node.' . $nid . '/0' => FALSE, 'layout_builder/configure/section/overrides/node.' . $nid . '/1' => TRUE, 'layout_builder/configure/section/overrides/node.' . $nid . '/2' => FALSE, ]; foreach ($paths as $path => $access) { if ($access || $user === 'administrator') { $this->assertSession()->linkByHrefExists($path); } else { $this->assertSession()->linkByHrefNotExists($path); } } } // Test Layout Builder configuration paths for catalog item content type. // catalog item content type only has one configure section and the above // content types have three configure sections (1, 2, 3). $nid = $content_nids['uw_ct_catalog_item']; $this->drupalGet('node/' . $nid . '/layout'); $paths = [ 'layout_builder/choose/section/overrides/node.' . $nid . '/0' => TRUE, 'layout_builder/choose/section/overrides/node.' . $nid . '/1' => FALSE, 'layout_builder/configure/section/overrides/node.' . $nid . '/0' => FALSE, ]; foreach ($paths as $path => $access) { if ($access || $user === 'administrator') { $this->assertSession()->linkByHrefExists($path); } else { $this->assertSession()->linkByHrefNotExists($path); } } } } /** * Test taxonomies. */ private function taxonomies() { $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_faculties_and_schools/overview'); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_audience/overview'); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_catalogs/overview'); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_catalog_categories/overview'); $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/config/search/path'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('/catalogs/faculties-and-schools/faculty-'); $this->assertSession()->pageTextContains('/audience/current-'); $this->assertSession()->pageTextContains('/events/types/'); $this->drupalGet('admin/config/search/path/patterns'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Audience path pattern'); $this->assertSession()->pageTextContains('Vocabulary is uw_vocab_audience'); $this->assertSession()->pageTextContains('Catalogs path pattern'); $this->assertSession()->pageTextContains('Vocabulary is uw_vocab_catalogs'); $this->assertSession()->pageTextContains('Catalog categories path pattern'); $this->assertSession()->pageTextContains('Vocabulary is uw_vocab_catalog_categories'); $this->assertSession()->pageTextContains('Faculties and schools path pattern'); $this->assertSession()->pageTextContains('Vocabulary is uw_vocab_faculties_and_schools'); // Make sure URL alias fields off of taxonomy forms for all vocabularies. $vocabs = [ 'uw_vocab_audience', 'uw_vocab_blog_tags', 'uw_vocab_catalog_categories', 'uw_vocab_catalogs', 'uw_tax_event_tags', 'uw_tax_event_type', 'uw_vocab_faculties_and_schools', 'uw_vocab_news_tags', ]; foreach ($vocabs as $vocab) { // Load the term-add page. $this->drupalGet('admin/structure/taxonomy/manage/' . $vocab . '/add'); $this->assertSession()->statusCodeEquals(200); // Check if URL alias field is off of taxomoy form. $this->assertSession()->pageTextNotContains('Generate automatic URL alias'); $this->assertNoFieldById('edit-path-0-pathauto'); $this->assertSession()->pageTextNotContains('URL alias'); $this->assertNoFieldById('edit-path-0-alias'); } } /** * Catalog tests. * * Case 1: Make sure workflows exist. * Case 2: Make sure roles at default install are set up as expected. * Case 3: Make sure "preview" button does not exist. */ private function catalogTest() { // Make sure work flows exist. $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet('admin/config/workflow/workflows/manage/uw_workflow'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Catalog item'); // Make sure only 'Basic' format is checked. $this->drupalGet('admin/structure/types/manage/uw_ct_catalog_item/fields/node.uw_ct_catalog_item.field_uw_catalog_summary'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-third-party-settings-allowed-formats-uw-tf-basic'); $this->assertSession()->checkboxNotChecked('edit-third-party-settings-allowed-formats-uw-tf-standard'); $this->assertSession()->checkboxNotChecked('edit-third-party-settings-allowed-formats-uw-tf-full-html'); $this->assertSession()->checkboxNotChecked('edit-third-party-settings-allowed-formats-plain-text'); // Make sure catalog term path pattern. $this->drupalGet('admin/config/search/path/patterns/uw_path_catalogs'); $this->assertSession()->statusCodeEquals(200); $this->getSession()->getPage()->findField('edit-type')->getValue('Taxonomy term'); $this->getSession()->getPage()->findField('edit-pattern')->getValue('catalogs/[term:name]'); $this->assertSession()->checkboxChecked('edit-bundles-uw-vocab-catalogs'); $this->getSession()->getPage()->findField('edit-label')->getValue('Catalogs path pattern'); $this->assertSession()->checkboxChecked('edit-status'); // Make sure taxonomy views integrator settings in uw_vocab_catalogs. $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_catalogs'); $this->assertSession()->statusCodeEquals(200); $tvi = $this->getSession()->getPage()->find('xpath', "//span[contains(text(), 'Taxonomy Views Integrator Settings')]"); $this->assertEquals('edit-tvi', $tvi->getParent()->getParent()->getAttribute('id')); $this->assertSession()->checkboxChecked('edit-tvi-enable-override'); $this->assertOptionSelected('edit-tvi-view', 'uw_view_catalog_show_nodes'); $this->assertOptionSelected('edit-tvi-view-display', 'catalog_a_z_page'); $this->assertSession()->checkboxChecked('tvi-inherit-check'); $this->assertSession()->checkboxChecked('tvi-pass-arguments'); // Make sure 'Tabs to display' field in uw_vocab_catalogs. $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_catalogs/overview/fields'); $this->assertSession()->statusCodeEquals(200); $elements = $this->xpath('//div[@id="block-uw-theme-admin-mainpagecontent"] //table/tbody/tr[@id="field-uw-catalog-tabs-display"]/td'); $expected_items = [ 'Tabs to display', 'field_uw_catalog_tabs_display', 'List (text)', ]; foreach ($expected_items as $key => $value) { $this->assertEqual($elements[$key]->getText(), $value); } // Make sure 'Tabs to display' field in creating catalog term. // all checkboxes are not checked by default. $this->drupalGet('admin/structure/taxonomy/manage/uw_vocab_catalogs/add'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Tabs to display'); $keys = [ 'new', 'popular', 'category', 'audience', 'faculty', ]; foreach ($keys as $key) { $this->assertEquals('edit-field-uw-catalog-tabs-display', $this->getSession()->getPage()->findById('edit-field-uw-catalog-tabs-display-' . $key)->getParent()->getParent()->getAttribute('id')); $this->assertSession()->checkboxNotChecked('edit-field-uw-catalog-tabs-display-' . $key); } // Make sure roles at default install are set up as expected. $roles = [ 'uw_role_content_author', 'uw_role_content_editor', 'uw_role_site_manager', ]; foreach ($roles as $role) { // Login as the given role. $this->drupalLogin($this->drupalUsers[$role]); // Prepare $edit for catalog term name. $edit = [ 'edit-name-0-value' => $this->randomString(), ]; // Create a catalog term based on the above catalog term name. $this->drupalPostForm('admin/structure/taxonomy/manage/uw_vocab_catalogs/add', $edit, $this->t('Save')); // Prepare $edit for catalog categories term name. $edit = [ 'edit-name-0-value' => $this->randomString(), ]; // Create a catalog categories term based on the above catalog term name. $this->drupalPostForm('admin/structure/taxonomy/manage/uw_vocab_catalog_categories/add', $edit, $this->t('Save')); // Prepare $edit for catalog item node. $edit = [ 'edit-title-0-value' => $this->randomString(), 'edit-field-uw-catalog-summary-0-value' => $this->randomString(), 'edit-moderation-state-0-state' => 'uw_wf_needs_review', ]; // Create a catalog item node. $this->drupalPostForm('node/add/uw_ct_catalog_item', $edit, 'Save'); } $this->drupalLogin($this->drupalUsers['uw_role_site_manager']); // Create the first taxonomy term which the vocab is // catalog and the tid should be 35. $editCatalog = [ 'edit-name-0-value' => $this->randomMachineName(), ]; $this->drupalPostForm('admin/structure/taxonomy/manage/uw_vocab_catalogs/add', $editCatalog, $this->t('Save')); // Create the second taxonomy term which the vocab is // category and the tid should be 36. $editCategory = [ 'edit-name-0-value' => 'apple', ]; $this->drupalPostForm('admin/structure/taxonomy/manage/uw_vocab_catalog_categories/add', $editCategory, $this->t('Save')); // Prepare $editNode for creating a catalog item node. // Use tid=35 as catalog term and tid=36 (apple) as category term. // Select tid=15 (faculty of arts) as faculty term. // Select tid=8 (Staff) as audience term. $editNode = [ 'edit-title-0-value' => 'Test catalog item', 'edit-field-uw-catalog-catalog-35' => 35, 'edit-field-uw-catalog-summary-0-value' => $this->randomString(), 'edit-moderation-state-0-state' => 'uw_wf_needs_review', ]; // Create a catalog item node with needs review. $this->drupalPostForm('node/add/uw_ct_catalog_item', $editNode, 'Save'); // Check node title. $this->assertSession()->pageTextContains('Edit layout for Test catalog item'); // Check that there is no moderation form. $this->assertSession()->linkByHrefNotExists('/admin/uw-content-moderation/'); // Make sure no 'Revert to default' on the above content type layout page. $this->assertSession()->buttonNotExists('Revert to defaults'); $this->assertSession()->buttonExists('Save layout'); // Check all paths related to catalog views exist. $this->drupalGet('catalogs'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Your filters returned no results please review criteria selected.'); $paths = [ 'taxonomy/term/35', 'taxonomy/term/35/new', 'taxonomy/term/35/popular', 'taxonomy/term/35/audience', 'taxonomy/term/35/category', 'taxonomy/term/35/faculty', 'taxonomy/term/35/audience/staff', 'taxonomy/term/35/category/apple', 'taxonomy/term/35/faculty/faculty-of-arts', ]; foreach ($paths as $path) { $this->drupalGet($path); $this->assertSession()->statusCodeEquals(200); // There is no published catalog item node existing. $this->assertSession()->pageTextContains('Your filters returned no results please review criteria selected.'); } // Make sure Metatags display extender is enabled. $views_display_extender_settings = \Drupal::config('views.settings')->get('display_extenders'); $this->assert(in_array('metatag_display_extender', $views_display_extender_settings), 'The metatags display extender is expected to be enabled.'); } /** * Test schema_metatag. */ private function schemaTest() { // Make sure the below modules are enabled. $modules = [ 'schema_article' => 'Schema.org Article', 'schema_event' => 'Schema.org Event', 'schema_metatag' => 'Schema.org Metatag', 'schema_organization' => 'Schema.org Organization', 'schema_service' => 'Schema.org Service', 'schema_web_page' => 'Schema.org WebPage', ]; foreach ($modules as $key => $module) { $enabled = \Drupal::moduleHandler()->moduleExists($key); $this->assertTrue($enabled, $module . ' module is not enabled.'); } // Make sure the below path exists. $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet('admin/config/search/metatag/settings'); $this->assertSession()->statusCodeEquals(200); // Make sure content blog post some are checked, and some are not checked. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-schema-service'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-blog-0-schema-web-page'); // Make sure content catalog item some are checked, and some are not. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-schema-web-page'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-catalog-item-0-schema-service'); // Make sure content contact some are checked, and some are not. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-schema-service'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-contact-0-schema-web-page'); // Make sure content event some are checked, and some are not checked. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-schema-service'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-event-0-schema-web-page'); // Make sure content news item some are checked, and some are not checked. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-schema-service'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-news-item-0-schema-web-page'); // Make sure content profile some are checked, and some are not. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-schema-service'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-profile-0-schema-web-page'); // Make sure content web page some are checked, and some are not checked. $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-basic'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-advanced'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-open-graph'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-twitter-cards'); $this->assertFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-schema-web-page'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-schema-article'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-schema-event'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-schema-organization'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-schema-person'); $this->assertNoFieldChecked('edit-entity-type-groups-node-uw-ct-web-page-0-schema-service'); // Make sure meta tag info fields exist when // add a node of the given content type. $types = $this->getContentTypes(TRUE); foreach ($types as $type) { $this->drupalGet('node/add/' . $type); $this->assertSession()->statusCodeEquals(200); $this->assertFieldById('edit-field-uw-meta-description-0-value'); $this->assertSession()->buttonExists('edit-field-uw-meta-image-open-button'); } } /** * Test config block. * * Test help text of Block ID and hiding url alias. * Test timeline block. */ private function configBlockTest() { $this->drupalLogin($this->drupalUsers['administrator']); $blocks = [ 'Blockquote', 'Call to action', 'CodePen', 'Copy text', 'Facebook', 'Facts and figures', 'Full width image', 'Google Maps', 'Image gallery', 'Instagram', 'Mailman subscription', 'PowerBI', 'Related links', 'Remote video', 'Tableau visualization', 'Timeline', 'Twitter', ]; foreach ($blocks as $block) { $this->drupalGet('node/1/layout'); $this->assertSession()->statusCodeEquals(200); // On the layout edit page to click 'Add block'. $this->clickLink('Add block'); // Verify that Blockquote and others are on the layout edit page. $this->assertSession()->pageTextContains('Choose a block'); // Click 'Blockquote'. $this->clickLink($block); // Show Configure block. $this->drupalPlaceBlock('layout_builder_add_block'); // Check help text of Block ID. $this->assertSession()->pageTextContains('Block ID is an optional setting which is used to support an anchor link to this block'); // Check if URL alias field exists. $this->assertSession()->pageTextNotContains('Generate automatic URL alias'); $this->assertSession()->pageTextNotContains('URL alias'); // Test specific blocks. switch ($block) { case 'CodePen': // Create CodePen block. $edit = [ 'edit-settings-label' => $this->randomString(), // Letters only, 6-7 characters. 'edit-settings-block-form-field-codepen-id-0-value' => substr(preg_replace('/[^a-zA-Z]+/', '', $this->randomMachineName(24)), 0, 7), 'edit-settings-block-form-field-codepen-username-0-value' => $this->randomMachineName(), 'edit-settings-block-form-field-codepen-displayed-author-0-value' => $this->randomString(), // Double-quote not possible because it will make the XPath invalid // later in this test. In normal use, double-quote would be allowed. 'edit-settings-block-form-field-codepen-displayed-title-0-value' => str_replace('"', '', $this->randomString()), 'edit-settings-block-form-field-codepen-default-tabs' => 'result', 'edit-settings-block-form-field-codepen-pixel-height-0-value' => rand(150, 1000), ]; $this->submitForm($edit, 'Add block'); // Test that the CodePen block markup appears on the page. $this->assertSession()->pageTextContains($edit['edit-settings-label']); $this->assertFieldByXPath('//div[@class="uw-codepen"]/div[ @class="codepen" and @data-height="' . $edit['edit-settings-block-form-field-codepen-pixel-height-0-value'] . '" and @data-theme-id="dark" and @data-slug-hash="' . $edit['edit-settings-block-form-field-codepen-id-0-value'] . '" and @data-default-tab="' . $edit['edit-settings-block-form-field-codepen-default-tabs'] . '" and @data-user="' . $edit['edit-settings-block-form-field-codepen-username-0-value'] . '" and @data-pen-title="' . $edit['edit-settings-block-form-field-codepen-displayed-title-0-value'] . '" and @data-preview="true" ]/a[@href="https://codepen.io/' . $edit['edit-settings-block-form-field-codepen-username-0-value'] . '/pen/' . $edit['edit-settings-block-form-field-codepen-id-0-value'] . '/"]'); $this->assertFieldByXPath('//div[@class="uw-codepen"]/script[@src="https://static.codepen.io/assets/embed/ei.js"]'); break; case 'Google Maps': // Create Google Maps block. $edit = [ 'edit-settings-label' => $this->randomString(), 'edit-settings-block-form-field-gmaps-embedded-url-0-uri' => 'https://www.google.com/maps/embed?pb=' . $this->randomMachineName(), 'edit-settings-block-form-field-gmaps-height-0-value' => rand(150, 1000), ]; $this->submitForm($edit, 'Add block'); // Test that the Google Maps block markup appears on the page. $this->assertSession()->pageTextContains($edit['edit-settings-label']); $this->assertFieldByXPath('//div[@class="uw-google-maps"]/div[text()="Enable JavaScript to view map."]'); $this->assertFieldByXPath('//div[@class="uw-google-maps"]/iframe[@height="' . $edit['edit-settings-block-form-field-gmaps-height-0-value'] . '" and @src="' . $edit['edit-settings-block-form-field-gmaps-embedded-url-0-uri'] . '"]'); break; case 'PowerBI': // Create PowerBI block. $edit = [ 'edit-settings-label' => $this->randomString(), 'edit-settings-block-form-field-uw-powerbi-url-0-value' => 'https://app.powerbi.com/' . $this->randomMachineName(), ]; $this->submitForm($edit, 'Add block'); // Test that the PowerBI block markup appears on the page. $this->assertSession()->pageTextContains($edit['edit-settings-label']); $this->assertFieldByXPath('//div[@class="uw-powerbi"]/iframe[@src="' . $edit['edit-settings-block-form-field-uw-powerbi-url-0-value'] . '"]'); break; case 'Related links': // Add a second link. $this->click('#edit-settings-block-form-field-uw-rl-related-link-add-more'); // Create Related links block. $edit = [ 'edit-settings-label' => $this->randomString(), // Internal link. 'edit-settings-block-form-field-uw-rl-related-link-0-uri' => 'entity:node/1', 'edit-settings-block-form-field-uw-rl-related-link-0-title' => 'should-not-appear--uses-node-title', // External link. 'edit-settings-block-form-field-uw-rl-related-link-1-uri' => 'https://www.sju.ca/', // This needs to use randomMachineName() so that it has not // double-quotes, which cannot be in XPath. 'edit-settings-block-form-field-uw-rl-related-link-1-title' => $this->randomMachineName(), ]; $this->submitForm($edit, 'Add block'); // Test that the Related links block markup appears on the page. $this->assertSession()->pageTextContains($edit['edit-settings-label']); // Internal link. $xpath_prefix = '//div[contains(@class, "block-inline-blockuw-cbl-related-links")]/div[@class="item-list"]/ul/li'; $this->assertFieldByXPath($xpath_prefix . '/a[@href="' . base_path() . 'home" and text()="Home"]'); $this->assertSession()->pageTextNotContains($edit['edit-settings-block-form-field-uw-rl-related-link-0-title']); // External link. $this->assertFieldByXPath($xpath_prefix . '/a[@href="' . $edit['edit-settings-block-form-field-uw-rl-related-link-1-uri'] . '" and text()="' . $edit['edit-settings-block-form-field-uw-rl-related-link-1-title'] . '"]'); unset($xpath_prefix); break; case 'Tableau visualization': // Create Tableau block. $edit = [ 'edit-settings-label' => $this->randomString(), 'edit-settings-block-form-field-uw-tbl-server' => 'Public', 'edit-settings-block-form-field-uw-tbl-site-name-0-value' => $this->randomMachineName(), 'edit-settings-block-form-field-uw-tbl-tableau-name-0-value' => $this->randomMachineName(), 'edit-settings-block-form-field-uw-tbl-tableau-height-0-value' => rand(100, 1000), 'edit-settings-block-form-field-uw-tbl-display-tabs' => 'Yes', ]; $this->submitForm($edit, 'Add block'); // Test that the appropriate Tableau block markup appears on the page. $this->assertSession()->pageTextContains($edit['edit-settings-label']); $this->assertFieldByXPath('//object[@class="tableauViz"]/param[@name="host_url" and @value="https://public.tableau.com/"]'); $this->assertFieldByXPath('//object[@class="tableauViz"]/param[@name="site_root" and @value="' . $edit['edit-settings-block-form-field-uw-tbl-site-name-0-value'] . '"]'); $this->assertFieldByXPath('//object[@class="tableauViz"]/param[@name="name" and @value="' . $edit['edit-settings-block-form-field-uw-tbl-tableau-name-0-value'] . '"]'); $this->assertFieldByXPath('//object[@class="tableauViz"]/param[@name="tabs" and @value="yes"]'); $this->assertFieldByXPath('//div[@class="uw-tableau__wrapper"]/script'); $this->assertRaw("vizElement.style.height = '" . $edit['edit-settings-block-form-field-uw-tbl-tableau-height-0-value'] . "px';"); break; } } // Test timeline Step 1: Visit the home page layout. $this->drupalGet('node/1/layout'); $this->assertSession()->statusCodeEquals(200); // Test timeline Step 2: Look on the layout edit page to click 'Add block'. $this->clickLink('Add block'); // Test timeline Step 3: Verify that Blockquote and others are on the // layout edit page. $this->assertSession()->pageTextContains('Choose a block'); // Test timeline Step 4: Look on the page for the 'Timeline' link. $this->assertSession()->linkExists('Timeline'); // Test timeline Step 5: Click 'Timeline'. $this->clickLink('Timeline'); // Test timeline Step 6: Show Configure block (pop-up window). $this->drupalPlaceBlock('layout_builder_add_block'); // Test timeline Step 7: Check all fields and buttons of timeline block. $this->assertSession()->pageTextContains('Title'); $this->assertFieldById('edit-settings-label'); $this->assertSession()->pageTextContains('Timeline style'); $this->assertFieldById('edit-settings-block-form-field-uw-timeline-style'); $this->assertSession()->pageTextContains('Timeline sort'); $this->assertFieldById('edit-settings-block-form-field-uw-timeline-sort'); $this->assertSession()->pageTextContains('Date'); $this->assertFieldById('edit-settings-block-form-field-uw-timeline-0-subform-field-uw-timeline-date-0-value-date'); $this->assertSession()->pageTextContains('Headline'); $this->assertFieldById('edit-settings-block-form-field-uw-timeline-0-subform-field-uw-timeline-headline-0-value'); $this->assertSession()->pageTextContains('One or both of the "Headline" and "Content" fields must be populated.'); $this->assertSession()->pageTextContains('PHOTO'); $this->assertSession()->buttonExists('Add media'); $this->assertSession()->pageTextContains('One media item remaining.'); $this->assertSession()->pageTextContains('Link'); $this->assertSession()->pageTextContains('Links the entire content to a URL. If entered, do not use links inside the content itself.'); $this->assertSession()->pageTextContains('Content'); $this->assertSession()->buttonExists('Add Timeline'); } /** * Test preview button option. */ private function previewButtonTest() { // Administrator login. $this->drupalLogin($this->drupalUsers['administrator']); // Add new content type. $this->drupalGet('admin/structure/types/add'); // Test that "Preview before submitting" is set to "Disabled". $this->assertFieldChecked('edit-preview-mode-0'); $this->assertNoFieldChecked('edit-preview-mode-1'); $this->assertNoFieldChecked('edit-preview-mode-2'); $types = $this->getContentTypes(); foreach ($types as $type) { // Load the node-add page. $this->drupalGet('node/add/' . $type); // Preview button doesn't exist. $this->assertSession()->buttonNotExists('edit-preview'); } } /** * A function to get all UW content types. * * @param bool $filter * When TRUE, return only content types that have metatag enabled. * * @return array * An array of all UW content types filtered by TRUE/FALSE. */ public function getContentTypes(bool $filter = FALSE): array { // This is the list of all UW content types, with a TRUE/FALSE, indicating // whether or not a metatag tag can be attached to this content type. $content_types = [ 'uw_ct_blog' => TRUE, 'uw_ct_catalog_item' => TRUE, 'uw_ct_contact' => TRUE, 'uw_ct_event' => TRUE, 'uw_ct_news_item' => TRUE, 'uw_ct_profile' => TRUE, 'uw_ct_sidebar' => FALSE, 'uw_ct_site_footer' => FALSE, 'uw_ct_web_page' => TRUE, ]; $return_content_types = []; foreach ($content_types as $key => $value) { if (($filter && $value) || !$filter) { $return_content_types[] = $key; } } return $return_content_types; } /** * Test Layout Builder Browser. * * Test Layout builder browser configuration and its weights. */ private function layoutBuilderBrowserTest() { // Administrator login. $this->drupalLogin($this->drupalUsers['administrator']); // Go to Layout Builder Browser configuration page. $this->drupalGet('admin/config/content/layout-builder-browser'); $this->assertSession()->statusCodeEquals(200); // Items include Content, External embeds, Listings, // Searches, Teasers and Webforms, and blocks related. $items = [ '.region-title-uw_bc_content', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-blockquote"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-call-to-action"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-copy-text"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-facts-and-figures"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-image"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-mailman"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-related-links"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-timeline"]', '.region-title-uw_bc_external_embeds', 'tr[data-drupal-selector="edit-categories-uw-lbb-facebook"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-google-maps"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-instagram"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-powerbi"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-remote-video"]', 'tr[data-drupal-selector="edit-categories-inline-blockuw-cbl-tableau"]', 'tr[data-drupal-selector="edit-categories-uw-lbb-twitter"]', '.region-title-uw_bc_listings', 'tr[data-drupal-selector="edit-categories-uw-cbl-multi-type-list"]', 'tr[data-drupal-selector="edit-categories-views-blockuw-view-blogs-blogs-listing-block"]', 'tr[data-drupal-selector="edit-categories-views-blockuw-view-events-events-listing-block"]', 'tr[data-drupal-selector="edit-categories-views-blockuw-view-news-items-news-items-listing-block"]', '.region-title-uw_bc_searches', '.region-title-uw_bc_teasers', 'tr[data-drupal-selector="edit-categories-uw-cbl-blog-teaser"]', 'tr[data-drupal-selector="edit-categories-uw-cbl-event-teaser"]', 'tr[data-drupal-selector="edit-categories-uw-cbl-news-teaser"]', '.region-title-uw_bc_webforms', 'tr[data-drupal-selector="edit-categories-webform-block"]', ]; foreach ($items as $item) { $this->assertSession()->elementExists('css', $item); } } /** * Test global footer. * * Test update territorial acknowledgement. * Test update the 'Media' link to read 'News'. */ private function globalFooterTest() { $this->drupalGet(''); $this->assertSession()->statusCodeEquals(200); // Find all 'News' links. $news = $this->getSession()->getPage()->findAll('xpath', "//span[contains(text(), 'News')]"); // Current we have two 'News' links. $this->assertCount(2, $news); // Make sure the second 'News' link is 'uwaterloo.ca/news'. $this->assertEquals('https://uwaterloo.ca/news/', $news[1]->getParent()->getAttribute('href')); // Media link doesn't exist. $this->assertSession()->linkNotExists('Media'); // 'the land granted to the Six Nations' can be found. $this->assertSession()->pageTextContains('the land granted to the Six Nations'); } /** * Test menu links. * * Test content management menu links. * Test site information menu links. */ private function menusTest() { // Administrator login. $this->drupalLogin($this->drupalUsers['administrator']); // Go to content management menu links. $this->drupalGet('admin/structure/menu/manage/uw-menu-content-management'); $this->assertSession()->statusCodeEquals(200); // Check content management menu links. $content_links = [ 'node/add/uw_ct_blog' => 'Blog post', 'admin/structure/taxonomy/manage/uw_vocab_blog_tags/add' => 'Add blog tag', 'admin/structure/taxonomy/manage/uw_vocab_blog_tags/overview' => 'List blog tags', 'node/add/uw_ct_catalog_item' => 'Catalog item', 'admin/structure/taxonomy/manage/uw_vocab_catalog_categories/add' => 'Add catalog category', 'admin/structure/taxonomy/manage/uw_vocab_catalogs/add' => 'Add catalog', 'admin/structure/taxonomy/manage/uw_vocab_catalog_categories/overview' => 'List catalog categories', 'admin/structure/taxonomy/manage/uw_vocab_catalogs/overview' => 'List catalogs', 'node/add/uw_ct_event' => 'Event', 'admin/structure/taxonomy/manage/uw_tax_event_tags/add' => 'Add event tag', 'admin/structure/taxonomy/manage/uw_tax_event_type/add' => 'Add event type', 'admin/structure/taxonomy/manage/uw_tax_event_tags/overview' => 'List event tags', 'admin/structure/taxonomy/manage/uw_tax_event_type/overview' => 'List event types', 'node/add/uw_ct_news_item' => 'News item', 'admin/structure/taxonomy/manage/uw_vocab_news_tags/add' => 'Add news tag', 'admin/structure/taxonomy/manage/uw_vocab_news_tags/overview' => 'List news tags', 'node/add/uw_ct_sidebar' => 'Sidebar', 'node/add/uw_ct_site_footer' => 'Site footer', 'node/add/uw_ct_web_page' => 'Web page', 'admin/structure/webform/add' => 'Form', 'admin/structure/webform/submissions/manage' => 'Manage submissions', 'admin/structure/taxonomy/manage/uw_vocab_audience/add' => 'Audience', 'admin/structure/taxonomy/manage/uw_vocab_audience/overview' => 'List terms', /* Conflicting links Manage, there is one found in admin top bar. 'admin/structure/taxonomy/manage/uw_vocab_audience' => 'Manage', */ ]; foreach ($content_links as $key => $item) { $this->assertSession()->linkExists($item); $this->assertEquals(base_path() . $key, $this->getSession()->getPage()->findLink($item)->getAttribute('href')); } // Go to site information menu links. $this->drupalGet('admin/structure/menu/manage/uw-menu-site-management'); $this->assertSession()->statusCodeEquals(200); // Check site information menu links. $site_links = [ base_path() . 'admin/content-access' => 'Content access', base_path() . 'admin/config/search/redirect/404' => 'Fix 404 pages', base_path() . 'admin/structure/menu' => 'Menus', base_path() . 'admin/config/user-interface/shortcut' => 'Shortcuts', base_path() . 'admin/config/search/redirect' => 'Redirects', 'mailto:rt-ist-wcms@rt.uwaterloo.ca' => 'Submit request', 'https://uwaterloo.ca/web-resources/wcms-users/training-and-support/wcms-how-documents' => 'WCMS how-to documents', ]; foreach ($site_links as $key => $item) { $this->assertSession()->linkExists($item); $this->assertEquals($key, $this->getSession()->getPage()->findLink($item)->getAttribute('href')); } // Test that main menu has weight of -51. $this->drupalGet('admin/structure/menu/link/uw_base_profile.front_page/edit'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->elementExists('css', 'input#edit-weight[value="-51"]'); $this->drupalLogin($this->drupalUsers['uw_role_site_manager']); // No access to edit home page menu entry. $this->drupalGet('admin/structure/menu/link/uw_base_profile.front_page/edit'); $this->assertSession()->statusCodeEquals(403); // Test that the home page cannot be the parent of any item. $this->drupalGet('admin/structure/menu/link/uw_main_menu.blog/edit'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->elementExists('css', 'select#edit-menu-parent'); $this->assertSession()->elementNotExists('css', 'select#edit-menu-parent > option[value="main:uw_base_profile.front_page"]'); // Test that main menu has disabled Catalogs menu link. $this->drupalGet('admin/structure/menu/manage/main'); $this->assertSession()->statusCodeEquals(200); $this->assertEquals(base_path() . 'catalogs', $this->getSession()->getPage()->findLink('Catalogs')->getAttribute('href')); $this->assertSession()->checkboxNotChecked('edit-links-menu-plugin-iduw-main-menucatalogs-enabled'); } /** * Test dashboard. * * Test default dashboard. */ private function dashboardTest() { // Anonymous user cannot view "Who's online" block in dashboard. if ($this->loggedInUser) { $this->drupalLogout(); } $this->drupalGet('dashboard/my_dashboard'); $this->assertSession()->statusCodeEquals(403); // "Who's online" block can be viewed by all roles. $roles = [ 'authenticated user', 'uw_role_site_owner', 'uw_role_site_manager', 'uw_role_content_editor', 'uw_role_content_author', 'uw_role_form_editor', 'uw_role_form_results_access', 'administrator', ]; foreach ($roles as $role) { $this->drupalLogin($this->drupalUsers[$role]); $this->drupalGet('dashboard/my_dashboard'); if ($role != 'authenticated user') { $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains("Who's online"); if ($role == 'administrator' || $role == 'uw_role_site_owner') { $this->assertSession()->linkExists('People'); $this->assertSession()->linkExists('Reports'); } else { $this->assertSession()->linkNotExists('People'); $this->assertSession()->linkNotExists('Reports'); } } else { $this->assertSession()->statusCodeEquals(403); } } // Site footer button label is 'Add/edit'. $this->assertSession()->linkExists('Add/edit'); $siteFooterlink = $this->getSession()->getPage()->find('xpath', "//a[contains(text(), 'Add/edit')]"); $this->assertEquals(base_path() . 'node/add/uw_ct_site_footer', $siteFooterlink->getAttribute('href')); // 'web-resources-news', 'recent-content' and 'whos-online' // are under 'layout--uw-3-col even-split', the rest four // are under 'layout--uw-2-col larger-left'. $ids = [ 'web-resources-news' => 'uw-full-width layout layout--uw-3-col even-split', 'recent-content' => 'uw-full-width layout layout--uw-3-col even-split', 'whos-online' => 'uw-full-width layout layout--uw-3-col even-split', 'content-list' => 'uw-full-width layout layout--uw-2-col larger-left', 'forms-list' => 'uw-full-width layout layout--uw-2-col larger-left', 'content-management-menu' => 'uw-full-width layout layout--uw-2-col larger-left', 'site-management-menu' => 'uw-full-width layout layout--uw-2-col larger-left', ]; foreach ($ids as $key => $id) { $class = $this->getSession()->getPage()->findById($key)->getParent()->getParent()->getAttribute('class'); $this->assertEquals($id, $class, "Failed looking up: $key"); } // In section one, the first column is 'web-resources-news', the second is // 'recent-content', and the third is 'whos-online'. // In section two, the first column is 'content-list' and 'form-list', // and the second column is 'content-management-menu' and // 'site-management-menu'. $section_ids = [ 'web-resources-news' => 'layout__region layout__region--first', 'recent-content' => 'layout__region layout__region--second', 'whos-online' => 'layout__region layout__region--third', 'content-list' => 'layout__region layout__region--first', 'forms-list' => 'layout__region layout__region--first', 'content-management-menu' => 'layout__region layout__region--second', 'site-management-menu' => 'layout__region layout__region--second', ]; foreach ($section_ids as $key => $id) { $class = $this->getSession()->getPage()->findById($key)->getParent()->getAttribute('class'); $this->assertEquals($id, $class, "Failed looking up: $key"); } } /** * Tests for Custom block CTA. */ private function ctaBlockTest() { $this->drupalLogin($this->drupalUsers['administrator']); // Make sure the type of CTA text details doesn't include 'icon' // under Text details settings. $this->drupalGet('admin/structure/paragraphs_type/uw_para_call_to_action/fields/paragraph.uw_para_call_to_action.field_uw_cta_text_details'); $this->assertSession()->statusCodeEquals(200); $small = $this->assertSession()->optionExists('default_value_input[field_uw_cta_text_details][0][style]', 'small'); $this->assertTrue($small); $this->assertEquals('Small', $small->getText()); $medium = $this->assertSession()->optionExists('default_value_input[field_uw_cta_text_details][0][style]', 'medium'); $this->assertTrue($medium); $this->assertEquals('Medium', $medium->getText()); $big = $this->assertSession()->optionExists('default_value_input[field_uw_cta_text_details][0][style]', 'big'); $this->assertTrue($big); $this->assertEquals('Big', $big->getText()); $this->assertSession()->optionNotExists('default_value_input[field_uw_cta_text_details][0][style]', 'icon/image'); // Make sure CTA link field and theme required. $this->drupalGet('admin/structure/paragraphs_type/uw_para_call_to_action/fields/paragraph.uw_para_call_to_action.field_uw_cta_link'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-required'); $this->drupalGet('admin/structure/paragraphs_type/uw_para_call_to_action/fields/paragraph.uw_para_call_to_action.field_uw_cta_theme'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-required'); // Test step 1: Visit the home page layout. $this->drupalGet('node/1/layout'); $this->assertSession()->statusCodeEquals(200); // Test step 2: Look on the layout edit page to click 'Add block'. $this->clickLink('Add block'); // Test step 3: Verify that cta block and others are on the // layout edit page. $this->assertSession()->pageTextContains('Choose a block'); // Test step 4: Look on the page for the 'Call to action' link. $this->assertSession()->linkExists('Call to action'); // Test step 6: Click 'Call to action'. $this->clickLink('Call to action'); // CTA link field and theme field show '*'. $ctalink = $this->getSession()->getPage()->find('xpath', "//label[contains(text(), 'Link')]"); $this->assertEquals('js-form-required form-required', $ctalink->getAttribute('class')); $ctatheme = $this->getSession()->getPage()->find('xpath', "//label[contains(text(), 'Theme')]"); $this->assertEquals('js-form-required form-required', $ctatheme->getAttribute('class')); $this->assertSession()->pageTextNotContains('Link text'); // Make sure the type of CTA text details doesn't include 'icon' // when add 'call to action' block. $small = $this->assertSession()->optionExists('settings[block_form][field_uw_cta_details][0][subform][field_uw_cta_text_details][0][style]', 'small'); $this->assertTrue($small); $this->assertEquals('Small', $small->getText()); $medium = $this->assertSession()->optionExists('settings[block_form][field_uw_cta_details][0][subform][field_uw_cta_text_details][0][style]', 'medium'); $this->assertTrue($medium); $this->assertEquals('Medium', $medium->getText()); $big = $this->assertSession()->optionExists('settings[block_form][field_uw_cta_details][0][subform][field_uw_cta_text_details][0][style]', 'big'); $this->assertTrue($big); $this->assertEquals('Big', $big->getText()); $this->assertSession()->optionNotExists('settings[block_form][field_uw_cta_details][0][subform][field_uw_cta_text_details][0][style]', 'icon/image'); // Use random string as cta label, saving for later compare. $cta_label = $this->randomString(); $this->submitForm([ 'edit-settings-label' => 'Block description title', 'edit-settings-block-form-field-uw-cta-details-0-subform-field-uw-cta-link-0-uri' => '/home', 'edit-settings-block-form-field-uw-cta-details-0-subform-field-uw-cta-text-details-0-text-value' => $cta_label, 'edit-settings-block-form-field-uw-cta-details-0-subform-field-uw-cta-theme' => 'org-default', ], 'Add block'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains($cta_label); } /** * Tests for Custom block FF. */ private function ffBlockTest() { $this->drupalLogin($this->drupalUsers['administrator']); // Test case 1: // Make sure manage fields of uw para fact figure // includes 'Small highlight' with value 'small'. $this->drupalGet('admin/structure/paragraphs_type/uw_para_fact_figure/fields/paragraph.uw_para_fact_figure.field_uw_ff_info'); $this->assertSession()->statusCodeEquals(200); $smallhighlight = $this->assertSession()->optionExists('default_value_input[field_uw_ff_info][0][style]', 'small'); $this->assertTrue($smallhighlight); $this->assertEquals('Small highlight', $smallhighlight->getText()); // Check the configure block by adding facts and figures. $this->drupalGet('node/1/layout'); $this->assertSession()->statusCodeEquals(200); $this->clickLink('Add block'); $this->clickLink('Facts and figures'); // The top-level remove button doesn't exist. $this->assertNoFieldByName('settings_block_form_field_uw_ff_fact_figure_0_remove'); // Check 'Default background colour' field help text. $this->assertSession()->pageTextContains('When gold is selected, the default colour will always be black.'); // Check 'Default background colour' field default value. $this->assertFieldByXPath('//option[@value="grey" and @selected="selected"]', NULL, 'Grey is selected.'); $this->assertFieldByName('settings[block_form][field_uw_ff_fact_figure][0][subform][field_uw_ff_def_color]'); // Select 'gold', then 'Default background colour' field is gone. $this->getSession()->getPage()->selectFieldOption('settings[block_form][field_uw_ff_fact_figure][0][subform][field_uw_ff_dbg_color]', 'gold'); $this->assertTrue($this->assertSession()->optionExists('Default background colour', 'gold')->isSelected()); // Select 'black', then 'Default background colour' field shows. $this->getSession()->getPage()->selectFieldOption('settings[block_form][field_uw_ff_fact_figure][0][subform][field_uw_ff_dbg_color]', 'black'); $this->assertTrue($this->assertSession()->optionExists('Default background colour', 'black')->isSelected()); // The default color is 'Default[uWaterloo]' and not have "none" option. $options = $this->getOptions('settings[block_form][field_uw_ff_fact_figure][0][subform][field_uw_ff_def_color]'); foreach ($options as $option) { $this->assertNotEqual('- None -', $option); } $this->assertFieldByXPath('//option[@value="org-default" and @selected="selected"]', NULL, 'Default uWaterloo is selected.'); // The type includes 'Small highlight' with value 'small'. $smallhighlight = $this->assertSession()->optionExists('settings[block_form][field_uw_ff_fact_figure][0][subform][field_uw_fact_figure][0][subform][field_uw_ff_info][0][style]', 'small'); $this->assertTrue($smallhighlight); $this->assertEquals('Small highlight', $smallhighlight->getText()); } /** * Tests permissions. * * Site owner role has administer users permission. * Site owner role has assign roles permission. * Configure the role assign to allow assigning * all roles except admin and site owner. */ private function permissionsTest() {// phpcs:ignore // Only administer can access permissions and roleassign pages. $this->drupalLogin($this->drupalUsers['administrator']); // Check admin/people/roleassign page. $this->drupalGet('admin/people/roleassign'); $this->assertSession()->statusCodeEquals(200); // Configure the role assign to allow assigning // all roles except admin and site owner. $this->assertSession()->checkboxNotChecked('edit-roleassign-roles-administrator'); $this->assertSession()->checkboxNotChecked('edit-roleassign-roles-uw-role-site-owner'); $this->assertSession()->checkboxChecked('edit-roleassign-roles-uw-role-site-manager'); $this->assertSession()->checkboxChecked('edit-roleassign-roles-uw-role-content-editor'); $this->assertSession()->checkboxChecked('edit-roleassign-roles-uw-role-content-author'); $this->assertSession()->checkboxChecked('edit-roleassign-roles-uw-role-form-editor'); $this->assertSession()->checkboxChecked('edit-roleassign-roles-uw-role-form-results-access'); // Check admin/people/permissions page. $this->drupalGet('admin/people/permissions'); $this->assertSession()->statusCodeEquals(200); // Site owner role has administer users. $this->assertSession()->checkboxChecked('edit-uw-role-site-owner-administer-users'); // Only the site owner role assign roles permissions. $this->assertSession()->checkboxChecked('edit-uw-role-site-owner-assign-roles'); $this->assertSession()->checkboxNotChecked('edit-uw-role-site-manager-assign-roles'); $this->assertSession()->checkboxNotChecked('edit-uw-role-content-editor-assign-roles'); $this->assertSession()->checkboxNotChecked('edit-uw-role-content-author-assign-roles'); $this->assertSession()->checkboxNotChecked('edit-uw-role-form-editor-assign-roles'); $this->assertSession()->checkboxNotChecked('edit-uw-role-form-results-access-assign-roles'); // Check Edit protection rule Authenticated user page. $this->drupalGet('admin/config/people/userprotect/manage/uw_protect_authenticated_user'); $this->assertSession()->statusCodeEquals(200); // Get Name field value: Authenticated user. $this->getSession()->getPage()->findField('edit-label')->getValue('Authenticated user'); // Get Role field value: Authenticated user. $this->getSession()->getPage()->findById('edit-entity-id')->getValue('Authenticated user'); // Only status and cancel operation are checked in proection field. $this->assertSession()->checkboxChecked('edit-protection-user-status'); $this->assertSession()->checkboxChecked('edit-protection-user-delete'); $this->assertSession()->checkboxNotChecked('edit-protection-user-name'); $this->assertSession()->checkboxNotChecked('edit-protection-user-mail'); $this->assertSession()->checkboxNotChecked('edit-protection-user-pass'); $this->assertSession()->checkboxNotChecked('edit-protection-user-roles'); $this->assertSession()->checkboxNotChecked('edit-protection-user-edit'); // Only Administrator is checked in Bypass for roles. $this->assertSession()->checkboxChecked('edit-bypass-roles-administrator'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-anonymous'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-authenticated'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-uw-role-site-owner'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-uw-role-site-manager'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-uw-role-content-editor'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-uw-role-content-author'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-uw-role-form-editor'); $this->assertSession()->checkboxNotChecked('edit-bypass-roles-uw-role-form-results-access'); // The other users do not have access permissions and roleassign pages. $roles = [ 'authenticated user', 'uw_role_site_manager', 'uw_role_content_editor', 'uw_role_content_author', 'uw_role_form_editor', 'uw_role_form_results_access', ]; foreach ($roles as $role) { $this->drupalLogin($this->drupalUsers[$role]); $this->drupalGet('admin/people/permissions'); $this->assertSession()->statusCodeEquals(403); $this->drupalGet('admin/people/roleassign'); $this->assertSession()->statusCodeEquals(403); $this->drupalGet('admin/config/people/userprotect/manage/uw_protect_authenticated_user'); $this->assertSession()->statusCodeEquals(403); // Test no access to config paths. $routes = [ 'dashboards.dashboards_settings_form', 'role_expire.config', 'entity_reference_revisions.delete_orphans', ]; foreach ($routes as $route) { $url = Url::fromRoute($route); $this->assertFalse($url->access(), 'No access to route ' . $route . '.'); } } $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet('admin/people/permissions'); $this->assertSession()->statusCodeEquals(200); // The following permissions are checked for the given roles. $content_types = [ 'Contact' => [ 'Create new content' => [ 'Site manager' => 'edit-uw-role-site-manager-create-uw-ct-contact-content', 'Content editor' => 'edit-uw-role-content-editor-create-uw-ct-contact-content', 'Content author' => 'edit-uw-role-content-author-create-uw-ct-contact-content', ], 'Delete any content' => [ 'Site manager' => 'edit-uw-role-site-manager-delete-any-uw-ct-contact-content', ], 'Delete own content' => [ 'Site manager' => 'edit-uw-role-site-manager-delete-own-uw-ct-contact-content', ], 'Edit any content' => [ 'Site manager' => 'edit-uw-role-site-manager-edit-any-uw-ct-contact-content', 'Content editor' => 'edit-uw-role-content-editor-edit-any-uw-ct-contact-content', 'Content author' => 'edit-uw-role-content-author-edit-any-uw-ct-contact-content', ], 'Edit own content' => [ 'Site manager' => 'edit-uw-role-site-manager-edit-own-uw-ct-contact-content', 'Content editor' => 'edit-uw-role-content-editor-edit-own-uw-ct-contact-content', 'Content author' => 'edit-uw-role-content-author-edit-own-uw-ct-contact-content', ], 'Revert revisions' => [ 'Site manager' => 'edit-uw-role-site-manager-revert-uw-ct-contact-revisions', 'Content editor' => 'edit-uw-role-content-editor-revert-uw-ct-contact-revisions', 'Content author' => 'edit-uw-role-content-author-revert-uw-ct-contact-revisions', ], 'View revisions' => [ 'Site manager' => 'edit-uw-role-site-manager-view-uw-ct-contact-revisions', 'Content editor' => 'edit-uw-role-content-editor-view-uw-ct-contact-revisions', 'Content author' => 'edit-uw-role-content-author-view-uw-ct-contact-revisions', ], 'Create contact group terms' => [ 'Site manager' => 'edit-uw-role-site-manager-create-terms-in-uw-vocab-contact-group', 'Content editor' => 'edit-uw-role-content-editor-create-terms-in-uw-vocab-contact-group', 'Content author' => 'edit-uw-role-content-author-create-terms-in-uw-vocab-contact-group', ], 'Delete contact group terms' => [ 'Site manager' => 'edit-uw-role-site-manager-delete-terms-in-uw-vocab-contact-group', ], 'Edit contact group terms' => [ 'Site manager' => 'edit-uw-role-site-manager-edit-terms-in-uw-vocab-contact-group', 'Content editor' => 'edit-uw-role-content-editor-edit-terms-in-uw-vocab-contact-group', 'Content author' => 'edit-uw-role-content-author-edit-terms-in-uw-vocab-contact-group', ], ], 'Profile' => [ 'Create new content' => [ 'Site manager' => 'edit-uw-role-site-manager-create-uw-ct-profile-content', 'Content editor' => 'edit-uw-role-content-editor-create-uw-ct-profile-content', 'Content author' => 'edit-uw-role-content-author-create-uw-ct-profile-content', ], 'Delete any content' => [ 'Site manager' => 'edit-uw-role-site-manager-delete-any-uw-ct-profile-content', ], 'Delete own content' => [ 'Site manager' => 'edit-uw-role-site-manager-delete-own-uw-ct-profile-content', ], 'Edit any content' => [ 'Site manager' => 'edit-uw-role-site-manager-edit-any-uw-ct-profile-content', 'Content editor' => 'edit-uw-role-content-editor-edit-any-uw-ct-profile-content', 'Content author' => 'edit-uw-role-content-author-edit-any-uw-ct-profile-content', ], 'Edit own content' => [ 'Site manager' => 'edit-uw-role-site-manager-edit-own-uw-ct-profile-content', 'Content editor' => 'edit-uw-role-content-editor-edit-own-uw-ct-profile-content', 'Content author' => 'edit-uw-role-content-author-edit-own-uw-ct-profile-content', ], 'Revert revisions' => [ 'Site manager' => 'edit-uw-role-site-manager-revert-uw-ct-profile-revisions', 'Content editor' => 'edit-uw-role-content-editor-revert-uw-ct-profile-revisions', 'Content author' => 'edit-uw-role-content-author-revert-uw-ct-profile-revisions', ], 'View revisions' => [ 'Site manager' => 'edit-uw-role-site-manager-view-uw-ct-profile-revisions', 'Content editor' => 'edit-uw-role-content-editor-view-uw-ct-profile-revisions', 'Content author' => 'edit-uw-role-content-author-view-uw-ct-profile-revisions', ], 'Create profile type terms' => [ 'Site manager' => 'edit-uw-role-site-manager-create-terms-in-uw-vocab-profile-type', 'Content editor' => 'edit-uw-role-content-editor-create-terms-in-uw-vocab-profile-type', 'Content author' => 'edit-uw-role-content-author-create-terms-in-uw-vocab-profile-type', ], 'Delete profile type terms' => [ 'Site manager' => 'edit-uw-role-site-manager-delete-terms-in-uw-vocab-profile-type', ], 'Edit profile type terms' => [ 'Site manager' => 'edit-uw-role-site-manager-edit-terms-in-uw-vocab-profile-type', 'Content editor' => 'edit-uw-role-content-editor-edit-terms-in-uw-vocab-profile-type', 'Content author' => 'edit-uw-role-content-author-edit-terms-in-uw-vocab-profile-type', ], ], ]; foreach ($content_types as $content_type) { foreach ($content_type as $perms) { foreach ($perms as $perm) { $this->assertSession()->checkboxChecked($perm); } } } // Administrator still has access to "status" and "cancel account" // options for users with all roles.. $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet('admin/people'); $this->assertSession()->statusCodeEquals(200); $this->getSession()->getPage()->clickLink('uw_role_site_owner'); $this->getSession()->getPage()->clickLink('Edit'); $this->assertSession()->pageTextContains('Status'); $this->assertSession()->buttonExists('edit-delete'); // Two required field (First name and Last name) in 'Add user' page. $this->drupalGet('admin/people/create'); $this->assertSession()->statusCodeEquals(200); $this->assertFieldByXPath('//input[@type="text" and @id="edit-field-uw-first-name-0-value" and @required=true()]', NULL, 'Required first name.'); $this->assertFieldByXPath('//input[@type="text" and @id="edit-field-uw-last-name-0-value" and @required=true()]', NULL, 'Required last name.'); // Admin has "Manage" toolbar item. $this->assertSession()->elementExists('css', '#toolbar-item-administration'); // Site owner oes not have access to "status" and "cancel account" // for other users. $this->drupalLogin($this->drupalUsers['uw_role_site_owner']); $this->drupalGet('admin/people'); $this->assertSession()->statusCodeEquals(200); $this->getSession()->getPage()->clickLink('uw_role_site_manager'); $this->getSession()->getPage()->clickLink('Edit'); $this->assertSession()->pageTextContains('has been protected from the following editing operations: Status'); $this->assertSession()->buttonNotExists('edit-delete'); // Non-admin does not have "Manage" toolbar item. $this->assertSession()->elementNotExists('css', '#toolbar-item-administration'); // "Workbench" tray has "People" and "Reports" links. $this->assertSession()->elementExists('css', '#toolbar-item-dashboards-tray a[href$="/admin/people"]'); $this->assertSession()->elementExists('css', '#toolbar-item-dashboards-tray a[href$="/admin/reports"]'); // All other roles (e.g. site manager) do not have access // to other accounts (e.g. content author). $this->drupalLogin($this->drupalUsers['uw_role_site_manager']); $this->drupalGet('users/uwrolecontentauthor'); $this->assertSession()->statusCodeEquals(403); // The users are able to change their own account (email and password). $this->drupalGet('users/uwrolesitemanager'); $this->assertSession()->statusCodeEquals(200); $this->clickLink('Edit profile'); $this->assertSession()->statusCodeEquals(200); } /** * Tests Real name module. * * Create a new user. * The user displays the first name and last name. */ private function realnameTest() { $this->drupalLogin($this->drupalUsers['administrator']); // Check admin/config/people/realname page. $this->drupalGet('admin/config/people/realname'); $this->assertSession()->statusCodeEquals(200); // The pattern is [user:field_uw_first_name] [user:field_uw_last_name]. $this->getSession() ->getPage() ->findById('edit-realname-pattern') ->getValue('[user:field_uw_first_name] [user:field_uw_last_name]'); // Add a new user. $this->drupalGet('admin/people/create'); $this->assertSession()->statusCodeEquals(200); $fname = $this->randomMachineName(); $lname = $this->randomMachineName(); $pass = $this->randomString(); $edit = [ 'edit-field-uw-first-name-0-value' => $fname, 'edit-field-uw-last-name-0-value' => $lname, 'edit-mail' => 'wcmstest@uwaterloo.ca', 'edit-name' => 'wcmstest', 'edit-pass-pass1' => $pass, 'edit-pass-pass2' => $pass, ]; $this->drupalPostForm('admin/people/create', $edit, 'Create new account'); // The first name and last name are displayed in people page. $this->drupalGet('admin/people'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains($fname . ' ' . $lname); // field_uw_first_name and field_uw_last_name are not displayed. $this->drupalGet('users/wcmstest'); $this->assertSession()->pageTextContains($fname . ' ' . $lname); $this->assertSession()->pageTextNotContains('First name'); $this->assertSession()->pageTextNotContains('Last name'); } /** * Tests for Contact content type. */ public function contactContentTypeTest() { $this->drupalLogin($this->drupalUsers['administrator']); // Test step 1: Visit the node add page. $this->drupalGet('node/add'); // Test step 2: Make sure content type Contact exists as link. $this->assertSession()->linkExists('Contact'); $this->clickLink('Contact'); // List of fields in order they are listed on wiki. // https://wiki.uwaterloo.ca/pages/viewpage.action?spaceKey=ISTWCMS&title=Contact+content+type+proposal $fields = [ 'WatIAM user ID', 'Method', 'Name', 'Name for sorting purposes', 'Affiliation', 'Title, position, or description', 'Email', 'Phone #', 'Location', 'Contact for', 'Additional information', ]; // Test step 3: Test for field id|name|label|value. foreach ($fields as $field) { $this->assertSession()->fieldExists($field); } // Some fields are displayed as fieldset, no input element with same name. // Testing those is a bit different. $field_groups = [ 'Fields', 'Listing page image', 'Link to profile', 'Link to personal website or CV', 'Group(s)', ]; // Test step 4: Test image, link and radio group fields. foreach ($field_groups as $field) { $this->assertSession()->pageTextContains($field); } // Test empty form, "Affiliation" field has default value. $this->submitForm([], "Save"); $this->assertSession()->responseContains('3 errors have been found'); // Test step 5: Required fields. $req_fields = [ 'Name' => $this->randomString(), 'Name for sorting purposes' => $this->randomString(), 'Title, position, or description' => $this->randomString(), 'Affiliation' => $this->randomString(), ]; foreach ($req_fields as $name => $value) { // Set one required field as an empty string. $fields = [$name => ''] + $req_fields; $this->submitForm($fields, 'Save'); // Expect error for required field. $this->assertSession()->responseContains($name . ' field is required.'); } // Submit form with all required fields. $this->submitForm($req_fields, 'Save'); // Contact successfully created when only required fields are submitted. $this->assertSession()->statusCodeEquals(200); // Make sure not 'Revert to defaults' button on contact layout page. $this->assertSession()->buttonNotExists('Revert to defaults'); // Check contacts listing view. $this->drupalGet('contacts'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Contacts'); $this->assertSession()->pageTextContains('Name'); $this->assertSession()->pageTextContains('Limit to contacts where the name matches'); $this->assertFieldByXPath('//input[@type="text" and @id="edit-title"]', NULL, 'Input field exists.'); $this->assertSession()->pageTextContains('Groups'); $this->assertSession()->pageTextContains('Limit to contacts where the group is one or more of'); $this->assertSession()->buttonExists('Apply filters'); // Check rearrange contacts. $this->drupalGet('admin/rearrange-contacts'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Published'); $this->assertOptionSelected('edit-status', '- Any -'); $this->assertSession()->buttonExists('Apply filters'); // Check dashboard contact rearrange link. $this->drupalGet('dashboard/my_dashboard'); $this->assertSession()->statusCodeEquals(200); $rearranges = $this->getSession()->getPage()->findAll('xpath', "//a[contains(text(), 'Rearrange')]"); $this->assertEquals(base_path() . 'admin/rearrange-contacts', $rearranges[0]->getAttribute('href')); // Make sure site manager's rearrange is checked. $this->drupalGet('admin/content-access'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-permissions-contact-rearrange-site-manager'); $this->assertSession()->checkboxNotChecked('edit-permissions-contact-rearrange-content-editor'); $this->assertSession()->checkboxNotChecked('edit-permissions-contact-rearrange-content-author'); // Check pathauto pattern to make sure they are in same row. $this->drupalGet('admin/config/search/path/patterns'); $this->assertSession()->statusCodeEquals(200); $elements = $this->xpath('//div[@id="block-uw-theme-admin-mainpagecontent"] //table/tbody/tr[@data-drupal-selector="edit-entities-uw-path-contact"]/td'); $expected_items = [ 'Contact path pattern', 'contacts/[node:title]', 'Content', 'The node bundle is uw_ct_contact', ]; foreach ($expected_items as $key => $value) { $this->assertEqual($elements[$key]->getText(), $value); } } /** * Tests for profile content type. */ public function profileContentTypeTest() { // Login as administrator. $this->drupalLogin($this->drupalUsers['administrator']); // field_uw_meta_description 'Required on Publish' is checked. $this->drupalGet('admin/structure/types/manage/uw_ct_profile/fields/node.uw_ct_profile.field_uw_meta_description'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-require-on-publish'); // Open page for adding content, lists all available content types. $this->drupalGet('node/add'); // Check if there is link Profile. $this->assertSession()->linkExists('Profile'); // Click on the link if it exists. $this->clickLink('Profile'); // List of valid fields of the content type. $fields = [ 'Link with contact', 'Name', 'Name for sorting purposes', 'Affiliation', 'Title, position, or description', ]; // Test for field id|name|label|value. foreach ($fields as $field) { $this->assertSession()->fieldExists($field); } // Some fields are displayed as fieldset, no input element with same name. // Testing those is a bit different. $field_groups = [ 'Listing page image', 'Link to personal website or CV', 'Link to additional information', 'Profile type(s)', ]; // Test image, link and radio group fields. foreach ($field_groups as $field) { $this->assertSession()->pageTextContains($field); } // Generate random name that will be used for tests. $profile_name = $this->randomString(); // Populate required fields. $req_fields = [ 'Name' => $profile_name, 'Name for sorting purposes' => $this->randomString(), 'Summary' => $this->randomString(), 'Affiliation' => $this->randomString(), 'Title, position, or description' => $this->randomString(), ]; // Submit form with required fields. $this->submitForm($req_fields, 'Save'); // Make sure not 'Revert to defaults' button on profile layout page. $this->assertSession()->buttonNotExists('Revert to defaults'); // Validate new content has been created with same name. $this->assertSession()->pageTextContains('Profile ' . $profile_name . ' has been created.'); // Check profiles listing view. // Temporarily removed because requests to /profiles return 403. // @todo Uncomment these and remove phpcs directives. // phpcs:disable Drupal.Files.LineLength.TooLong // @code // $this->drupalGet('profiles'); // $this->assertSession()->statusCodeEquals(200); // $this->assertSession()->pageTextContains('Profiles'); // $this->assertSession()->pageTextContains('Name'); // $this->assertSession()->pageTextContains('Limit to profiles where the name matches'); // $this->assertFieldByXPath('//input[@type="text" and @id="edit-title"]', NULL, 'Input field exists.'); // $this->assertSession()->pageTextContains('Types'); // $this->assertSession()->pageTextContains('Limit to profiles where the type is one or more of'); // $this->assertSession()->buttonExists('Apply filters'); // @endcode // phpcs:enable // Check rearrange profiles. $this->drupalGet('admin/rearrange-profiles'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('Published'); $this->assertOptionSelected('edit-status', '- Any -'); $this->assertSession()->buttonExists('Apply filters'); // Check dashboard profile rearrange link. $this->drupalGet('dashboard/my_dashboard'); $this->assertSession()->statusCodeEquals(200); $rearranges = $this->getSession()->getPage()->findAll('xpath', "//a[contains(text(), 'Rearrange')]"); $this->assertEquals(base_path() . 'admin/rearrange-profiles', $rearranges[1]->getAttribute('href')); // Make sure site manager's rearrange for profile is checked. $this->drupalGet('admin/content-access'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-permissions-profile-rearrange-site-manager'); $this->assertSession()->checkboxNotChecked('edit-permissions-profile-rearrange-content-editor'); $this->assertSession()->checkboxNotChecked('edit-permissions-profile-rearrange-content-author'); // Check pathauto pattern to make sure they are in same row. $this->drupalGet('admin/config/search/path/patterns'); $this->assertSession()->statusCodeEquals(200); $elements = $this->xpath('//div[@id="block-uw-theme-admin-mainpagecontent"] //table/tbody/tr[@data-drupal-selector="edit-entities-uw-path-profile"]/td'); $expected_items = [ 'Profile path pattern', 'profiles/[node:title]', 'Content', 'The node bundle is uw_ct_profile', ]; foreach ($expected_items as $key => $value) { $this->assertEqual($elements[$key]->getText(), $value); } } /** * Tests for Layout Section Configuration Form and their Settings. */ private function layoutSectionConfigurationFormTest() { // Step 3A is in a bigger loop and only need to do it once. $step3AComplete = FALSE; $locator = ''; // Plan: // Add 6 sections. One of each layout type. // Each section will be a little bit different so we can test things. // From Bottom to Top // One column: Group1, Admin Label 1 Column, Section ID 1 Column. // Two columns: Group1, Admin Label none, Section ID none. // Three columns: Group2, Admin Label none. // Four columns: no group, Admin Label none. Section ID 4 Column. // Inverted "L" - right: no group. Admin Label Inverted "L" - right. // Inverted "L" - left: Group2. Admin Label Inverted "L" - left. $listLayout = [ [ 'name' => 'One column', 'admin-label' => '1 Column', 'section-id' => '1 Column', 'ec-setting' => 1, 'ec-group-title' => 'One Column Tab Title', 'group' => 'group1', 'group-sections-total' => 1, ], [ 'name' => 'Two columns', 'admin-label' => '', 'section-id' => '', 'ec-setting' => 1, 'ec-group-title' => 'Two Column Tab Title', 'group' => 'group1', 'group-sections-total' => 2, ], [ 'name' => 'Three columns', 'admin-label' => '', 'section-id' => '', 'ec-setting' => 1, 'ec-group-title' => 'Third Column Tab Title', 'group' => 'group2', 'group-sections-total' => 1, ], [ 'name' => 'Four columns', 'admin-label' => '', 'section-id' => '4 Column', 'ec-setting' => 0, 'group' => '', ], [ 'name' => 'Inverted "L" - right', 'admin-label' => 'Inverted "L" - right', 'section-id' => '', 'ec-setting' => 0, 'group' => '', ], [ 'name' => 'Inverted "L" - left', 'admin-label' => 'Inverted "L" - left', 'section-id' => '', 'ec-setting' => 1, 'ec-group-title' => 'Inverted "L" - left Tab Title', 'group' => 'group2', 'group-sections-total' => 2, ], ]; $this->drupalLogin($this->drupalUsers['administrator']); // Test step 1: Visit the home page layout. $this->drupalGet('node/1/layout'); $this->assertSession()->statusCodeEquals(200); foreach ($listLayout as $section) { // Test step 2: Look on the layout edit page to click 'Add section'. $this->clickLink('Add section'); $this->assertSession()->statusCodeEquals(200); // Test step 3: Loop and add 6 sections. Testing along the way. // Test step 3A: Verify all the columns. Do this only once. if ($step3AComplete == FALSE) { foreach ($listLayout as $layout) { $this->assertSession()->linkExists($layout['name']); } $step3AComplete = TRUE; } // Test step 3B: Goto section configuration form. $this->clickLink($section['name']); // Test step 3C: Verify all configuration form elements. // Note: Javascription is off so no conditional form elements are hidden. $this->assertSession()->pageTextContains('Administrative label'); $this->assertSession()->pageTextContains('Section ID'); $this->assertSession() ->pageTextContains('Make Section Expand/Collapsible'); $this->assertSession() ->pageTextContains('Title of Expand/Collapse Group'); $this->assertSession()->pageTextContains('Heading Selector'); $this->assertSession()->pageTextContains('Grouping'); $this->assertSession()->pageTextContains('other'); $this->assertSession()->pageTextContains('Create new grouping'); $this->assertSession()->pageTextContains('Extra-wide contained width'); // No column widths on one column. if ($section['name'] != 'One column') { $this->assertSession()->pageTextContains('Column widths'); } $locator = "//*[@id='edit-expand-collapse-group-" . $section['group'] . "']"; // Step 3D: Submit the form. if ($this->getSession()->getPage()->find('xpath', $locator)) { $this->submitForm([ 'layout_settings[label]' => $section['admin-label'], 'layout_settings[layout_builder_id]' => $section['section-id'], 'expand_collapse[setting]' => $section['ec-setting'], 'expand_collapse[heading_selector]' => $section['heading-selector'] ?? 'h2', 'expand_collapse[group_title]' => $section['ec-group-title'] ?? '', 'expand_collapse[group]' => $section['group'], ], 'Add section'); } else { $this->submitForm([ 'layout_settings[label]' => $section['admin-label'], 'layout_settings[layout_builder_id]' => $section['section-id'], 'expand_collapse[setting]' => $section['ec-setting'], 'expand_collapse[heading_selector]' => $section['heading-selector'] ?? 'h2', 'expand_collapse[group_title]' => $section['ec-group-title'] ?? '', 'expand_collapse[group]' => 'other', 'expand_collapse[new_grouping]' => $section['group'], ], 'Add section'); } // Test step 3E: Check if page contains the correct link wordage. $this->assertSession()->statusCodeEquals(200); $msg = $this->t('Expand/Collapse Grouping of'); // Text is based on the label and group. $labelCheck = [ 'label' => "Configure " . $section['admin-label'], 'group' => "Configure [$msg: " . $section['group'] . "]", 'label-group' => "Configure " . $section['admin-label'] . " [$msg: " . $section['group'] . "]", ]; if (!empty($section['admin-label']) && !empty($section['group'])) { // Configure {ADMIN LABEL} [Expand/Collapse Grouping of: {GROUP}]. $this->assertSession()->linkExists($labelCheck['label-group']); } elseif (!empty($section['admin-label']) && empty($section['group'])) { // Configure {ADMIN LABEL}. $this->assertSession()->linkExists($labelCheck['label']); } elseif (empty($section['admin-label']) && !empty($section['group'])) { // Configure [Expand/Collapse Grouping of: {GROUP}]. $this->assertSession()->linkExists($labelCheck['group']); } // Step 3F: Assert the class and custom data property. if (!empty($section['group'])) { $locator = "//section[@data-expand-collapse-group='" . $section['group'] . "']"; $dataGroupCount = $this->getSession() ->getPage() ->findAll('xpath', $locator); $this->assertCount($section['group-sections-total'], $dataGroupCount); } } } /** * Tests media types. */ public function mediaTypesTest() { $this->drupalLogin($this->drupalUsers['administrator']); // File directory default value for File media type // is 'uploads/documents'. $this->drupalGet('admin/structure/media/manage/uw_mt_file/fields/media.uw_mt_file.field_media_file'); $this->assertSession()->statusCodeEquals(200); $this->getSession()->getPage()->findField('edit-settings-file-directory')->getValue('uploads/documents'); // File directory default value for Icon media type // is 'uploads/icons'. $this->drupalGet('admin/structure/media/manage/uw_mt_icon/fields/media.uw_mt_icon.field_media_image_1'); $this->assertSession()->statusCodeEquals(200); $this->getSession()->getPage()->findField('edit-settings-file-directory')->getValue('uploads/icons'); // File directory default value for Image media type // is 'uploads/images'. $this->drupalGet('admin/structure/media/manage/uw_mt_image/fields/media.uw_mt_image.field_media_image'); $this->assertSession()->statusCodeEquals(200); $this->getSession()->getPage()->findField('edit-settings-file-directory')->getValue('uploads/images'); } /** * Tests redirects. */ public function redirectsTest() { $this->drupalLogin($this->drupalUsers['administrator']); // Check admin/people/permissions, only site manager has this role. $this->drupalGet('admin/people/permissions'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxChecked('edit-uw-role-site-manager-administer-redirects'); $this->assertSession()->checkboxNotChecked('edit-uw-role-site-owner-administer-redirects'); $this->assertSession()->checkboxNotChecked('edit-uw-role-content-editor-administer-redirects'); $this->assertSession()->checkboxNotChecked('edit-uw-role-content-author-administer-redirects'); // Check admin/config/search/redirect/settings. $this->drupalGet('admin/config/search/redirect/settings'); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->checkboxNotChecked('edit-redirect-auto-redirect'); $this->assertSession()->checkboxChecked('edit-redirect-passthrough-querystring'); $this->assertOptionSelected('edit-redirect-default-status-code', '301 Moved Permanently'); $this->assertSession()->checkboxChecked('edit-redirect-route-normalizer-enabled'); $this->assertSession()->checkboxNotChecked('edit-redirect-ignore-admin-path'); $this->assertSession()->checkboxNotChecked('edit-redirect-access-check'); $this->assertOptionSelected('edit-row-limit', '10000'); $this->assertSession()->fieldExists('ignore_pages'); $this->assertSession()->checkboxNotChecked('edit-suppress-404'); } /** * Tests for UWLdap service. */ public function uwLdapTest() { // Test LDAP view page. $test_path = 'uw-ldap/wcmsadmi'; $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet($test_path); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->pageTextContains('LDAP View: wcmsadmi'); // Test that the LDAP page contains the full name of user wcmsadmi. // This ought to pass, but in UwLdap::openConnection(), configFactory->get() // returns NULLs for values in testing preventing LDAP bind. // @code // $this->assertSession()->pageTextContains('Administrator Wcms'); // @endcode // // Test LDAP view page is not available to anonymous. Cannot do this first // because drupalLogout() raises an error if called when there is no user // logged-in. $this->drupalLogout(); $this->drupalGet($test_path); $this->assertSession()->statusCodeEquals(403); // The rest of this could be unit tests, except that accessing // config.factory does not work in unit or kernel tests. $config_factory = $this->container->get('config.factory'); // Use mock user object. $current_user = $this->createMock(AccountProxy::class); $ldap = new UWLdap($config_factory, $current_user); // Test search() and lookupPerson(). $search = $ldap->search('(sAMAccountName=wcmsadmi)'); $search = $ldap->formatResults($search[0]); $lookup = $ldap->lookupPerson('wcmsadmi'); $this->assertEquals($search, $lookup, 'LDAP search() and lookupPerson() give matching results.'); $this->assertEquals($lookup['displayname'][0], 'Administrator Wcms', 'Expected name found in LDAP.'); // Test formatResults(). $test_in = ['objectguid' => ['ABCDEFGHIJKLMNOP']]; $test_in = $ldap->formatResults($test_in); $test_out = ['objectguid' => ['44434241-4645-4847-494A-4B4C4D4E4F50']]; $this->assertEquals($test_in, $test_out, 'formatResults() gives correct results.'); } /** * Tests for CKEditor buttons. */ public function ckeditorButtonsTest() { $this->drupalLogin($this->drupalUsers['administrator']); // Create function to encode HTML as we expect it in drupalSettings. $json_encode = function ($html) { return trim(Json::encode($html), '"'); }; $textformats = [ 'uw_tf_standard', 'uw_tf_full_html', 'uw_tf_basic', ]; foreach ($textformats as $textformat) { $this->drupalGet('admin/config/content/formats/manage/' . $textformat); $this->assertSession()->statusCodeEquals(200); $this->assertRaw($json_encode('
  • ')); } } /** * Test for OFIS module. * * Testing: * - has module been enabled by default. * - admin role checks: * - check config page, default api endopoint, and disabled profiles. * - site owner checks: * - login as site owner, and check if you have access to config page. * - confirm api_endpoint field is not on config form. */ public function ofisTest() { // Check if module is enabled with profile install. $module_enabled = \Drupal::moduleHandler()->moduleExists('uw_ws_ofis'); $this->assertTrue($module_enabled, 'Module uw_ws_ofis not enabled.'); // Login as administrator and check ofis config form. $this->drupalLogin($this->drupalUsers['administrator']); $this->drupalGet('admin/config/uw_ws_ofis'); $this->assertSession()->statusCodeEquals(200); // Validate settings form fields for administrator. $this->assertSession()->pageTextContains('Clear OFIS caches'); $this->assertSession()->fieldExists('API endpoint'); $this->assertSession()->fieldExists('Enable OFIS profiles'); $this->drupalLogout(); // Login as site owner. $this->drupalLogin($this->drupalUsers['uw_role_site_owner']); // Get to config form using dashboard. $this->drupalGet('dashboard/my_dashboard'); $this->assertSession()->linkExists('OFIS settings'); $this->clickLink('OFIS settings'); $this->assertSession()->statusCodeEquals(200); // Make sure enable/disable profiles is available. $this->assertSession()->fieldExists('Enable OFIS profiles'); // API endpoint and cache clear should not be visible to site owner. $this->assertSession()->fieldNotExists('API endpoint'); $this->assertSession()->pageTextNotContains('Clear OFIS caches'); } }