3 namespace Drupal\metatag\Tests;
5 use Drupal\Component\Render\FormattableMarkup;
6 use Drupal\simpletest\WebTestBase;
7 use Symfony\Component\DependencyInjection\Container;
10 * Base class to test all of the meta tags that are in a specific module.
12 abstract class MetatagTagsTestBase extends WebTestBase {
14 use MetatagHelperTrait;
19 public static $modules = [
20 // This is needed for the 'access content' permission.
29 // This module will be used to load a static page which will inherit the
30 // global defaults, without loading values from other configs.
31 'metatag_test_custom_route',
35 * All of the meta tags defined by this module which will be tested.
42 * The tag to look for when testing the output.
46 private $testTag = 'meta';
53 private $testNameAttribute = 'name';
56 * The attribute to look for when testing the output.
60 private $testValueAttribute = 'content';
65 protected function setUp() {
68 // Use the test page as the front page.
69 $this->config('system.site')->set('page.front', '/test-page')->save();
71 // Initiate session with a user who can manage meta tags and access content.
73 'administer site configuration',
74 'administer meta tags',
77 $account = $this->drupalCreateUser($permissions);
78 $this->drupalLogin($account);
82 * Tests that this module's tags are available.
84 public function testTagsArePresent() {
85 // Load the global config.
86 $this->drupalGet('admin/config/search/metatag/global');
87 $this->assertResponse(200);
89 // Confirm the various meta tags are available.
90 foreach ($this->tags as $tag) {
91 // Look for a custom method named "{$tagname}TestFieldXpath", if found
92 // use that method to get the xpath definition for this meta tag,
93 // otherwise it defaults to just looking for a text input field.
94 $method = $this->getMethodFromTagCallback($tag, 'test_field_xpath');
95 if (method_exists($this, $method)) {
96 $xpath = $this->$method();
99 $xpath = "//input[@name='{$tag}' and @type='text']";
102 $this->assertFieldByXPath($xpath, NULL, new FormattableMarkup('Found the @tag meta tag field.', ['@tag' => $tag]));
105 $this->drupalLogout();
109 * Confirm that each tag can be saved and that the output is correct.
111 public function testTagsInputOutput() {
112 // Create a content type to test with.
113 $this->createContentType(['type' => 'page']);
114 $this->drupalCreateNode([
115 'title' => t('Hello, world!'),
119 // Test a non-entity path and an entity path. The non-entity path inherits
120 // the global meta tags, the entity path inherits from its entity config.
123 'admin/config/search/metatag/global',
124 'metatag_test_custom_route',
125 'Saved the Global Metatag defaults.',
128 'admin/config/search/metatag/node',
130 'Saved the Content Metatag defaults',
134 foreach ($paths as $item) {
135 list($path1, $path2, $save_message) = $item;
137 // Load the global config.
138 $this->drupalGet($path1);
139 $this->assertResponse(200);
141 // Update the Global defaults and test them.
142 $all_values = $values = [];
143 foreach ($this->tags as $tag_name) {
144 // Look for a custom method named "{$tagname}TestKey", if found use
145 // that method to get the test string for this meta tag, otherwise it
146 // defaults to the meta tag's name.
147 $method = $this->getMethodFromTagCallback($tag_name, 'TestKey');
148 if (method_exists($this, $method)) {
149 $test_key = $this->$method();
152 $test_key = $tag_name;
155 // Look for a custom method named "{$tagname}TestValue", if found use
156 // that method to get the test string for this meta tag, otherwise it
157 // defaults to just generating a random string.
158 $method = $this->getMethodFromTagCallback($tag_name, 'TestValue');
159 if (method_exists($this, $method)) {
160 $test_value = $this->$method();
163 // Generate a random string. Generating two words of 8 characters each
164 // with simple machine name -style strings.
165 $test_value = $this->randomMachineName() . ' ' . $this->randomMachineName();
168 $values[$test_key] = $test_value;
169 $all_values[$tag_name] = $test_value;
171 $this->drupalPostForm(NULL, $values, 'Save');
172 $this->assertText($save_message);
174 // Load the test page.
175 $this->drupalGet($path2);
176 $this->assertResponse(200);
178 // Look for the values.
179 foreach ($this->tags as $tag_name) {
180 // Look for a custom method named "{$tag_name}TestOutputXpath", if
181 // found use that method to get the xpath definition for this meta tag,
182 // otherwise it defaults to just looking for a meta tag matching:
183 // <$testTag $testNameAttribute=$tag_name $testValueAttribute=$value />
184 $method = $this->getMethodFromTagCallback($tag_name, 'TestOutputXpath');
185 if (method_exists($this, $method)) {
186 $xpath_string = $this->$method();
189 // Look for a custom method named "{$tag_name}TestTag", if
190 // found use that method to get the xpath definition for this meta
191 // tag, otherwise it defaults to $this->testTag.
192 $method = $this->getMethodFromTagCallback($tag_name, 'TestTag');
193 if (method_exists($this, $method)) {
194 $xpath_tag = $this->$method();
197 $xpath_tag = $this->testTag;
200 // Look for a custom method named "{$tag_name}TestNameAttribute",
201 // if found use that method to get the xpath definition for this meta
202 // tag, otherwise it defaults to $this->testNameAttribute.
203 $method = $this->getMethodFromTagCallback($tag_name, 'TestNameAttribute');
204 if (method_exists($this, $method)) {
205 $xpath_name_attribute = $this->$method();
208 $xpath_name_attribute = $this->testNameAttribute;
211 // Look for a custom method named "{$tag_name}TestTagName", if
212 // found use that method to get the xpath definition for this meta
213 // tag, otherwise it defaults to $tag_name.
214 $method = $this->getMethodFromTagCallback($tag_name, 'TestTagName');
215 if (method_exists($this, $method)) {
216 $xpath_name_tag = $this->$method();
219 $xpath_name_tag = $this->getTestTagName($tag_name);
222 // Compile the xpath.
223 $xpath_string = "//{$xpath_tag}[@{$xpath_name_attribute}='{$xpath_name_tag}']";
226 // Look for a custom method named "{$tag_name}TestValueAttribute", if
227 // found use that method to get the xpath definition for this meta tag,
228 // otherwise it defaults to $this->testValueAttribute.
229 $method = $this->getMethodFromTagCallback($tag_name, 'TestValueAttribute');
230 if (method_exists($this, $method)) {
231 $xpath_value_attribute = $this->$method();
234 $xpath_value_attribute = $this->testValueAttribute;
237 // Extract the meta tag from the HTML.
238 $xpath = $this->xpath($xpath_string);
239 $this->assertEqual(count($xpath), 1, new FormattableMarkup('One @name tag found.', ['@name' => $tag_name]));
240 if (count($xpath) !== 1) {
241 $this->verbose($xpath, $tag_name . ': ' . $xpath_string);
244 // Run various tests on the output variables.
245 // Most meta tags have an attribute, but some don't.
246 if (!empty($xpath_value_attribute)) {
247 $this->assertTrue($xpath_value_attribute);
248 $this->assertTrue(isset($xpath[0][$xpath_value_attribute]));
249 // Help with debugging.
250 if (!isset($xpath[0][$xpath_value_attribute])) {
251 $this->verbose($xpath, $tag_name . ': ' . $xpath_string);
254 if ((string) $xpath[0][$xpath_value_attribute] != $all_values[$tag_name]) {
255 $this->verbose($xpath, $tag_name . ': ' . $xpath_string);
257 $this->assertTrue($xpath[0][$xpath_value_attribute]);
258 $this->assertEqual($xpath[0][$xpath_value_attribute], $all_values[$tag_name], "The meta tag was found with the expected value.");
262 $this->verbose($xpath, $tag_name . ': ' . $xpath_string);
263 $this->assertTrue((string) $xpath[0]);
264 $this->assertEqual((string) $xpath[0], $all_values[$tag_name], "The meta tag was found with the expected value.");
269 $this->drupalLogout();
273 * Convert a tag's internal name to the string which is actually used in HTML.
275 * The meta tag internal name will be machine names, i.e. only contain a-z,
276 * A-Z, 0-9 and the underline character. Meta tag names will actually contain
277 * any possible character.
279 * @param string $tag_name
280 * The tag name to be converted.
283 * The converted tag name.
285 private function getTestTagName($tag_name) {
290 * Generate a random value for testing meta tag fields.
292 * As a reasonable default, this will generating two words of 8 characters
293 * each with simple machine name -style strings.
298 private function getTestTagValue() {
299 return $this->randomMachineName() . ' ' . $this->randomMachineName();
303 * Generate a URL for an image.
306 * An absolute URL to a non-existent image.
308 private function randomImageUrl() {
309 return 'http://www.example.com/images/' . $this->randomMachineName() . '.png';
313 * Convert a tag name with a callback to a lowerCamelCase method name.
315 * @param string $tag_name
317 * @param string $callback
318 * The callback that is to be used.
321 * The tag name and callback concatenated together and converted to
324 private function getMethodFromTagCallback($tag_name, $callback) {
325 return lcfirst(Container::camelize($tag_name . '_' . $callback));