getTestFiles('image'); $image_file = File::create([ 'uri' => $test_files[0]->uri, 'uuid' => 'b2c22b6f-7bf8-4da4-9de5-316e93487518', 'status' => FILE_STATUS_PERMANENT, ]); $image_file->save(); $media_file = File::create([ 'uri' => $test_files[8]->uri, 'uuid' => '5dd794d0-cb75-4130-9296-838aebc1fe74', 'status' => FILE_STATUS_PERMANENT, ]); $media_file->save(); $media = Media::create([ 'bundle' => 'image', 'name' => 'Image 1', 'field_media_image' => ['target_id' => $media_file->id()], ]); $media->save(); $node_values = [ 'title' => 'Alpha', 'uuid' => 'ad1b902a-344f-41d1-8c61-a69f0366dbfa', 'field_image' => [ 'target_id' => $image_file->id(), 'alt' => 'Alt text', 'title' => 'Title', ], 'field_media' => [ 'target_id' => $media->id(), ], ]; $this->createNode($node_values); $this->createNode(['title' => 'Beta']); $this->createNode(['title' => 'Gamma']); ResponsiveImageStyle::create([ 'id' => 'example', 'label' => 'Example', 'breakpoint_group' => 'responsive_image', ])->save(); // Setup Russian language. ConfigurableLanguage::createFromLangcode('ru')->save(); } /** * Tests output produced by the Twig extension. */ public function testOutput(): void { $this->drupalGet('twig-tweak-test'); // -- View (default display). $xpath = '//div[@class = "tt-view-default"]'; $xpath .= '//div[contains(@class, "view-twig-tweak-test") and contains(@class, "view-display-id-default")]'; $xpath .= '/div[@class = "view-content"]//ul[count(./li) = 3]/li'; $this->assertXpath($xpath . '//a[contains(@href, "/node/1") and text() = "Alpha"]'); $this->assertXpath($xpath . '//a[contains(@href, "/node/2") and text() = "Beta"]'); $this->assertXpath($xpath . '//a[contains(@href, "/node/3") and text() = "Gamma"]'); // -- View (page_1 display). $xpath = '//div[@class = "tt-view-page_1"]'; $xpath .= '//div[contains(@class, "view-twig-tweak-test") and contains(@class, "view-display-id-page_1")]'; $xpath .= '/div[@class = "view-content"]//ul[count(./li) = 3]/li'; $this->assertXpath($xpath . '//a[contains(@href, "/node/1") and text() = "Alpha"]'); $this->assertXpath($xpath . '//a[contains(@href, "/node/2") and text() = "Beta"]'); $this->assertXpath($xpath . '//a[contains(@href, "/node/3") and text() = "Gamma"]'); // -- View with arguments. $xpath = '//div[@class = "tt-view-page_1-with-argument"]'; $xpath .= '//div[contains(@class, "view-twig-tweak-test")]'; $xpath .= '/div[@class = "view-content"]//ul[count(./li) = 1]/li'; $this->assertXpath($xpath . '//a[contains(@href, "/node/1") and text() = "Alpha"]'); // -- View result. $xpath = '//div[@class = "tt-view-result" and text() = 3]'; $this->assertXpath($xpath); // -- Block. $xpath = '//div[@class = "tt-block"]'; $xpath .= '/img[contains(@src, "/core/themes/classy/logo.svg") and @alt="Home"]'; $this->assertXpath($xpath); // -- Block with wrapper. $xpath = '//div[@class = "tt-block-with-wrapper"]'; $xpath .= '/div[@class = "block block-system block-system-branding-block"]'; $xpath .= '/h2[text() = "Branding"]'; $xpath .= '/following-sibling::a[img[contains(@src, "/core/themes/classy/logo.svg") and @alt="Home"]]'; $xpath .= '/following-sibling::div[@class = "site-name"]/a'; $this->assertXpath($xpath); // -- Region. $xpath = '//div[@class = "tt-region"]/div[@class = "region region-sidebar-first"]'; $xpath .= '/div[contains(@class, "block-page-title-block") and h1[@class="page-title" and text() = "Twig Tweak Test"]]'; $xpath .= '/following-sibling::div[contains(@class, "block-system-powered-by-block")]/span[. = "Powered by Drupal"]'; $this->assertXpath($xpath); // -- Entity (default view mode). $xpath = '//div[@class = "tt-entity-default"]'; $xpath .= '/article[contains(@class, "node") and not(contains(@class, "node--view-mode-teaser"))]'; $xpath .= '/h2/a/span[text() = "Alpha"]'; $this->assertXpath($xpath); // -- Entity (teaser view mode). $xpath = '//div[@class = "tt-entity-teaser"]'; $xpath .= '/article[contains(@class, "node") and contains(@class, "node--view-mode-teaser")]'; $xpath .= '/h2/a/span[text() = "Alpha"]'; $this->assertXpath($xpath); // -- Entity by UUID. $xpath = '//div[@class = "tt-entity-uuid"]'; $xpath .= '/article[contains(@class, "node")]'; $xpath .= '/h2/a/span[text() = "Alpha"]'; $this->assertXpath($xpath); // -- Entity by UUID (missing). $xpath = '//div[@class = "tt-entity-uuid-missing" and . = ""]'; $this->assertXpath($xpath); // -- Entity add form (unprivileged user). $xpath = '//div[@class = "tt-entity-add-form"]/form'; $this->assertSession()->elementNotExists('xpath', $xpath); // -- Entity edit form (unprivileged user). $xpath = '//div[@class = "tt-entity-edit-form"]/form'; $this->assertSession()->elementNotExists('xpath', $xpath); // Grant require permissions and test the forms again. $permissions = ['create page content', 'edit any page content']; /** @var \Drupal\user\RoleInterface $role */ $role = Role::load(Role::ANONYMOUS_ID); $this->grantPermissions($role, $permissions); $this->drupalGet($this->getUrl()); // -- Entity add form. $xpath = '//div[@class = "tt-entity-add-form"]/form'; $xpath .= '//input[@name = "title[0][value]" and @value = ""]'; $xpath .= '/../../../div/input[@type = "submit" and @value = "Save"]'; $this->assertXpath($xpath); // -- Entity edit form. $xpath = '//div[@class = "tt-entity-edit-form"]/form'; $xpath .= '//input[@name = "title[0][value]" and @value = "Alpha"]'; $xpath .= '/../../../div/input[@type = "submit" and @value = "Save"]'; $this->assertXpath($xpath); // -- Field. $xpath = '//div[@class = "tt-field"]/div[contains(@class, "field--name-body")]/p[text() != ""]'; $this->assertXpath($xpath); // -- Menu. $xpath = '//div[@class = "tt-menu-default"]/ul[@class = "menu"]/li/a[text() = "Link 1"]/../ul[@class = "menu"]/li/ul[@class = "menu"]/li/a[text() = "Link 3"]'; $this->assertXpath($xpath); // -- Menu with level option. $xpath = '//div[@class = "tt-menu-level"]/ul[@class = "menu"]/li/a[text() = "Link 2"]/../ul[@class = "menu"]/li/a[text() = "Link 3"]'; $this->assertXpath($xpath); // -- Menu with depth option. $xpath = '//div[@class = "tt-menu-depth"]/ul[@class = "menu"]/li[not(ul)]/a[text() = "Link 1"]'; $this->assertXpath($xpath); // -- Form. $xpath = '//div[@class = "tt-form"]/form[@class="system-cron-settings"]/input[@type = "submit" and @value = "Run cron"]'; $this->assertXpath($xpath); // -- Image by FID. $xpath = '//div[@class = "tt-image-by-fid"]/img[contains(@src, "/files/image-test.png")]'; $this->assertXpath($xpath); // -- Image by URI. $xpath = '//div[@class = "tt-image-by-uri"]/img[contains(@src, "/files/image-test.png")]'; $this->assertXpath($xpath); // -- Image by UUID. $xpath = '//div[@class = "tt-image-by-uuid"]/img[contains(@src, "/files/image-test.png")]'; $this->assertXpath($xpath); // -- Image with style. $xpath = '//div[@class = "tt-image-with-style"]/img[contains(@src, "/files/styles/thumbnail/public/image-test.png")]'; $this->assertXpath($xpath); // -- Image with responsive style. $xpath = '//div[@class = "tt-image-with-responsive-style"]/picture/img[contains(@src, "/files/image-test.png")]'; $this->assertXpath($xpath); // -- Token. $xpath = '//div[@class = "tt-token" and text() = "Drupal"]'; $this->assertXpath($xpath); // -- Token with context. $xpath = '//div[@class = "tt-token-data" and text() = "Alpha"]'; $this->assertXpath($xpath); // -- Config. $xpath = '//div[@class = "tt-config" and text() = "Anonymous"]'; $this->assertXpath($xpath); // -- Page title. $xpath = '//div[@class = "tt-title" and text() = "Twig Tweak Test"]'; $this->assertXpath($xpath); // -- URL. $url = Url::fromUserInput('/node/1', ['absolute' => TRUE])->toString(); $xpath = sprintf('//div[@class = "tt-url"]/div[@data-case="default" and text() = "%s"]', $url); $this->assertXpath($xpath); // -- URL with langcode. $url = str_replace('node/1', 'ru/node/1', $url); $xpath = sprintf('//div[@class = "tt-url"]/div[@data-case="with-langcode" and text() = "%s"]', $url); $this->assertXpath($xpath); // -- Link. $url = Url::fromUserInput('/node/1/edit', ['absolute' => TRUE]); $link = Link::fromTextAndUrl('Edit', $url)->toString(); $xpath = '//div[@class = "tt-link"]'; self::assertEquals($link, $this->xpath($xpath)[0]->getHtml()); // -- Link with HTML. $text = Markup::create('Edit'); $url = Url::fromUserInput('/node/1/edit', ['absolute' => TRUE]); $link = Link::fromTextAndUrl($text, $url)->toString(); $xpath = '//div[@class = "tt-link-html"]'; self::assertEquals($link, $this->xpath($xpath)[0]->getHtml()); // -- Status messages. $xpath = '//div[@class = "tt-messages"]//div[contains(@class, "messages--status") and contains(., "Hello world!")]'; $this->assertXpath($xpath); // -- Breadcrumb. $xpath = '//div[@class = "tt-breadcrumb"]/nav[@class = "breadcrumb"]/ol/li/a[text() = "Home"]'; $this->assertXpath($xpath); // -- Protected link. $xpath = '//div[@class = "tt-link-access"]'; self::assertSame('', $this->xpath($xpath)[0]->getHtml()); // -- Token replacement. $xpath = '//div[@class = "tt-token-replace" and text() = "Site name: Drupal"]'; $this->assertXpath($xpath); // -- Contextual links. $xpath = '//div[@class="tt-contextual-links" and not(div[@data-contextual-id])]'; $this->assertXpath($xpath); /** @var \Drupal\user\RoleInterface $role */ $role = Role::load(Role::ANONYMOUS_ID); $this->grantPermissions($role, ['access contextual links']); $this->drupalGet($this->getUrl()); $xpath = '//div[@class="tt-contextual-links" and div[@data-contextual-id]]'; $this->assertXpath($xpath); // -- Replace (preg). $xpath = '//div[@class = "tt-preg-replace" and text() = "FOO-bar"]'; $this->assertXpath($xpath); // -- Image style. $xpath = '//div[@class = "tt-image-style" and contains(text(), "styles/thumbnail/public/images/ocean.jpg")]'; $this->assertXpath($xpath); // -- Transliterate. $xpath = '//div[@class = "tt-transliterate" and contains(text(), "Privet!")]'; $this->assertXpath($xpath); // -- Text format. $xpath = '//div[@class = "tt-check-markup"]'; self::assertSame('bold strong', $this->xpath($xpath)[0]->getHtml()); // -- Format size. $xpath = '//div[@class = "tt-format-size"]'; self::assertSame('12.06 KB', $this->xpath($xpath)[0]->getHtml()); // -- Truncate. $xpath = '//div[@class = "tt-truncate" and text() = "Hello…"]'; $this->assertXpath($xpath); // -- 'with'. $xpath = '//div[@class = "tt-with"]/b[text() = "Example"]'; $this->assertXpath($xpath); // -- Nested 'with'. $xpath = '//div[@class = "tt-with-nested" and text() = "{alpha:{beta:{gamma:456}}}"]'; $this->assertXpath($xpath); // -- 'children'. $xpath = '//div[@class = "tt-children" and text() = "doremi"]'; $this->assertXpath($xpath); // -- Entity view. $xpath = '//div[@class = "tt-node-view"]/article[contains(@class, "node--view-mode-default")]/h2[a/span[text() = "Alpha"]]'; $xpath .= '/following-sibling::div[@class = "node__content"]/div/p'; $this->assertXpath($xpath); // -- Field list view. $xpath = '//div[@class = "tt-field-list-view"]/span[contains(@class, "field--name-title") and text() = "Alpha"]'; $this->assertXpath($xpath); // -- Field item view. $xpath = '//div[@class = "tt-field-item-view" and text() = "Alpha"]'; $this->assertXpath($xpath); // -- File URI from image field. $xpath = '//div[@class = "tt-file-uri-from-image-field" and contains(text(), "public://image-test.png")]'; $this->assertXpath($xpath); // -- File URI from a specific image field item. $xpath = '//div[@class = "tt-file-uri-from-image-field-delta" and contains(text(), "public://image-test.png")]'; $this->assertXpath($xpath); // -- File URI from media field. $xpath = '//div[@class = "tt-file-uri-from-media-field" and contains(text(), "public://image-1.png")]'; $this->assertXpath($xpath); // -- Image style from File URI from media field. $xpath = '//div[@class = "tt-image-style-from-file-uri-from-media-field" and contains(text(), "styles/thumbnail/public/image-1.png")]'; $this->assertXpath($xpath); // -- File URL from URI (relative). $xpath = '//div[@class = "tt-file-url-from-uri" and contains(text(), "/files/image-test.png") and not(contains(text(), "http://"))]'; $this->assertXpath($xpath); // -- File URL from URI (absolute). $xpath = '//div[@class = "tt-file-url-from-uri-absolute" and contains(text(), "/files/image-test.png") and contains(text(), "http://")]'; $this->assertXpath($xpath); // -- File URL from image field. $xpath = '//div[@class = "tt-file-url-from-image-field" and contains(text(), "/files/image-test.png")]'; $this->assertXpath($xpath); // -- File URL from a specific image field item. $xpath = '//div[@class = "tt-file-url-from-image-field-delta" and contains(text(), "/files/image-test.png")]'; $this->assertXpath($xpath); // -- File URL from media field. $xpath = '//div[@class = "tt-file-url-from-media-field" and contains(text(), "/files/image-1.png")]'; $this->assertXpath($xpath); // -- Entity translation. // This is just a smoke test because the node is not translatable. $xpath = '//div[@class = "tt-translation" and contains(text(), "Alpha")]'; $this->assertXpath($xpath); // -- Hook twig_tweak_functions_alter(). $xpath = '//div[@class = "tt-functions_alter" and text() = "-=bar=-"]'; $this->assertXpath($xpath); // -- Hook twig_tweak_filters_alter(). $xpath = '//div[@class = "tt-filters_alter" and text() = "bar"]'; $this->assertXpath($xpath); // -- Hook twig_tweak_tests_alter(). $xpath = '//div[@class = "tt-tests_alter" and text() = "Yes"]'; $this->assertXpath($xpath); } /** * Checks that an element specified by a the xpath exists on the current page. */ private function assertXpath(string $xpath): void { $this->assertSession()->elementExists('xpath', $xpath); } }