3 namespace Drupal\Tests\rdf\Functional;
6 use Drupal\file\Entity\File;
7 use Drupal\image\Entity\ImageStyle;
8 use Drupal\node\Entity\NodeType;
9 use Drupal\node\NodeInterface;
10 use Drupal\Tests\BrowserTestBase;
11 use Drupal\comment\Entity\Comment;
12 use Drupal\taxonomy\Entity\Term;
15 * Tests the RDF mappings and RDFa markup of the standard profile.
19 class StandardProfileTest extends BrowserTestBase {
22 * The profile used during tests.
24 * This purposefully uses the standard profile.
28 public $profile = 'standard';
36 * @var \Drupal\user\UserInterface
41 * @var \Drupal\user\UserInterface
46 * @var \Drupal\taxonomy\TermInterface
51 * @var \Drupal\file\FileInterface
56 * @var \Drupal\node\NodeInterface
61 * @var \Drupal\comment\CommentInterface
63 protected $articleComment;
66 * @var \Drupal\node\NodeInterface
83 protected $articleUri;
98 protected $articleCommentUri;
103 protected $commenterUri;
105 protected function setUp() {
108 // Use Classy theme for testing markup output.
109 \Drupal::service('theme_handler')->install(['classy']);
110 $this->config('system.theme')->set('default', 'classy')->save();
112 $this->baseUri = \Drupal::url('<front>', [], ['absolute' => TRUE]);
114 // Create two test users.
115 $this->adminUser = $this->drupalCreateUser([
116 'administer content types',
117 'administer comments',
121 $this->webUser = $this->drupalCreateUser([
124 'skip comment approval',
128 $this->drupalLogin($this->adminUser);
131 $this->term = Term::create([
132 'name' => $this->randomMachineName(),
133 'description' => $this->randomMachineName(),
139 file_unmanaged_copy(\Drupal::root() . '/core/misc/druplicon.png', 'public://example.jpg');
140 $this->image = File::create(['uri' => 'public://example.jpg']);
141 $this->image->save();
144 $article_settings = [
146 'promote' => NodeInterface::PROMOTED,
149 'target_id' => $this->image->id(),
154 'target_id' => $this->term->id(),
158 $this->article = $this->drupalCreateNode($article_settings);
159 // Create second article to test teaser list.
160 $this->drupalCreateNode(['type' => 'article', 'promote' => NodeInterface::PROMOTED]);
162 // Create article comment.
163 $this->articleComment = $this->saveComment($this->article->id(), $this->webUser->id(), NULL, 0);
166 $this->page = $this->drupalCreateNode(['type' => 'page']);
170 $image_file = $this->article->get('field_image')->entity;
171 $this->imageUri = ImageStyle::load('large')->buildUrl($image_file->getFileUri());
173 $this->termUri = $this->term->url('canonical', ['absolute' => TRUE]);
175 $this->articleUri = $this->article->url('canonical', ['absolute' => TRUE]);
177 $this->pageUri = $this->page->url('canonical', ['absolute' => TRUE]);
179 $this->authorUri = $this->adminUser->url('canonical', ['absolute' => TRUE]);
181 $this->articleCommentUri = $this->articleComment->url('canonical', ['absolute' => TRUE]);
183 $this->commenterUri = $this->webUser->url('canonical', ['absolute' => TRUE]);
185 $this->drupalLogout();
189 * Tests that data is exposed correctly when using standard profile.
191 * Because tests using standard profile take a very long time to run, and
192 * because there is no manipulation of config or data within the test, simply
193 * run all the tests from within this function.
195 public function testRdfaOutput() {
196 $this->doFrontPageRdfaTests();
197 $this->doArticleRdfaTests();
198 $this->doPageRdfaTests();
199 $this->doUserRdfaTests();
200 $this->doTermRdfaTests();
204 * Tests that data is exposed in the front page teasers.
206 protected function doFrontPageRdfaTests() {
207 // Feed the HTML into the parser.
208 $graph = $this->getRdfGraph(Url::fromRoute('<front>'));
210 // Ensure that both articles are listed.
211 $this->assertEqual(2, count($graph->allOfType('http://schema.org/Article')), 'Two articles found on front page.');
213 // Test interaction count.
216 'value' => 'UserComments:1',
219 $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/interactionCount', $expected_value), "Teaser comment count was found (schema:interactionCount).");
221 // Test the properties that are common between pages and articles and are
222 // displayed in full and teaser mode.
223 $this->assertRdfaCommonNodeProperties($graph, $this->article, "Teaser");
224 // Test properties that are displayed in both teaser and full mode.
225 $this->assertRdfaArticleProperties($graph, "Teaser");
227 // @todo Once the image points to the original instead of the processed
228 // image, move this to testArticleProperties().
229 $image_file = $this->article->get('field_image')->entity;
230 $image_uri = ImageStyle::load('medium')->buildUrl($image_file->getFileUri());
233 'value' => $image_uri,
235 $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/image', $expected_value), "Teaser image was found (schema:image).");
239 * Tests that article data is exposed using RDFa.
241 * Two fields are not tested for output here. Changed date is not displayed
242 * on the page, so there is no test for output in node view. Comment count is
243 * displayed in teaser view, so it is tested in the front article tests.
245 protected function doArticleRdfaTests() {
246 // Feed the HTML into the parser.
247 $graph = $this->getRdfGraph($this->article->urlInfo());
250 $this->assertEqual($graph->type($this->articleUri), 'schema:Article', 'Article type was found (schema:Article).');
252 // Test the properties that are common between pages and articles.
253 $this->assertRdfaCommonNodeProperties($graph, $this->article, "Article");
254 // Test properties that are displayed in both teaser and full mode.
255 $this->assertRdfaArticleProperties($graph, "Article");
256 // Test the comment properties displayed on articles.
257 $this->assertRdfaNodeCommentProperties($graph);
259 // @todo Once the image points to the original instead of the processed
260 // image, move this to testArticleProperties().
263 'value' => $this->imageUri,
265 $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/image', $expected_value), "Article image was found (schema:image).");
269 * Tests that page data is exposed using RDFa.
271 * Two fields are not tested for output here. Changed date is not displayed
272 * on the page, so there is no test for output in node view. Comment count is
273 * displayed in teaser view, so it is tested in the front page tests.
275 protected function doPageRdfaTests() {
276 // The standard profile hides the created date on pages. Revert display to
278 // @todo Clean-up standard profile defaults.
279 $node_type = NodeType::load('page');
280 $node_type->setDisplaySubmitted(TRUE);
283 // Feed the HTML into the parser.
284 $graph = $this->getRdfGraph($this->page->urlInfo());
287 $this->assertEqual($graph->type($this->pageUri), 'schema:WebPage', 'Page type was found (schema:WebPage).');
289 // Test the properties that are common between pages and articles.
290 $this->assertRdfaCommonNodeProperties($graph, $this->page, "Page");
294 * Tests that user data is exposed on user page.
296 protected function doUserRdfaTests() {
297 $this->drupalLogin($this->rootUser);
299 // Feed the HTML into the parser.
300 $graph = $this->getRdfGraph($this->adminUser->urlInfo());
303 $this->assertEqual($graph->type($this->authorUri), 'schema:Person', "User type was found (schema:Person) on user page.");
308 'value' => $this->adminUser->label(),
310 $this->assertTrue($graph->hasProperty($this->authorUri, 'http://schema.org/name', $expected_value), "User name was found (schema:name) on user page.");
312 $this->drupalLogout();
316 * Tests that term data is exposed on term page.
318 protected function doTermRdfaTests() {
319 // Feed the HTML into the parser.
320 $graph = $this->getRdfGraph($this->term->urlInfo());
323 $this->assertEqual($graph->type($this->termUri), 'schema:Thing', "Term type was found (schema:Thing) on term page.");
328 'value' => $this->term->getName(),
331 $this->assertTrue($graph->hasProperty($this->termUri, 'http://schema.org/name', $expected_value), "Term name was found (schema:name) on term page.");
333 // @todo Add test for term description once it is a field:
334 // https://www.drupal.org/node/569434.
338 * Tests output for properties held in common between articles and pages.
340 * @param \EasyRdf_Graph $graph
341 * The EasyRDF graph object.
342 * @param \Drupal\node\NodeInterface $node
343 * The node being displayed.
344 * @param string $message_prefix
345 * The word to use in the test assertion message.
347 protected function assertRdfaCommonNodeProperties($graph, NodeInterface $node, $message_prefix) {
348 $uri = $node->url('canonical', ['absolute' => TRUE]);
353 'value' => $node->get('title')->value,
356 $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/name', $expected_value), "$message_prefix title was found (schema:name).");
361 'value' => format_date($node->get('created')->value, 'custom', 'c', 'UTC'),
364 $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/dateCreated', $expected_value), "$message_prefix created date was found (schema:dateCreated) in teaser.");
369 'value' => $node->get('body')->value,
372 $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/text', $expected_value), "$message_prefix body was found (schema:text) in teaser.");
377 'value' => $this->authorUri,
379 $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/author', $expected_value), "$message_prefix author was found (schema:author) in teaser.");
382 $this->assertEqual($graph->type($this->authorUri), 'schema:Person', "$message_prefix author type was found (schema:Person).");
387 'value' => $this->adminUser->label(),
389 $this->assertTrue($graph->hasProperty($this->authorUri, 'http://schema.org/name', $expected_value), "$message_prefix author name was found (schema:name).");
393 * Tests output for article properties displayed in both view modes.
395 * @param \EasyRdf_Graph $graph
396 * The EasyRDF graph object.
397 * @param string $message_prefix
398 * The word to use in the test assertion message.
400 protected function assertRdfaArticleProperties($graph, $message_prefix) {
404 'value' => $this->termUri,
406 $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/about', $expected_value), "$message_prefix tag was found (schema:about).");
409 // @todo Enable with https://www.drupal.org/node/2072791.
410 // $this->assertEqual($graph->type($this->termUri), 'schema:Thing', 'Tag type was found (schema:Thing).');
415 'value' => $this->term->getName(),
418 // @todo Enable with https://www.drupal.org/node/2072791.
419 // $this->assertTrue($graph->hasProperty($this->termUri, 'http://schema.org/name', $expected_value), "$message_prefix name was found (schema:name).");
423 * Tests output for comment properties on nodes in full page view mode.
425 * @param \EasyRdf_Graph $graph
426 * The EasyRDF graph object.
428 protected function assertRdfaNodeCommentProperties($graph) {
429 // Relationship between node and comment.
432 'value' => $this->articleCommentUri,
434 $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/comment', $expected_value), 'Relationship between node and comment found (schema:comment).');
437 $this->assertEqual($graph->type($this->articleCommentUri), 'schema:Comment', 'Comment type was found (schema:Comment).');
442 'value' => $this->articleComment->get('subject')->value,
445 $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/name', $expected_value), 'Article comment title was found (schema:name).');
447 // Comment created date.
450 'value' => format_date($this->articleComment->get('created')->value, 'custom', 'c', 'UTC'),
453 $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/dateCreated', $expected_value), 'Article comment created date was found (schema:dateCreated).');
456 $text = $this->articleComment->get('comment_body')->value;
459 // There is an extra carriage return in the when parsing comments as
460 // output by Bartik, so it must be added to the expected value.
465 $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/text', $expected_value), 'Article comment body was found (schema:text).');
470 'value' => $this->commenterUri,
472 $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/author', $expected_value), 'Article comment author was found (schema:author).');
474 // Comment author type.
475 $this->assertEqual($graph->type($this->commenterUri), 'schema:Person', 'Comment author type was found (schema:Person).');
477 // Comment author name.
480 'value' => $this->webUser->getUsername(),
482 $this->assertTrue($graph->hasProperty($this->commenterUri, 'http://schema.org/name', $expected_value), 'Comment author name was found (schema:name).');
486 * Creates a comment entity.
489 * Node id which will hold the comment.
491 * User id of the author of the comment. Can be NULL if $contact provided.
492 * @param mixed $contact
493 * Set to NULL for no contact info, TRUE to ignore success checking, and
494 * array of values to set contact info.
496 * Comment id of the parent comment in a thread.
498 * @return \Drupal\comment\Entity\Comment
501 protected function saveComment($nid, $uid, $contact = NULL, $pid = 0) {
504 'entity_type' => 'node',
505 'field_name' => 'comment',
508 'subject' => $this->randomMachineName(),
509 'comment_body' => $this->randomMachineName(),
516 $comment = Comment::create($values);
522 * Get the EasyRdf_Graph object for a page.
524 * @param \Drupal\Core\Url $url
525 * The URL object for the page.
527 * @return \EasyRdf_Graph
528 * The RDF graph object.
530 protected function getRdfGraph(Url $url) {
531 $parser = new \EasyRdf_Parser_Rdfa();
532 $graph = new \EasyRdf_Graph();
533 $parser->parse($graph, $this->drupalGet($url), 'rdfa', $this->baseUri);