Chris@0: install(['classy']); Chris@0: $this->config('system.theme')->set('default', 'classy')->save(); Chris@0: Chris@18: $this->baseUri = Url::fromRoute('', [], ['absolute' => TRUE])->toString(); Chris@0: Chris@0: // Create two test users. Chris@0: $this->adminUser = $this->drupalCreateUser([ Chris@0: 'administer content types', Chris@0: 'administer comments', Chris@0: 'access comments', Chris@0: 'access content', Chris@0: ]); Chris@0: $this->webUser = $this->drupalCreateUser([ Chris@0: 'access comments', Chris@0: 'post comments', Chris@0: 'skip comment approval', Chris@0: 'access content', Chris@0: ]); Chris@0: Chris@0: $this->drupalLogin($this->adminUser); Chris@0: Chris@0: // Create term. Chris@0: $this->term = Term::create([ Chris@0: 'name' => $this->randomMachineName(), Chris@0: 'description' => $this->randomMachineName(), Chris@0: 'vid' => 'tags', Chris@0: ]); Chris@0: $this->term->save(); Chris@0: Chris@0: // Create image. Chris@18: \Drupal::service('file_system')->copy($this->root . '/core/misc/druplicon.png', 'public://example.jpg'); Chris@0: $this->image = File::create(['uri' => 'public://example.jpg']); Chris@0: $this->image->save(); Chris@0: Chris@0: // Create article. Chris@0: $article_settings = [ Chris@0: 'type' => 'article', Chris@0: 'promote' => NodeInterface::PROMOTED, Chris@0: 'field_image' => [ Chris@0: [ Chris@0: 'target_id' => $this->image->id(), Chris@0: ], Chris@0: ], Chris@0: 'field_tags' => [ Chris@0: [ Chris@0: 'target_id' => $this->term->id(), Chris@0: ], Chris@0: ], Chris@0: ]; Chris@0: $this->article = $this->drupalCreateNode($article_settings); Chris@0: // Create second article to test teaser list. Chris@0: $this->drupalCreateNode(['type' => 'article', 'promote' => NodeInterface::PROMOTED]); Chris@0: Chris@0: // Create article comment. Chris@0: $this->articleComment = $this->saveComment($this->article->id(), $this->webUser->id(), NULL, 0); Chris@0: Chris@0: // Create page. Chris@0: $this->page = $this->drupalCreateNode(['type' => 'page']); Chris@0: Chris@0: // Set URIs. Chris@0: // Image. Chris@0: $image_file = $this->article->get('field_image')->entity; Chris@0: $this->imageUri = ImageStyle::load('large')->buildUrl($image_file->getFileUri()); Chris@0: // Term. Chris@18: $this->termUri = $this->term->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: // Article. Chris@18: $this->articleUri = $this->article->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: // Page. Chris@18: $this->pageUri = $this->page->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: // Author. Chris@18: $this->authorUri = $this->adminUser->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: // Comment. Chris@18: $this->articleCommentUri = $this->articleComment->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: // Commenter. Chris@18: $this->commenterUri = $this->webUser->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: Chris@0: $this->drupalLogout(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that data is exposed correctly when using standard profile. Chris@0: * Chris@0: * Because tests using standard profile take a very long time to run, and Chris@0: * because there is no manipulation of config or data within the test, simply Chris@0: * run all the tests from within this function. Chris@0: */ Chris@0: public function testRdfaOutput() { Chris@0: $this->doFrontPageRdfaTests(); Chris@0: $this->doArticleRdfaTests(); Chris@0: $this->doPageRdfaTests(); Chris@0: $this->doUserRdfaTests(); Chris@0: $this->doTermRdfaTests(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that data is exposed in the front page teasers. Chris@0: */ Chris@0: protected function doFrontPageRdfaTests() { Chris@0: // Feed the HTML into the parser. Chris@0: $graph = $this->getRdfGraph(Url::fromRoute('')); Chris@0: Chris@0: // Ensure that both articles are listed. Chris@0: $this->assertEqual(2, count($graph->allOfType('http://schema.org/Article')), 'Two articles found on front page.'); Chris@0: Chris@0: // Test interaction count. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => 'UserComments:1', Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/interactionCount', $expected_value), "Teaser comment count was found (schema:interactionCount)."); Chris@0: Chris@0: // Test the properties that are common between pages and articles and are Chris@0: // displayed in full and teaser mode. Chris@0: $this->assertRdfaCommonNodeProperties($graph, $this->article, "Teaser"); Chris@0: // Test properties that are displayed in both teaser and full mode. Chris@0: $this->assertRdfaArticleProperties($graph, "Teaser"); Chris@0: Chris@0: // @todo Once the image points to the original instead of the processed Chris@0: // image, move this to testArticleProperties(). Chris@0: $image_file = $this->article->get('field_image')->entity; Chris@0: $image_uri = ImageStyle::load('medium')->buildUrl($image_file->getFileUri()); Chris@0: $expected_value = [ Chris@0: 'type' => 'uri', Chris@0: 'value' => $image_uri, Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/image', $expected_value), "Teaser image was found (schema:image)."); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that article data is exposed using RDFa. Chris@0: * Chris@0: * Two fields are not tested for output here. Changed date is not displayed Chris@0: * on the page, so there is no test for output in node view. Comment count is Chris@0: * displayed in teaser view, so it is tested in the front article tests. Chris@0: */ Chris@0: protected function doArticleRdfaTests() { Chris@0: // Feed the HTML into the parser. Chris@18: $graph = $this->getRdfGraph($this->article->toUrl()); Chris@0: Chris@0: // Type. Chris@0: $this->assertEqual($graph->type($this->articleUri), 'schema:Article', 'Article type was found (schema:Article).'); Chris@0: Chris@0: // Test the properties that are common between pages and articles. Chris@0: $this->assertRdfaCommonNodeProperties($graph, $this->article, "Article"); Chris@0: // Test properties that are displayed in both teaser and full mode. Chris@0: $this->assertRdfaArticleProperties($graph, "Article"); Chris@0: // Test the comment properties displayed on articles. Chris@0: $this->assertRdfaNodeCommentProperties($graph); Chris@0: Chris@0: // @todo Once the image points to the original instead of the processed Chris@0: // image, move this to testArticleProperties(). Chris@0: $expected_value = [ Chris@0: 'type' => 'uri', Chris@0: 'value' => $this->imageUri, Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/image', $expected_value), "Article image was found (schema:image)."); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that page data is exposed using RDFa. Chris@0: * Chris@0: * Two fields are not tested for output here. Changed date is not displayed Chris@0: * on the page, so there is no test for output in node view. Comment count is Chris@0: * displayed in teaser view, so it is tested in the front page tests. Chris@0: */ Chris@0: protected function doPageRdfaTests() { Chris@0: // The standard profile hides the created date on pages. Revert display to Chris@0: // true for testing. Chris@0: // @todo Clean-up standard profile defaults. Chris@0: $node_type = NodeType::load('page'); Chris@0: $node_type->setDisplaySubmitted(TRUE); Chris@0: $node_type->save(); Chris@0: Chris@0: // Feed the HTML into the parser. Chris@18: $graph = $this->getRdfGraph($this->page->toUrl()); Chris@0: Chris@0: // Type. Chris@0: $this->assertEqual($graph->type($this->pageUri), 'schema:WebPage', 'Page type was found (schema:WebPage).'); Chris@0: Chris@0: // Test the properties that are common between pages and articles. Chris@0: $this->assertRdfaCommonNodeProperties($graph, $this->page, "Page"); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that user data is exposed on user page. Chris@0: */ Chris@0: protected function doUserRdfaTests() { Chris@0: $this->drupalLogin($this->rootUser); Chris@0: Chris@0: // Feed the HTML into the parser. Chris@18: $graph = $this->getRdfGraph($this->adminUser->toUrl()); Chris@0: Chris@0: // User type. Chris@0: $this->assertEqual($graph->type($this->authorUri), 'schema:Person', "User type was found (schema:Person) on user page."); Chris@0: Chris@0: // User name. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $this->adminUser->label(), Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->authorUri, 'http://schema.org/name', $expected_value), "User name was found (schema:name) on user page."); Chris@0: Chris@0: $this->drupalLogout(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests that term data is exposed on term page. Chris@0: */ Chris@0: protected function doTermRdfaTests() { Chris@0: // Feed the HTML into the parser. Chris@18: $graph = $this->getRdfGraph($this->term->toUrl()); Chris@0: Chris@0: // Term type. Chris@0: $this->assertEqual($graph->type($this->termUri), 'schema:Thing', "Term type was found (schema:Thing) on term page."); Chris@0: Chris@0: // Term name. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $this->term->getName(), Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->termUri, 'http://schema.org/name', $expected_value), "Term name was found (schema:name) on term page."); Chris@0: Chris@0: // @todo Add test for term description once it is a field: Chris@0: // https://www.drupal.org/node/569434. Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests output for properties held in common between articles and pages. Chris@0: * Chris@0: * @param \EasyRdf_Graph $graph Chris@0: * The EasyRDF graph object. Chris@0: * @param \Drupal\node\NodeInterface $node Chris@0: * The node being displayed. Chris@0: * @param string $message_prefix Chris@0: * The word to use in the test assertion message. Chris@0: */ Chris@0: protected function assertRdfaCommonNodeProperties($graph, NodeInterface $node, $message_prefix) { Chris@18: $uri = $node->toUrl('canonical', ['absolute' => TRUE])->toString(); Chris@0: Chris@0: // Title. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $node->get('title')->value, Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/name', $expected_value), "$message_prefix title was found (schema:name)."); Chris@0: Chris@0: // Created date. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@18: 'value' => $this->container->get('date.formatter')->format($node->get('created')->value, 'custom', 'c', 'UTC'), Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/dateCreated', $expected_value), "$message_prefix created date was found (schema:dateCreated) in teaser."); Chris@0: Chris@0: // Body. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $node->get('body')->value, Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/text', $expected_value), "$message_prefix body was found (schema:text) in teaser."); Chris@0: Chris@0: // Author. Chris@0: $expected_value = [ Chris@0: 'type' => 'uri', Chris@0: 'value' => $this->authorUri, Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($uri, 'http://schema.org/author', $expected_value), "$message_prefix author was found (schema:author) in teaser."); Chris@0: Chris@0: // Author type. Chris@0: $this->assertEqual($graph->type($this->authorUri), 'schema:Person', "$message_prefix author type was found (schema:Person)."); Chris@0: Chris@0: // Author name. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $this->adminUser->label(), Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->authorUri, 'http://schema.org/name', $expected_value), "$message_prefix author name was found (schema:name)."); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests output for article properties displayed in both view modes. Chris@0: * Chris@0: * @param \EasyRdf_Graph $graph Chris@0: * The EasyRDF graph object. Chris@0: * @param string $message_prefix Chris@0: * The word to use in the test assertion message. Chris@0: */ Chris@0: protected function assertRdfaArticleProperties($graph, $message_prefix) { Chris@0: // Tags. Chris@0: $expected_value = [ Chris@0: 'type' => 'uri', Chris@0: 'value' => $this->termUri, Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/about', $expected_value), "$message_prefix tag was found (schema:about)."); Chris@0: Chris@0: // Tag type. Chris@0: // @todo Enable with https://www.drupal.org/node/2072791. Chris@0: // $this->assertEqual($graph->type($this->termUri), 'schema:Thing', 'Tag type was found (schema:Thing).'); Chris@0: Chris@0: // Tag name. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $this->term->getName(), Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: // @todo Enable with https://www.drupal.org/node/2072791. Chris@0: // $this->assertTrue($graph->hasProperty($this->termUri, 'http://schema.org/name', $expected_value), "$message_prefix name was found (schema:name)."); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests output for comment properties on nodes in full page view mode. Chris@0: * Chris@0: * @param \EasyRdf_Graph $graph Chris@0: * The EasyRDF graph object. Chris@0: */ Chris@0: protected function assertRdfaNodeCommentProperties($graph) { Chris@0: // Relationship between node and comment. Chris@0: $expected_value = [ Chris@0: 'type' => 'uri', Chris@0: 'value' => $this->articleCommentUri, Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleUri, 'http://schema.org/comment', $expected_value), 'Relationship between node and comment found (schema:comment).'); Chris@0: Chris@0: // Comment type. Chris@0: $this->assertEqual($graph->type($this->articleCommentUri), 'schema:Comment', 'Comment type was found (schema:Comment).'); Chris@0: Chris@0: // Comment title. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: 'value' => $this->articleComment->get('subject')->value, Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/name', $expected_value), 'Article comment title was found (schema:name).'); Chris@0: Chris@0: // Comment created date. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@18: 'value' => $this->container->get('date.formatter')->format($this->articleComment->get('created')->value, 'custom', 'c', 'UTC'), Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/dateCreated', $expected_value), 'Article comment created date was found (schema:dateCreated).'); Chris@0: Chris@0: // Comment body. Chris@0: $text = $this->articleComment->get('comment_body')->value; Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@0: // There is an extra carriage return in the when parsing comments as Chris@0: // output by Bartik, so it must be added to the expected value. Chris@0: 'value' => "$text Chris@0: ", Chris@0: 'lang' => 'en', Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/text', $expected_value), 'Article comment body was found (schema:text).'); Chris@0: Chris@0: // Comment uid. Chris@0: $expected_value = [ Chris@0: 'type' => 'uri', Chris@0: 'value' => $this->commenterUri, Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->articleCommentUri, 'http://schema.org/author', $expected_value), 'Article comment author was found (schema:author).'); Chris@0: Chris@0: // Comment author type. Chris@0: $this->assertEqual($graph->type($this->commenterUri), 'schema:Person', 'Comment author type was found (schema:Person).'); Chris@0: Chris@0: // Comment author name. Chris@0: $expected_value = [ Chris@0: 'type' => 'literal', Chris@18: 'value' => $this->webUser->getAccountName(), Chris@0: ]; Chris@0: $this->assertTrue($graph->hasProperty($this->commenterUri, 'http://schema.org/name', $expected_value), 'Comment author name was found (schema:name).'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Creates a comment entity. Chris@0: * Chris@0: * @param int $nid Chris@0: * Node id which will hold the comment. Chris@0: * @param int $uid Chris@0: * User id of the author of the comment. Can be NULL if $contact provided. Chris@0: * @param mixed $contact Chris@0: * Set to NULL for no contact info, TRUE to ignore success checking, and Chris@0: * array of values to set contact info. Chris@0: * @param int $pid Chris@0: * Comment id of the parent comment in a thread. Chris@0: * Chris@0: * @return \Drupal\comment\Entity\Comment Chris@0: * The saved comment. Chris@0: */ Chris@0: protected function saveComment($nid, $uid, $contact = NULL, $pid = 0) { Chris@0: $values = [ Chris@0: 'entity_id' => $nid, Chris@0: 'entity_type' => 'node', Chris@0: 'field_name' => 'comment', Chris@0: 'uid' => $uid, Chris@0: 'pid' => $pid, Chris@0: 'subject' => $this->randomMachineName(), Chris@0: 'comment_body' => $this->randomMachineName(), Chris@0: 'status' => 1, Chris@0: ]; Chris@0: if ($contact) { Chris@0: $values += $contact; Chris@0: } Chris@0: Chris@0: $comment = Comment::create($values); Chris@0: $comment->save(); Chris@0: return $comment; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get the EasyRdf_Graph object for a page. Chris@0: * Chris@0: * @param \Drupal\Core\Url $url Chris@0: * The URL object for the page. Chris@0: * Chris@0: * @return \EasyRdf_Graph Chris@0: * The RDF graph object. Chris@0: */ Chris@0: protected function getRdfGraph(Url $url) { Chris@0: $parser = new \EasyRdf_Parser_Rdfa(); Chris@0: $graph = new \EasyRdf_Graph(); Chris@0: $parser->parse($graph, $this->drupalGet($url), 'rdfa', $this->baseUri); Chris@0: return $graph; Chris@0: } Chris@0: Chris@0: }