cms/drupal/modules/rdf/rdf.test
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * Tests for rdf.module.
       
     6  */
       
     7 
       
     8 class RdfMappingHookTestCase extends DrupalWebTestCase {
       
     9   public static function getInfo() {
       
    10     return array(
       
    11       'name' => 'RDF mapping hook',
       
    12       'description' => 'Test hook_rdf_mapping().',
       
    13       'group' => 'RDF',
       
    14     );
       
    15   }
       
    16 
       
    17   function setUp() {
       
    18     parent::setUp('rdf', 'rdf_test', 'field_test');
       
    19   }
       
    20 
       
    21   /**
       
    22    * Test that hook_rdf_mapping() correctly returns and processes mapping.
       
    23    */
       
    24   function testMapping() {
       
    25     // Test that the mapping is returned correctly by the hook.
       
    26     $mapping = rdf_mapping_load('test_entity', 'test_bundle');
       
    27     $this->assertIdentical($mapping['rdftype'], array('sioc:Post'), 'Mapping for rdftype is sioc:Post.');
       
    28     $this->assertIdentical($mapping['title'], array('predicates' => array('dc:title')), 'Mapping for title is dc:title.');
       
    29     $this->assertIdentical($mapping['created'], array(
       
    30       'predicates' => array('dc:created'),
       
    31       'datatype' => 'xsd:dateTime',
       
    32       'callback' => 'date_iso8601',
       
    33     ), t('Mapping for created is dc:created with datatype xsd:dateTime and callback date_iso8601.'));
       
    34     $this->assertIdentical($mapping['uid'], array('predicates' => array('sioc:has_creator', 'dc:creator'), 'type' => 'rel'), 'Mapping for uid is sioc:has_creator and dc:creator, and type is rel.');
       
    35 
       
    36     $mapping = rdf_mapping_load('test_entity', 'test_bundle_no_mapping');
       
    37     $this->assertEqual($mapping, array(), 'Empty array returned when an entity type, bundle pair has no mapping.');
       
    38   }
       
    39 }
       
    40 
       
    41 /**
       
    42  * Test RDFa markup generation.
       
    43  */
       
    44 class RdfRdfaMarkupTestCase extends DrupalWebTestCase {
       
    45   public static function getInfo() {
       
    46     return array(
       
    47       'name' => 'RDFa markup',
       
    48       'description' => 'Test RDFa markup generation.',
       
    49       'group' => 'RDF',
       
    50     );
       
    51   }
       
    52 
       
    53   function setUp() {
       
    54     parent::setUp('rdf', 'field_test', 'rdf_test');
       
    55   }
       
    56 
       
    57   /**
       
    58    * Test rdf_rdfa_attributes().
       
    59    */
       
    60   function testDrupalRdfaAttributes() {
       
    61     // Same value as the one in the HTML tag (no callback function).
       
    62     $expected_attributes = array(
       
    63       'property' => array('dc:title'),
       
    64     );
       
    65     $mapping = rdf_mapping_load('test_entity', 'test_bundle');
       
    66     $attributes = rdf_rdfa_attributes($mapping['title']);
       
    67     ksort($expected_attributes);
       
    68     ksort($attributes);
       
    69     $this->assertEqual($expected_attributes, $attributes);
       
    70 
       
    71     // Value different from the one in the HTML tag (callback function).
       
    72     $date = 1252750327;
       
    73     $isoDate = date('c', $date);
       
    74     $expected_attributes = array(
       
    75       'datatype' => 'xsd:dateTime',
       
    76       'property' => array('dc:created'),
       
    77       'content' => $isoDate,
       
    78     );
       
    79     $mapping = rdf_mapping_load('test_entity', 'test_bundle');
       
    80     $attributes = rdf_rdfa_attributes($mapping['created'], $date);
       
    81     ksort($expected_attributes);
       
    82     ksort($attributes);
       
    83     $this->assertEqual($expected_attributes, $attributes);
       
    84 
       
    85     // Same value as the one in the HTML tag with datatype.
       
    86     $expected_attributes = array(
       
    87       'datatype' => 'foo:bar1type',
       
    88       'property' => array('foo:bar1'),
       
    89     );
       
    90     $mapping = rdf_mapping_load('test_entity', 'test_bundle');
       
    91     $attributes = rdf_rdfa_attributes($mapping['foobar1']);
       
    92     ksort($expected_attributes);
       
    93     ksort($attributes);
       
    94     $this->assertEqual($expected_attributes, $attributes);
       
    95 
       
    96     // ObjectProperty mapping (rel).
       
    97     $expected_attributes = array(
       
    98       'rel' => array('sioc:has_creator', 'dc:creator'),
       
    99     );
       
   100     $mapping = rdf_mapping_load('test_entity', 'test_bundle');
       
   101     $attributes = rdf_rdfa_attributes($mapping['foobar_objproperty1']);
       
   102     ksort($expected_attributes);
       
   103     ksort($attributes);
       
   104     $this->assertEqual($expected_attributes, $attributes);
       
   105 
       
   106     // Inverse ObjectProperty mapping (rev).
       
   107     $expected_attributes = array(
       
   108       'rev' => array('sioc:reply_of'),
       
   109     );
       
   110     $mapping = rdf_mapping_load('test_entity', 'test_bundle');
       
   111     $attributes = rdf_rdfa_attributes($mapping['foobar_objproperty2']);
       
   112     ksort($expected_attributes);
       
   113     ksort($attributes);
       
   114     $this->assertEqual($expected_attributes, $attributes);
       
   115   }
       
   116 
       
   117   /**
       
   118    * Ensure that file fields have the correct resource as the object in RDFa
       
   119    * when displayed as a teaser.
       
   120    */
       
   121   function testAttributesInMarkupFile() {
       
   122     // Create a user to post the image.
       
   123     $admin_user = $this->drupalCreateUser(array('edit own article content', 'revert revisions', 'administer content types'));
       
   124     $this->drupalLogin($admin_user);
       
   125 
       
   126     $langcode = LANGUAGE_NONE;
       
   127     $bundle_name = "article";
       
   128 
       
   129     $field_name = 'file_test';
       
   130     $field = array(
       
   131       'field_name' => $field_name,
       
   132       'type' => 'file',
       
   133     );
       
   134     field_create_field($field);
       
   135     $instance = array(
       
   136       'field_name' => $field_name,
       
   137       'entity_type' => 'node',
       
   138       'bundle' => $bundle_name,
       
   139       'display' => array(
       
   140         'teaser' => array(
       
   141           'type' => 'file_default',
       
   142         ),
       
   143       ),
       
   144     );
       
   145     field_create_instance($instance);
       
   146 
       
   147     // Set the RDF mapping for the new field.
       
   148     $rdf_mapping = rdf_mapping_load('node', $bundle_name);
       
   149     $rdf_mapping += array($field_name => array('predicates' => array('rdfs:seeAlso'), 'type' => 'rel'));
       
   150     $rdf_mapping_save = array('mapping' => $rdf_mapping, 'type' => 'node', 'bundle' => $bundle_name);
       
   151     rdf_mapping_save($rdf_mapping_save);
       
   152 
       
   153     // Get the test file that simpletest provides.
       
   154     $file = current($this->drupalGetTestFiles('text'));
       
   155 
       
   156     // Prepare image variables.
       
   157     $image_field = "field_image";
       
   158     // Get the test image that simpletest provides.
       
   159     $image = current($this->drupalGetTestFiles('image'));
       
   160 
       
   161     // Create an array for drupalPost with the field names as the keys and
       
   162     // the URIs for the test files as the values.
       
   163     $edit = array("files[" . $field_name . "_" . $langcode . "_0]" => drupal_realpath($file->uri),
       
   164                   "files[" . $image_field . "_" . $langcode . "_0]" => drupal_realpath($image->uri));
       
   165 
       
   166     // Create node and save, then edit node to upload files.
       
   167     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
   168     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
       
   169 
       
   170     // Get filenames and nid for comparison with HTML output.
       
   171     $file_filename = $file->filename;
       
   172     $image_filename = $image->filename;
       
   173     $nid = $node->nid;
       
   174     // Navigate to front page, where node is displayed in teaser form.
       
   175     $this->drupalGet('node');
       
   176 
       
   177     // We only check to make sure that the resource attribute contains '.txt'
       
   178     // instead of the full file name because the filename is altered on upload.
       
   179     $file_rel = $this->xpath('//div[contains(@about, :node-uri)]//div[contains(@rel, "rdfs:seeAlso") and contains(@resource, ".txt")]', array(
       
   180       ':node-uri' => 'node/' . $nid,
       
   181     ));
       
   182     $this->assertTrue(!empty($file_rel), "Attribute 'rel' set on file field. Attribute 'resource' is also set.");
       
   183     $image_rel = $this->xpath('//div[contains(@about, :node-uri)]//div[contains(@rel, "rdfs:seeAlso") and contains(@resource, :image)]//img[contains(@typeof, "foaf:Image")]', array(
       
   184       ':node-uri' => 'node/' . $nid,
       
   185       ':image' => $image_filename,
       
   186     ));
       
   187 
       
   188     $this->assertTrue(!empty($image_rel), "Attribute 'rel' set on image field. Attribute 'resource' is also set.");
       
   189 
       
   190     // Edits the node to add tags.
       
   191     $tag1 = $this->randomName(8);
       
   192     $tag2 = $this->randomName(8);
       
   193     $edit = array();
       
   194     $edit['field_tags[' . LANGUAGE_NONE . ']'] = "$tag1, $tag2";
       
   195     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
       
   196     // Ensures the RDFa markup for the relationship between the node and its
       
   197     // tags is correct.
       
   198     $term_rdfa_meta = $this->xpath('//div[@about=:node-url and contains(@typeof, "sioc:Item") and contains(@typeof, "foaf:Document")]//ul[@class="links"]/li[@rel="dc:subject"]/a[@typeof="skos:Concept" and @datatype="" and text()=:term-name]', array(
       
   199       ':node-url' => url('node/' . $node->nid),
       
   200       ':term-name' => $tag1,
       
   201     ));
       
   202     $this->assertTrue(!empty($term_rdfa_meta), 'Property dc:subject is present for the tag1 field item.');
       
   203     $term_rdfa_meta = $this->xpath('//div[@about=:node-url and contains(@typeof, "sioc:Item") and contains(@typeof, "foaf:Document")]//ul[@class="links"]/li[@rel="dc:subject"]/a[@typeof="skos:Concept" and @datatype="" and text()=:term-name]', array(
       
   204       ':node-url' => url('node/' . $node->nid),
       
   205       ':term-name' => $tag2,
       
   206     ));
       
   207     $this->assertTrue(!empty($term_rdfa_meta), 'Property dc:subject is present for the tag2 field item.');
       
   208   }
       
   209 }
       
   210 
       
   211 class RdfCrudTestCase extends DrupalWebTestCase {
       
   212   public static function getInfo() {
       
   213     return array(
       
   214       'name' => 'RDF mapping CRUD functions',
       
   215       'description' => 'Test the RDF mapping CRUD functions.',
       
   216       'group' => 'RDF',
       
   217     );
       
   218   }
       
   219 
       
   220   function setUp() {
       
   221     parent::setUp('rdf', 'rdf_test');
       
   222   }
       
   223 
       
   224   /**
       
   225    * Test inserting, loading, updating, and deleting RDF mappings.
       
   226    */
       
   227   function testCRUD() {
       
   228     // Verify loading of a default mapping.
       
   229     $mapping = _rdf_mapping_load('test_entity', 'test_bundle');
       
   230     $this->assertTrue(count($mapping), 'Default mapping was found.');
       
   231 
       
   232     // Verify saving a mapping.
       
   233     $mapping = array(
       
   234       'type' => 'crud_test_entity',
       
   235       'bundle' => 'crud_test_bundle',
       
   236       'mapping' => array(
       
   237         'rdftype' => array('sioc:Post'),
       
   238         'title' => array(
       
   239           'predicates' => array('dc:title'),
       
   240         ),
       
   241         'uid' => array(
       
   242           'predicates' => array('sioc:has_creator', 'dc:creator'),
       
   243           'type' => 'rel',
       
   244         ),
       
   245       ),
       
   246     );
       
   247     $this->assertTrue(rdf_mapping_save($mapping) === SAVED_NEW, 'Mapping was saved.');
       
   248 
       
   249     // Read the raw record from the {rdf_mapping} table.
       
   250     $result = db_query('SELECT * FROM {rdf_mapping} WHERE type = :type AND bundle = :bundle', array(':type' => $mapping['type'], ':bundle' => $mapping['bundle']));
       
   251     $stored_mapping = $result->fetchAssoc();
       
   252     $stored_mapping['mapping'] = unserialize($stored_mapping['mapping']);
       
   253     $this->assertEqual($mapping, $stored_mapping, 'Mapping was stored properly in the {rdf_mapping} table.');
       
   254 
       
   255     // Verify loading of saved mapping.
       
   256     $this->assertEqual($mapping['mapping'], _rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Saved mapping loaded successfully.');
       
   257 
       
   258     // Verify updating of mapping.
       
   259     $mapping['mapping']['title'] = array(
       
   260       'predicates' => array('dc2:bar2'),
       
   261     );
       
   262     $this->assertTrue(rdf_mapping_save($mapping) === SAVED_UPDATED, 'Mapping was updated.');
       
   263 
       
   264     // Read the raw record from the {rdf_mapping} table.
       
   265     $result = db_query('SELECT * FROM {rdf_mapping} WHERE type = :type AND bundle = :bundle', array(':type' => $mapping['type'], ':bundle' => $mapping['bundle']));
       
   266     $stored_mapping = $result->fetchAssoc();
       
   267     $stored_mapping['mapping'] = unserialize($stored_mapping['mapping']);
       
   268     $this->assertEqual($mapping, $stored_mapping, 'Updated mapping was stored properly in the {rdf_mapping} table.');
       
   269 
       
   270     // Verify loading of saved mapping.
       
   271     $this->assertEqual($mapping['mapping'], _rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Saved mapping loaded successfully.');
       
   272 
       
   273     // Verify deleting of mapping.
       
   274     $this->assertTrue(rdf_mapping_delete($mapping['type'], $mapping['bundle']), 'Mapping was deleted.');
       
   275     $this->assertFalse(_rdf_mapping_load($mapping['type'], $mapping['bundle']), 'Deleted mapping is no longer found in the database.');
       
   276   }
       
   277 }
       
   278 
       
   279 class RdfMappingDefinitionTestCase extends TaxonomyWebTestCase {
       
   280   public static function getInfo() {
       
   281     return array(
       
   282       'name' => 'RDF mapping definition functionality',
       
   283       'description' => 'Test the different types of RDF mappings and ensure the proper RDFa markup in included in nodes and user profile pages.',
       
   284       'group' => 'RDF',
       
   285     );
       
   286   }
       
   287 
       
   288   function setUp() {
       
   289     parent::setUp('rdf', 'rdf_test', 'blog');
       
   290   }
       
   291 
       
   292   /**
       
   293    * Create a node of type blog and test whether the RDF mapping defined for
       
   294    * this node type in rdf_test.module is used in the node page.
       
   295    */
       
   296   function testAttributesInMarkup1() {
       
   297     $node = $this->drupalCreateNode(array('type' => 'blog'));
       
   298     $isoDate = date('c', $node->changed);
       
   299     $url = url('node/' . $node->nid);
       
   300     $this->drupalGet('node/' . $node->nid);
       
   301 
       
   302     // Ensure the default bundle mapping for node is used. These attributes come
       
   303     // from the node default bundle definition.
       
   304     $blog_title = $this->xpath("//div[@about='$url']/span[@property='dc:title' and @content='$node->title']");
       
   305     $blog_meta = $this->xpath("//div[(@about='$url') and (@typeof='sioct:Weblog')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']");
       
   306     $this->assertTrue(!empty($blog_title), 'Property dc:title is present in meta tag.');
       
   307     $this->assertTrue(!empty($blog_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.');
       
   308   }
       
   309 
       
   310   /**
       
   311    * Create a content type and a node of type test_bundle_hook_install and test
       
   312    * whether the RDF mapping defined in rdf_test.install is used.
       
   313    */
       
   314   function testAttributesInMarkup2() {
       
   315     $type = $this->drupalCreateContentType(array('type' => 'test_bundle_hook_install'));
       
   316     // Create node with single quotation mark title to ensure it does not get
       
   317     // escaped more than once.
       
   318     $node = $this->drupalCreateNode(array(
       
   319       'type' => 'test_bundle_hook_install',
       
   320       'title' => $this->randomName(8) . "'",
       
   321     ));
       
   322     $isoDate = date('c', $node->changed);
       
   323     $url = url('node/' . $node->nid);
       
   324     $this->drupalGet('node/' . $node->nid);
       
   325 
       
   326     // Ensure the mapping defined in rdf_module.test is used.
       
   327     $test_bundle_title = $this->xpath("//div[@about='$url']/span[@property='dc:title' and @content=\"$node->title\"]");
       
   328     $test_bundle_meta = $this->xpath("//div[(@about='$url') and contains(@typeof, 'foo:mapping_install1') and contains(@typeof, 'bar:mapping_install2')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']");
       
   329     $this->assertTrue(!empty($test_bundle_title), 'Property dc:title is present in meta tag.');
       
   330     $this->assertTrue(!empty($test_bundle_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.');
       
   331   }
       
   332 
       
   333   /**
       
   334    * Create a random content type and node and ensure the default mapping for
       
   335    * node is used.
       
   336    */
       
   337   function testAttributesInMarkup3() {
       
   338     $type = $this->drupalCreateContentType();
       
   339     $node = $this->drupalCreateNode(array('type' => $type->type));
       
   340     $isoDate = date('c', $node->changed);
       
   341     $url = url('node/' . $node->nid);
       
   342     $this->drupalGet('node/' . $node->nid);
       
   343 
       
   344     // Ensure the default bundle mapping for node is used. These attributes come
       
   345     // from the node default bundle definition.
       
   346     $random_bundle_title = $this->xpath("//div[@about='$url']/span[@property='dc:title' and @content='$node->title']");
       
   347     $random_bundle_meta = $this->xpath("//div[(@about='$url') and contains(@typeof, 'sioc:Item') and contains(@typeof, 'foaf:Document')]//span[contains(@property, 'dc:date') and contains(@property, 'dc:created') and @datatype='xsd:dateTime' and @content='$isoDate']");
       
   348     $this->assertTrue(!empty($random_bundle_title), 'Property dc:title is present in meta tag.');
       
   349     $this->assertTrue(!empty($random_bundle_meta), 'RDF type is present on post. Properties dc:date and dc:created are present on post date.');
       
   350   }
       
   351 
       
   352   /**
       
   353    * Create a random user and ensure the default mapping for user is used.
       
   354    */
       
   355   function testUserAttributesInMarkup() {
       
   356     // Create two users, one with access to user profiles.
       
   357     $user1 = $this->drupalCreateUser(array('access user profiles'));
       
   358     $user2 = $this->drupalCreateUser();
       
   359     $username = $user2->name;
       
   360     $this->drupalLogin($user1);
       
   361     // Browse to the user profile page.
       
   362     $this->drupalGet('user/' . $user2->uid);
       
   363     // Ensure the default bundle mapping for user is used on the user profile
       
   364     // page. These attributes come from the user default bundle definition.
       
   365     $account_uri = url('user/' . $user2->uid);
       
   366     $person_uri = url('user/' . $user2->uid, array('fragment' => 'me'));
       
   367 
       
   368     $user2_profile_about = $this->xpath('//div[@class="profile" and @typeof="sioc:UserAccount" and @about=:account-uri]', array(
       
   369       ':account-uri' => $account_uri,
       
   370     ));
       
   371     $this->assertTrue(!empty($user2_profile_about), 'RDFa markup found on user profile page');
       
   372 
       
   373     $user_account_holder = $this->xpath('//meta[contains(@typeof, "foaf:Person") and @about=:person-uri and @resource=:account-uri and contains(@rel, "foaf:account")]', array(
       
   374       ':person-uri' => $person_uri,
       
   375       ':account-uri' => $account_uri,
       
   376     ));
       
   377     $this->assertTrue(!empty($user_account_holder), 'URI created for account holder and username set on sioc:UserAccount.');
       
   378 
       
   379     $user_username = $this->xpath('//meta[@about=:account-uri and contains(@property, "foaf:name") and @content=:username]', array(
       
   380       ':account-uri' => $account_uri,
       
   381       ':username' => $username,
       
   382     ));
       
   383     $this->assertTrue(!empty($user_username), 'foaf:name set on username.');
       
   384 
       
   385     // User 2 creates node.
       
   386     $this->drupalLogin($user2);
       
   387     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
   388     $this->drupalLogin($user1);
       
   389     $this->drupalGet('node/' . $node->nid);
       
   390     // Ensures the default bundle mapping for user is used on the Authored By
       
   391     // information on the node.
       
   392     $author_about = $this->xpath('//a[@typeof="sioc:UserAccount" and @about=:account-uri and @property="foaf:name" and @datatype="" and contains(@xml:lang, "")]', array(
       
   393       ':account-uri' => $account_uri,
       
   394     ));
       
   395     $this->assertTrue(!empty($author_about), 'RDFa markup found on author information on post. xml:lang on username is set to empty string.');
       
   396   }
       
   397 
       
   398   /**
       
   399    * Creates a random term and ensures the right RDFa markup is used.
       
   400    */
       
   401   function testTaxonomyTermRdfaAttributes() {
       
   402     $vocabulary = $this->createVocabulary();
       
   403     $term = $this->createTerm($vocabulary);
       
   404 
       
   405     // Views the term and checks that the RDFa markup is correct.
       
   406     $this->drupalGet('taxonomy/term/' . $term->tid);
       
   407     $term_url = url('taxonomy/term/' . $term->tid);
       
   408     $term_name = $term->name;
       
   409     $term_rdfa_meta = $this->xpath('//meta[@typeof="skos:Concept" and @about=:term-url and contains(@property, "rdfs:label") and contains(@property, "skos:prefLabel") and @content=:term-name]', array(
       
   410       ':term-url' => $term_url,
       
   411       ':term-name' => $term_name,
       
   412     ));
       
   413     $this->assertTrue(!empty($term_rdfa_meta), 'RDFa markup found on term page.');
       
   414   }
       
   415 }
       
   416 
       
   417 class RdfCommentAttributesTestCase extends CommentHelperCase {
       
   418 
       
   419   public static function getInfo() {
       
   420     return array(
       
   421       'name' => 'RDF comment mapping',
       
   422       'description' => 'Tests the RDFa markup of comments.',
       
   423       'group' => 'RDF',
       
   424     );
       
   425   }
       
   426 
       
   427   public function setUp() {
       
   428     parent::setUp('comment', 'rdf', 'rdf_test');
       
   429 
       
   430     $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer permissions', 'administer blocks'));
       
   431     $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'access user profiles'));
       
   432 
       
   433     // Enables anonymous user comments.
       
   434     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       
   435       'access comments' => TRUE,
       
   436       'post comments' => TRUE,
       
   437       'skip comment approval' => TRUE,
       
   438     ));
       
   439     // Allows anonymous to leave their contact information.
       
   440     $this->setCommentAnonymous(COMMENT_ANONYMOUS_MAY_CONTACT);
       
   441     $this->setCommentPreview(DRUPAL_OPTIONAL);
       
   442     $this->setCommentForm(TRUE);
       
   443     $this->setCommentSubject(TRUE);
       
   444     $this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, 'Comment paging changed.');
       
   445 
       
   446     // Creates the nodes on which the test comments will be posted.
       
   447     $this->drupalLogin($this->web_user);
       
   448     $this->node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
   449     $this->node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
       
   450     $this->drupalLogout();
       
   451   }
       
   452 
       
   453   /**
       
   454    * Tests the presence of the RDFa markup for the number of comments.
       
   455    */
       
   456   public function testNumberOfCommentsRdfaMarkup() {
       
   457     // Posts 2 comments as a registered user.
       
   458     $this->drupalLogin($this->web_user);
       
   459     $this->postComment($this->node1, $this->randomName(), $this->randomName());
       
   460     $this->postComment($this->node1, $this->randomName(), $this->randomName());
       
   461 
       
   462     // Tests number of comments in teaser view.
       
   463     $this->drupalGet('node');
       
   464     $node_url = url('node/' . $this->node1->nid);
       
   465     $comment_count_teaser = $this->xpath('//div[@about=:node-url]/span[@property="sioc:num_replies" and @content="2" and @datatype="xsd:integer"]', array(':node-url' => $node_url));
       
   466     $this->assertTrue(!empty($comment_count_teaser), 'RDFa markup for the number of comments found on teaser view.');
       
   467 
       
   468     // Tests number of comments in full node view.
       
   469     $this->drupalGet('node/' . $this->node1->nid);
       
   470     $comment_count_teaser = $this->xpath('//div[@about=:node-url]/span[@property="sioc:num_replies" and @content="2" and @datatype="xsd:integer"]', array(':node-url' => $node_url));
       
   471     $this->assertTrue(!empty($comment_count_teaser), 'RDFa markup for the number of comments found on full node view.');
       
   472   }
       
   473 
       
   474   /**
       
   475    * Tests the presence of the RDFa markup for the title, date and author and
       
   476    * homepage on registered users and anonymous comments.
       
   477    */
       
   478   public function testCommentRdfaMarkup() {
       
   479 
       
   480     // Posts comment #1 as a registered user.
       
   481     $this->drupalLogin($this->web_user);
       
   482     $comment1_subject = $this->randomName();
       
   483     $comment1_body = $this->randomName();
       
   484     $comment1 = $this->postComment($this->node1, $comment1_body, $comment1_subject);
       
   485 
       
   486     // Tests comment #1 with access to the user profile.
       
   487     $this->drupalGet('node/' . $this->node1->nid);
       
   488     $this->_testBasicCommentRdfaMarkup($comment1);
       
   489 
       
   490     // Tests comment #1 with no access to the user profile (as anonymous user).
       
   491     $this->drupalLogout();
       
   492     $this->drupalGet('node/' . $this->node1->nid);
       
   493     $this->_testBasicCommentRdfaMarkup($comment1);
       
   494 
       
   495     // Posts comment #2 as anonymous user.
       
   496     $comment2_subject = $this->randomName();
       
   497     $comment2_body = $this->randomName();
       
   498     $anonymous_user = array();
       
   499     $anonymous_user['name'] = $this->randomName();
       
   500     $anonymous_user['mail'] = 'tester@simpletest.org';
       
   501     $anonymous_user['homepage'] = 'http://example.org/';
       
   502     $comment2 = $this->postComment($this->node2, $comment2_body, $comment2_subject, $anonymous_user);
       
   503     $this->drupalGet('node/' . $this->node2->nid);
       
   504 
       
   505     // Tests comment #2 as anonymous user.
       
   506     $this->_testBasicCommentRdfaMarkup($comment2, $anonymous_user);
       
   507     // Tests the RDFa markup for the homepage (specific to anonymous comments).
       
   508     $comment_homepage = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//span[@rel="sioc:has_creator"]/a[contains(@class, "username") and @typeof="sioc:UserAccount" and @property="foaf:name" and @datatype="" and @href="http://example.org/" and contains(@rel, "foaf:page")]');
       
   509     $this->assertTrue(!empty($comment_homepage), 'RDFa markup for the homepage of anonymous user found.');
       
   510     // There should be no about attribute on anonymous comments.
       
   511     $comment_homepage = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//span[@rel="sioc:has_creator"]/a[@about]');
       
   512     $this->assertTrue(empty($comment_homepage), 'No about attribute is present on anonymous user comment.');
       
   513 
       
   514     // Tests comment #2 as logged in user.
       
   515     $this->drupalLogin($this->web_user);
       
   516     $this->drupalGet('node/' . $this->node2->nid);
       
   517     $this->_testBasicCommentRdfaMarkup($comment2, $anonymous_user);
       
   518     // Tests the RDFa markup for the homepage (specific to anonymous comments).
       
   519     $comment_homepage = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//span[@rel="sioc:has_creator"]/a[contains(@class, "username") and @typeof="sioc:UserAccount" and @property="foaf:name" and @datatype="" and @href="http://example.org/" and contains(@rel, "foaf:page")]');
       
   520     $this->assertTrue(!empty($comment_homepage), "RDFa markup for the homepage of anonymous user found.");
       
   521     // There should be no about attribute on anonymous comments.
       
   522     $comment_homepage = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//span[@rel="sioc:has_creator"]/a[@about]');
       
   523     $this->assertTrue(empty($comment_homepage), "No about attribute is present on anonymous user comment.");
       
   524   }
       
   525 
       
   526   /**
       
   527    * Test RDF comment replies.
       
   528    */
       
   529   public function testCommentReplyOfRdfaMarkup() {
       
   530     // Posts comment #1 as a registered user.
       
   531     $this->drupalLogin($this->web_user);
       
   532     $comments[] = $this->postComment($this->node1, $this->randomName(), $this->randomName());
       
   533 
       
   534     // Tests the reply_of relationship of a first level comment.
       
   535     $result = $this->xpath("(id('comments')//div[contains(@class,'comment ')])[position()=1]//span[@rel='sioc:reply_of' and @resource=:node]", array(':node' => url("node/{$this->node1->nid}")));
       
   536     $this->assertEqual(1, count($result), 'RDFa markup referring to the node is present.');
       
   537     $result = $this->xpath("(id('comments')//div[contains(@class,'comment ')])[position()=1]//span[@rel='sioc:reply_of' and @resource=:comment]", array(':comment' => url('comment/1#comment-1')));
       
   538     $this->assertFalse($result, 'No RDFa markup referring to the comment itself is present.');
       
   539 
       
   540     // Posts a reply to the first comment.
       
   541     $this->drupalGet('comment/reply/' . $this->node1->nid . '/' . $comments[0]->id);
       
   542     $comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
       
   543 
       
   544     // Tests the reply_of relationship of a second level comment.
       
   545     $result = $this->xpath("(id('comments')//div[contains(@class,'comment ')])[position()=2]//span[@rel='sioc:reply_of' and @resource=:node]", array(':node' => url("node/{$this->node1->nid}")));
       
   546     $this->assertEqual(1, count($result), 'RDFa markup referring to the node is present.');
       
   547     $result = $this->xpath("(id('comments')//div[contains(@class,'comment ')])[position()=2]//span[@rel='sioc:reply_of' and @resource=:comment]", array(':comment' => url('comment/1', array('fragment' => 'comment-1'))));
       
   548     $this->assertEqual(1, count($result), 'RDFa markup referring to the parent comment is present.');
       
   549     $comments = $this->xpath("(id('comments')//div[contains(@class,'comment ')])[position()=2]");
       
   550   }
       
   551 
       
   552   /**
       
   553    * Helper function for testCommentRdfaMarkup().
       
   554    *
       
   555    * Tests the current page for basic comment RDFa markup.
       
   556    *
       
   557    * @param $comment
       
   558    *   Comment object.
       
   559    * @param $account
       
   560    *   An array containing information about an anonymous user.
       
   561    */
       
   562   function _testBasicCommentRdfaMarkup($comment, $account = array()) {
       
   563     $comment_container = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]');
       
   564     $this->assertTrue(!empty($comment_container), "Comment RDF type for comment found.");
       
   565     $comment_title = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//h3[@property="dc:title"]');
       
   566     $this->assertEqual((string)$comment_title[0]->a, $comment->subject, "RDFa markup for the comment title found.");
       
   567     $comment_date = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//*[contains(@property, "dc:date") and contains(@property, "dc:created")]');
       
   568     $this->assertTrue(!empty($comment_date), "RDFa markup for the date of the comment found.");
       
   569     // The author tag can be either a or span
       
   570     $comment_author = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//span[@rel="sioc:has_creator"]/*[contains(@class, "username") and @typeof="sioc:UserAccount" and @property="foaf:name" and @datatype=""]');
       
   571     $name = empty($account["name"]) ? $this->web_user->name : $account["name"] . " (not verified)";
       
   572     $this->assertEqual((string)$comment_author[0], $name, "RDFa markup for the comment author found.");
       
   573     $comment_body = $this->xpath('//div[contains(@class, "comment") and contains(@typeof, "sioct:Comment")]//div[@class="content"]//div[contains(@class, "comment-body")]//div[@property="content:encoded"]');
       
   574     $this->assertEqual((string)$comment_body[0]->p, $comment->comment, "RDFa markup for the comment body found.");
       
   575   }
       
   576 }
       
   577 
       
   578 class RdfTrackerAttributesTestCase extends DrupalWebTestCase {
       
   579   public static function getInfo() {
       
   580     return array(
       
   581       'name' => 'RDF tracker page mapping',
       
   582       'description' => 'Test the mapping for the tracker page and ensure the proper RDFa markup in included.',
       
   583       'group' => 'RDF',
       
   584     );
       
   585   }
       
   586 
       
   587   function setUp() {
       
   588     parent::setUp('rdf', 'rdf_test', 'tracker');
       
   589     // Enable anonymous posting of content.
       
   590     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       
   591       'create article content' => TRUE,
       
   592       'access comments' => TRUE,
       
   593       'post comments' => TRUE,
       
   594       'skip comment approval' => TRUE,
       
   595     ));
       
   596   }
       
   597 
       
   598   /**
       
   599    * Create nodes as both admin and anonymous user and test for correct RDFa
       
   600    * markup on the tracker page for those nodes and their comments.
       
   601    */
       
   602   function testAttributesInTracker() {
       
   603     // Create node as anonymous user.
       
   604     $node_anon = $this->drupalCreateNode(array('type' => 'article', 'uid' => 0));
       
   605     // Create node as admin user.
       
   606     $node_admin = $this->drupalCreateNode(array('type' => 'article', 'uid' => 1));
       
   607 
       
   608     // Pass both the anonymously posted node and the administrator posted node
       
   609     // through to test for the RDF attributes.
       
   610     $this->_testBasicTrackerRdfaMarkup($node_anon);
       
   611     $this->_testBasicTrackerRdfaMarkup($node_admin);
       
   612 
       
   613   }
       
   614 
       
   615   /**
       
   616    * Helper function for testAttributesInTracker().
       
   617    *
       
   618    * Tests the tracker page for RDFa markup.
       
   619    *
       
   620    * @param $node
       
   621    * The node just created.
       
   622    */
       
   623   function _testBasicTrackerRdfaMarkup($node) {
       
   624     $url = url('node/' . $node->nid);
       
   625 
       
   626     $user = ($node->uid == 0) ? 'Anonymous user' : 'Registered user';
       
   627 
       
   628     // Navigate to tracker page.
       
   629     $this->drupalGet('tracker');
       
   630 
       
   631     // Tests whether the about property is applied. This is implicit in the
       
   632     // success of the following tests, but making it explicit will make
       
   633     // debugging easier in case of failure.
       
   634     $tracker_about = $this->xpath('//tr[@about=:url]', array(':url' => $url));
       
   635     $this->assertTrue(!empty($tracker_about), format_string('About attribute found on table row for @user content.', array('@user'=> $user)));
       
   636 
       
   637     // Tests whether the title has the correct property attribute.
       
   638     $tracker_title = $this->xpath('//tr[@about=:url]/td[@property="dc:title" and @datatype=""]', array(':url' => $url));
       
   639     $this->assertTrue(!empty($tracker_title), format_string('Title property attribute found on @user content.', array('@user'=> $user)));
       
   640 
       
   641     // Tests whether the relationship between the content and user has been set.
       
   642     $tracker_user = $this->xpath('//tr[@about=:url]//td[contains(@rel, "sioc:has_creator")]//*[contains(@typeof, "sioc:UserAccount") and contains(@property, "foaf:name")]', array(':url' => $url));
       
   643     $this->assertTrue(!empty($tracker_user), format_string('Typeof and name property attributes found on @user.', array('@user'=> $user)));
       
   644     // There should be an about attribute on logged in users and no about
       
   645     // attribute for anonymous users.
       
   646     $tracker_user = $this->xpath('//tr[@about=:url]//td[@rel="sioc:has_creator"]/*[@about]', array(':url' => $url));
       
   647     if ($node->uid == 0) {
       
   648       $this->assertTrue(empty($tracker_user), format_string('No about attribute is present on @user.', array('@user'=> $user)));
       
   649     }
       
   650     elseif ($node->uid > 0) {
       
   651       $this->assertTrue(!empty($tracker_user), format_string('About attribute is present on @user.', array('@user'=> $user)));
       
   652     }
       
   653 
       
   654     // Tests whether the property has been set for number of comments.
       
   655     $tracker_replies = $this->xpath('//tr[@about=:url]//td[contains(@property, "sioc:num_replies") and contains(@content, "0") and @datatype="xsd:integer"]', array(':url' => $url));
       
   656     $this->assertTrue($tracker_replies, format_string('Num replies property and content attributes found on @user content.', array('@user'=> $user)));
       
   657 
       
   658     // Tests that the appropriate RDFa markup to annotate the latest activity
       
   659     // date has been added to the tracker output before comments have been
       
   660     // posted, meaning the latest activity reflects changes to the node itself.
       
   661     $isoDate = date('c', $node->changed);
       
   662     $tracker_activity = $this->xpath('//tr[@about=:url]//td[contains(@property, "dc:modified") and contains(@property, "sioc:last_activity_date") and contains(@datatype, "xsd:dateTime") and @content=:date]', array(':url' => $url, ':date' => $isoDate));
       
   663     $this->assertTrue(!empty($tracker_activity), format_string('Latest activity date and changed properties found when there are no comments on @user content. Latest activity date content is correct.', array('@user'=> $user)));
       
   664 
       
   665     // Tests that the appropriate RDFa markup to annotate the latest activity
       
   666     // date has been added to the tracker output after a comment is posted.
       
   667     $comment = array(
       
   668       'subject' => $this->randomName(),
       
   669       'comment_body[' . LANGUAGE_NONE . '][0][value]' => $this->randomName(),
       
   670     );
       
   671     $this->drupalPost('comment/reply/' . $node->nid, $comment, t('Save'));
       
   672     $this->drupalGet('tracker');
       
   673 
       
   674     // Tests whether the property has been set for number of comments.
       
   675     $tracker_replies = $this->xpath('//tr[@about=:url]//td[contains(@property, "sioc:num_replies") and contains(@content, "1") and @datatype="xsd:integer"]', array(':url' => $url));
       
   676     $this->assertTrue($tracker_replies, format_string('Num replies property and content attributes found on @user content.', array('@user'=> $user)));
       
   677 
       
   678     // Need to query database directly to obtain last_activity_date because
       
   679     // it cannot be accessed via node_load().
       
   680     $result = db_query('SELECT t.changed FROM {tracker_node} t WHERE t.nid = (:nid)', array(':nid' => $node->nid));
       
   681     foreach ($result as $node) {
       
   682       $expected_last_activity_date = $node->changed;
       
   683     }
       
   684     $isoDate = date('c', $expected_last_activity_date);
       
   685     $tracker_activity = $this->xpath('//tr[@about=:url]//td[@property="sioc:last_activity_date" and @datatype="xsd:dateTime" and @content=:date]', array(':url' => $url, ':date' => $isoDate));
       
   686     $this->assertTrue(!empty($tracker_activity), format_string('Latest activity date found when there are comments on @user content. Latest activity date content is correct.', array('@user'=> $user)));
       
   687   }
       
   688 }
       
   689 
       
   690 /**
       
   691  * Tests for RDF namespaces declaration with hook_rdf_namespaces().
       
   692  */
       
   693 class RdfGetRdfNamespacesTestCase extends DrupalWebTestCase {
       
   694   public static function getInfo() {
       
   695     return array(
       
   696       'name' => 'RDF namespaces',
       
   697       'description' => 'Test hook_rdf_namespaces() and ensure only "safe" namespaces are returned.',
       
   698       'group' => 'RDF',
       
   699     );
       
   700   }
       
   701 
       
   702   function setUp() {
       
   703     parent::setUp('rdf', 'rdf_test');
       
   704   }
       
   705 
       
   706   /**
       
   707    * Test getting RDF namesapces.
       
   708    */
       
   709   function testGetRdfNamespaces() {
       
   710     // Get all RDF namespaces.
       
   711     $ns = rdf_get_namespaces();
       
   712 
       
   713     $this->assertEqual($ns['rdfs'], 'http://www.w3.org/2000/01/rdf-schema#', 'A prefix declared once is included.');
       
   714     $this->assertEqual($ns['foaf'], 'http://xmlns.com/foaf/0.1/', 'The same prefix declared in several implementations of hook_rdf_namespaces() is valid as long as all the namespaces are the same.');
       
   715     $this->assertEqual($ns['foaf1'], 'http://xmlns.com/foaf/0.1/', 'Two prefixes can be assigned the same namespace.');
       
   716     $this->assertTrue(!isset($ns['dc']), 'A prefix with conflicting namespaces is discarded.');
       
   717   }
       
   718 }