Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / rdf / tests / src / Functional / StandardProfileTest.php
1 <?php
2
3 namespace Drupal\Tests\rdf\Functional;
4
5 use Drupal\Core\Url;
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;
13
14 /**
15  * Tests the RDF mappings and RDFa markup of the standard profile.
16  *
17  * @group rdf
18  */
19 class StandardProfileTest extends BrowserTestBase {
20
21   /**
22    * The profile used during tests.
23    *
24    * This purposefully uses the standard profile.
25    *
26    * @var string
27    */
28   public $profile = 'standard';
29
30   /**
31    * @var string
32    */
33   protected $baseUri;
34
35   /**
36    * @var \Drupal\user\UserInterface
37    */
38   protected $adminUser;
39
40   /**
41    * @var \Drupal\user\UserInterface
42    */
43   protected $webUser;
44
45   /**
46    * @var \Drupal\taxonomy\TermInterface
47    */
48   protected $term;
49
50   /**
51    * @var \Drupal\file\FileInterface
52    */
53   protected $image;
54
55   /**
56    * @var \Drupal\node\NodeInterface
57    */
58   protected $article;
59
60   /**
61    * @var \Drupal\comment\CommentInterface
62    */
63   protected $articleComment;
64
65   /**
66    * @var \Drupal\node\NodeInterface
67    */
68   protected $page;
69
70   /**
71    * @var string
72    */
73   protected $imageUri;
74
75   /**
76    * @var string
77    */
78   protected $termUri;
79
80   /**
81    * @var string
82    */
83   protected $articleUri;
84
85   /**
86    * @var string
87    */
88   protected $pageUri;
89
90   /**
91    * @var string
92    */
93   protected $authorUri;
94
95   /**
96    * @var string
97    */
98   protected $articleCommentUri;
99
100   /**
101    * @var string
102    */
103   protected $commenterUri;
104
105   protected function setUp() {
106     parent::setUp();
107
108     // Use Classy theme for testing markup output.
109     \Drupal::service('theme_handler')->install(['classy']);
110     $this->config('system.theme')->set('default', 'classy')->save();
111
112     $this->baseUri = \Drupal::url('<front>', [], ['absolute' => TRUE]);
113
114     // Create two test users.
115     $this->adminUser = $this->drupalCreateUser([
116       'administer content types',
117       'administer comments',
118       'access comments',
119       'access content',
120     ]);
121     $this->webUser = $this->drupalCreateUser([
122       'access comments',
123       'post comments',
124       'skip comment approval',
125       'access content',
126     ]);
127
128     $this->drupalLogin($this->adminUser);
129
130     // Create term.
131     $this->term = Term::create([
132       'name' => $this->randomMachineName(),
133       'description' => $this->randomMachineName(),
134       'vid' => 'tags',
135     ]);
136     $this->term->save();
137
138     // Create image.
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();
142
143     // Create article.
144     $article_settings = [
145       'type' => 'article',
146       'promote' => NodeInterface::PROMOTED,
147       'field_image' => [
148         [
149           'target_id' => $this->image->id(),
150         ],
151       ],
152       'field_tags' => [
153         [
154           'target_id' => $this->term->id(),
155         ],
156       ],
157     ];
158     $this->article = $this->drupalCreateNode($article_settings);
159     // Create second article to test teaser list.
160     $this->drupalCreateNode(['type' => 'article', 'promote' => NodeInterface::PROMOTED]);
161
162     // Create article comment.
163     $this->articleComment = $this->saveComment($this->article->id(), $this->webUser->id(), NULL, 0);
164
165     // Create page.
166     $this->page = $this->drupalCreateNode(['type' => 'page']);
167
168     // Set URIs.
169     // Image.
170     $image_file = $this->article->get('field_image')->entity;
171     $this->imageUri = ImageStyle::load('large')->buildUrl($image_file->getFileUri());
172     // Term.
173     $this->termUri = $this->term->url('canonical', ['absolute' => TRUE]);
174     // Article.
175     $this->articleUri = $this->article->url('canonical', ['absolute' => TRUE]);
176     // Page.
177     $this->pageUri = $this->page->url('canonical', ['absolute' => TRUE]);
178     // Author.
179     $this->authorUri = $this->adminUser->url('canonical', ['absolute' => TRUE]);
180     // Comment.
181     $this->articleCommentUri = $this->articleComment->url('canonical', ['absolute' => TRUE]);
182     // Commenter.
183     $this->commenterUri = $this->webUser->url('canonical', ['absolute' => TRUE]);
184
185     $this->drupalLogout();
186   }
187
188   /**
189    * Tests that data is exposed correctly when using standard profile.
190    *
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.
194    */
195   public function testRdfaOutput() {
196     $this->doFrontPageRdfaTests();
197     $this->doArticleRdfaTests();
198     $this->doPageRdfaTests();
199     $this->doUserRdfaTests();
200     $this->doTermRdfaTests();
201   }
202
203   /**
204    * Tests that data is exposed in the front page teasers.
205    */
206   protected function doFrontPageRdfaTests() {
207     // Feed the HTML into the parser.
208     $graph = $this->getRdfGraph(Url::fromRoute('<front>'));
209
210     // Ensure that both articles are listed.
211     $this->assertEqual(2, count($graph->allOfType('http://schema.org/Article')), 'Two articles found on front page.');
212
213     // Test interaction count.
214     $expected_value = [
215       'type' => 'literal',
216       'value' => 'UserComments:1',
217       'lang' => 'en',
218     ];
219     $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/interactionCount', $expected_value), "Teaser comment count was found (schema:interactionCount).");
220
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");
226
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());
231     $expected_value = [
232       'type' => 'uri',
233       'value' => $image_uri,
234     ];
235     $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/image', $expected_value), "Teaser image was found (schema:image).");
236   }
237
238   /**
239    * Tests that article data is exposed using RDFa.
240    *
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.
244    */
245   protected function doArticleRdfaTests() {
246     // Feed the HTML into the parser.
247     $graph = $this->getRdfGraph($this->article->urlInfo());
248
249     // Type.
250     $this->assertEqual($graph->type($this->articleUri), 'schema:Article', 'Article type was found (schema:Article).');
251
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);
258
259     // @todo Once the image points to the original instead of the processed
260     //   image, move this to testArticleProperties().
261     $expected_value = [
262       'type' => 'uri',
263       'value' => $this->imageUri,
264     ];
265     $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/image', $expected_value), "Article image was found (schema:image).");
266   }
267
268   /**
269    * Tests that page data is exposed using RDFa.
270    *
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.
274    */
275   protected function doPageRdfaTests() {
276     // The standard profile hides the created date on pages. Revert display to
277     // true for testing.
278     // @todo Clean-up standard profile defaults.
279     $node_type = NodeType::load('page');
280     $node_type->setDisplaySubmitted(TRUE);
281     $node_type->save();
282
283     // Feed the HTML into the parser.
284     $graph = $this->getRdfGraph($this->page->urlInfo());
285
286     // Type.
287     $this->assertEqual($graph->type($this->pageUri), 'schema:WebPage', 'Page type was found (schema:WebPage).');
288
289     // Test the properties that are common between pages and articles.
290     $this->assertRdfaCommonNodeProperties($graph, $this->page, "Page");
291   }
292
293   /**
294    * Tests that user data is exposed on user page.
295    */
296   protected function doUserRdfaTests() {
297     $this->drupalLogin($this->rootUser);
298
299     // Feed the HTML into the parser.
300     $graph = $this->getRdfGraph($this->adminUser->urlInfo());
301
302     // User type.
303     $this->assertEqual($graph->type($this->authorUri), 'schema:Person', "User type was found (schema:Person) on user page.");
304
305     // User name.
306     $expected_value = [
307       'type' => 'literal',
308       'value' => $this->adminUser->label(),
309     ];
310     $this->assertTrue($graph->hasProperty($this->authorUri, 'http://schema.org/name', $expected_value), "User name was found (schema:name) on user page.");
311
312     $this->drupalLogout();
313   }
314
315   /**
316    * Tests that term data is exposed on term page.
317    */
318   protected function doTermRdfaTests() {
319     // Feed the HTML into the parser.
320     $graph = $this->getRdfGraph($this->term->urlInfo());
321
322     // Term type.
323     $this->assertEqual($graph->type($this->termUri), 'schema:Thing', "Term type was found (schema:Thing) on term page.");
324
325     // Term name.
326     $expected_value = [
327       'type' => 'literal',
328       'value' => $this->term->getName(),
329       'lang' => 'en',
330     ];
331     $this->assertTrue($graph->hasProperty($this->termUri, 'http://schema.org/name', $expected_value), "Term name was found (schema:name) on term page.");
332
333     // @todo Add test for term description once it is a field:
334     //   https://www.drupal.org/node/569434.
335   }
336
337   /**
338    * Tests output for properties held in common between articles and pages.
339    *
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.
346    */
347   protected function assertRdfaCommonNodeProperties($graph, NodeInterface $node, $message_prefix) {
348     $uri = $node->url('canonical', ['absolute' => TRUE]);
349
350     // Title.
351     $expected_value = [
352       'type' => 'literal',
353       'value' => $node->get('title')->value,
354       'lang' => 'en',
355     ];
356     $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/name', $expected_value), "$message_prefix title was found (schema:name).");
357
358     // Created date.
359     $expected_value = [
360       'type' => 'literal',
361       'value' => format_date($node->get('created')->value, 'custom', 'c', 'UTC'),
362       'lang' => 'en',
363     ];
364     $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/dateCreated', $expected_value), "$message_prefix created date was found (schema:dateCreated) in teaser.");
365
366     // Body.
367     $expected_value = [
368       'type' => 'literal',
369       'value' => $node->get('body')->value,
370       'lang' => 'en',
371     ];
372     $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/text', $expected_value), "$message_prefix body was found (schema:text) in teaser.");
373
374     // Author.
375     $expected_value = [
376       'type' => 'uri',
377       'value' => $this->authorUri,
378     ];
379     $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/author', $expected_value), "$message_prefix author was found (schema:author) in teaser.");
380
381     // Author type.
382     $this->assertEqual($graph->type($this->authorUri), 'schema:Person', "$message_prefix author type was found (schema:Person).");
383
384     // Author name.
385     $expected_value = [
386       'type' => 'literal',
387       'value' => $this->adminUser->label(),
388     ];
389     $this->assertTrue($graph->hasProperty($this->authorUri, 'http://schema.org/name', $expected_value), "$message_prefix author name was found (schema:name).");
390   }
391
392   /**
393    * Tests output for article properties displayed in both view modes.
394    *
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.
399    */
400   protected function assertRdfaArticleProperties($graph, $message_prefix) {
401     // Tags.
402     $expected_value = [
403       'type' => 'uri',
404       'value' => $this->termUri,
405     ];
406     $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/about', $expected_value), "$message_prefix tag was found (schema:about).");
407
408     // Tag type.
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).');
411
412     // Tag name.
413     $expected_value = [
414       'type' => 'literal',
415       'value' => $this->term->getName(),
416       'lang' => 'en',
417     ];
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).");
420   }
421
422   /**
423    * Tests output for comment properties on nodes in full page view mode.
424    *
425    * @param \EasyRdf_Graph $graph
426    *   The EasyRDF graph object.
427    */
428   protected function assertRdfaNodeCommentProperties($graph) {
429     // Relationship between node and comment.
430     $expected_value = [
431       'type' => 'uri',
432       'value' => $this->articleCommentUri,
433     ];
434     $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/comment', $expected_value), 'Relationship between node and comment found (schema:comment).');
435
436     // Comment type.
437     $this->assertEqual($graph->type($this->articleCommentUri), 'schema:Comment', 'Comment type was found (schema:Comment).');
438
439     // Comment title.
440     $expected_value = [
441       'type' => 'literal',
442       'value' => $this->articleComment->get('subject')->value,
443       'lang' => 'en',
444     ];
445     $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/name', $expected_value), 'Article comment title was found (schema:name).');
446
447     // Comment created date.
448     $expected_value = [
449       'type' => 'literal',
450       'value' => format_date($this->articleComment->get('created')->value, 'custom', 'c', 'UTC'),
451       'lang' => 'en',
452     ];
453     $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/dateCreated', $expected_value), 'Article comment created date was found (schema:dateCreated).');
454
455     // Comment body.
456     $text = $this->articleComment->get('comment_body')->value;
457     $expected_value = [
458       'type' => 'literal',
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.
461       'value' => "$text
462 ",
463       'lang' => 'en',
464     ];
465     $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/text', $expected_value), 'Article comment body was found (schema:text).');
466
467     // Comment uid.
468     $expected_value = [
469       'type' => 'uri',
470       'value' => $this->commenterUri,
471     ];
472     $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/author', $expected_value), 'Article comment author was found (schema:author).');
473
474     // Comment author type.
475     $this->assertEqual($graph->type($this->commenterUri), 'schema:Person', 'Comment author type was found (schema:Person).');
476
477     // Comment author name.
478     $expected_value = [
479       'type' => 'literal',
480       'value' => $this->webUser->getUsername(),
481     ];
482     $this->assertTrue($graph->hasProperty($this->commenterUri, 'http://schema.org/name', $expected_value), 'Comment author name was found (schema:name).');
483   }
484
485   /**
486    * Creates a comment entity.
487    *
488    * @param int $nid
489    *   Node id which will hold the comment.
490    * @param int $uid
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.
495    * @param int $pid
496    *   Comment id of the parent comment in a thread.
497    *
498    * @return \Drupal\comment\Entity\Comment
499    *   The saved comment.
500    */
501   protected function saveComment($nid, $uid, $contact = NULL, $pid = 0) {
502     $values = [
503       'entity_id' => $nid,
504       'entity_type' => 'node',
505       'field_name' => 'comment',
506       'uid' => $uid,
507       'pid' => $pid,
508       'subject' => $this->randomMachineName(),
509       'comment_body' => $this->randomMachineName(),
510       'status' => 1,
511     ];
512     if ($contact) {
513       $values += $contact;
514     }
515
516     $comment = Comment::create($values);
517     $comment->save();
518     return $comment;
519   }
520
521   /**
522    * Get the EasyRdf_Graph object for a page.
523    *
524    * @param \Drupal\Core\Url $url
525    *   The URL object for the page.
526    *
527    * @return \EasyRdf_Graph
528    *   The RDF graph object.
529    */
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);
534     return $graph;
535   }
536
537 }