You are here

relation.test in Relation 7

Tests for Relation module.

File

tests/relation.test
View source
<?php

/**
 * @file
 * Tests for Relation module.
 */

/**
 * Relation helper class.
 */
class RelationTestCase extends DrupalWebTestCase {
  protected $sleep = FALSE;
  function setUp() {

    // Other modules will reuse this class, make sure to pass the arguments up.
    if (func_num_args()) {
      parent::setUp(func_get_args());
    }
    else {
      parent::setUp('relation');
    }

    // Defines users and permissions.
    $permissions = array(
      'create article content',
      'create page content',
      'administer relation types',
      'administer relations',
      'administer fields',
      'use relation import',
      'access relations',
      'create relations',
      'edit relations',
      'delete relations',
    );
    $this->web_user = $this
      ->drupalCreateUser($permissions);
    $this
      ->drupalLogin($this->web_user);

    // Defines entities.
    $this
      ->createRelationNodes();
    $this
      ->createRelationUsers();

    // Defines relation types.
    $this
      ->createRelationTypes();

    // Defines end points.
    $this
      ->createRelationEndPoints();

    // Defines relations.
    $this
      ->createRelationSymmetric();
    $this
      ->createRelationDirectional();
    $this
      ->createRelationOctopus();
    $this
      ->createRelationUnary();
  }

  /**
   * Creates nodes.
   */
  function createRelationNodes() {
    $this->node1 = $this
      ->drupalCreateNode(array(
      'type' => 'article',
      'promote' => 1,
      'title' => 'Grandparent',
    ));
    $this->node2 = $this
      ->drupalCreateNode(array(
      'type' => 'article',
      'promote' => 0,
    ));
    $this->node3 = $this
      ->drupalCreateNode(array(
      'type' => 'page',
      'promote' => 1,
      'title' => 'Parent',
    ));
    $this->node4 = $this
      ->drupalCreateNode(array(
      'type' => 'page',
      'promote' => 0,
      'title' => 'Child',
    ));
    $this->node5 = $this
      ->drupalCreateNode(array(
      'type' => 'page',
      'promote' => 0,
    ));
    $this->node6 = $this
      ->drupalCreateNode(array(
      'type' => 'page',
      'promote' => 0,
      'title' => 'Unrelated',
    ));
  }
  function createRelationUsers() {
    $this->user1 = $this
      ->drupalCreateUser();
  }

  /**
   * Creates end points.
   */
  function createRelationEndPoints() {
    $this->endpoints = array(
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node1->nid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node4->nid,
      ),
    );
    $this->endpoints_4 = array(
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node1->nid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node2->nid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node3->nid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node4->nid,
      ),
    );
    $this->endpoints_entitysame = array(
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node3->nid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node4->nid,
      ),
    );
    $this->endpoints_entitydifferent = array(
      array(
        'entity_type' => 'user',
        'entity_id' => $this->user1->uid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node3->nid,
      ),
    );
    $this->endpoints_unary = array(
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node5->nid,
      ),
    );
  }

  /**
   * Creates a set of standard relation types.
   */
  function createRelationTypes() {
    $this->relation_types['symmetric'] = array(
      'relation_type' => 'symmetric',
      'label' => 'symmetric',
      'source_bundles' => array(
        'node:article',
        'node:page',
        'taxonomy_term:*',
        'user:*',
      ),
    );
    $this->relation_types['directional'] = array(
      'relation_type' => 'directional',
      'label' => 'directional',
      'directional' => TRUE,
      'source_bundles' => array(
        'node:*',
      ),
      'target_bundles' => array(
        'node:page',
      ),
    );
    $this->relation_types['directional_entitysame'] = array(
      'relation_type' => 'directional_entitysame',
      'label' => 'directional_entitysame',
      'directional' => TRUE,
      'source_bundles' => array(
        'node:page',
      ),
      'target_bundles' => array(
        'node:page',
      ),
    );
    $this->relation_types['directional_entitydifferent'] = array(
      'relation_type' => 'directional_entitydifferent',
      'label' => 'directional_entitydifferent',
      'directional' => TRUE,
      'source_bundles' => array(
        'user:*',
      ),
      'target_bundles' => array(
        'node:page',
      ),
    );
    $this->relation_types['octopus'] = array(
      'relation_type' => 'octopus',
      'label' => 'octopus',
      'min_arity' => 3,
      'max_arity' => 5,
      'source_bundles' => array(
        'node:article',
        'node:page',
      ),
    );
    $this->relation_types['unary'] = array(
      'relation_type' => 'unary',
      'label' => 'unary',
      'min_arity' => 1,
      'max_arity' => 1,
      'source_bundles' => array(
        'node:page',
      ),
    );
    foreach ($this->relation_types as $relation_type) {
      relation_type_save($relation_type);
    }
  }

  /**
   * Creates a Symmetric relation.
   */
  function createRelationSymmetric() {

    // Article 1 <--> Page 4
    $this->relation_type_symmetric = $this->relation_types['symmetric']['relation_type'];
    $this->rid_symmetric = $this
      ->saveRelation($this->relation_type_symmetric, $this->endpoints);
  }

  /**
   * Creates a Directional relation.
   */
  function createRelationDirectional() {

    // Article 1 --> Page 3
    $this->endpoints[1]['entity_id'] = $this->node3->nid;
    $this->endpoints[1]['r_index'] = 1;
    $this->relation_type_directional = $this->relation_types['directional']['relation_type'];
    $this->rid_directional = $this
      ->saveRelation($this->relation_type_directional, $this->endpoints);

    // Page 3 --> Page 4
    $this->endpoints[0]['entity_id'] = $this->node3->nid;
    $this->endpoints[1]['entity_id'] = $this->node4->nid;
    $this
      ->saveRelation($this->relation_type_directional, $this->endpoints);

    // Page 3 --> Page 4
    $this->endpoints_entitysame[1]['r_index'] = 1;
    $this->relation_type_directional_entitysame = $this->relation_types['directional_entitysame']['relation_type'];
    $this
      ->saveRelation($this->relation_type_directional_entitysame, $this->endpoints_entitysame);

    // Page 3 --> Page 5
    $this->endpoints_entitysame[1]['entity_id'] = $this->node5->nid;
    $this
      ->saveRelation($this->relation_type_directional_entitysame, $this->endpoints_entitysame);

    // Page 4 --> Page 3
    $this->endpoints_entitysame[0]['entity_id'] = $this->node4->nid;
    $this->endpoints_entitysame[1]['entity_id'] = $this->node3->nid;
    $this
      ->saveRelation($this->relation_type_directional_entitysame, $this->endpoints_entitysame);

    // User 1 --> Page 3
    $this->endpoints_entitydifferent[1]['r_index'] = 1;
    $this->relation_type_directional_entitydifferent = $this->relation_types['directional_entitydifferent']['relation_type'];
    $this
      ->saveRelation($this->relation_type_directional_entitydifferent, $this->endpoints_entitydifferent);

    // User 1 --> Page 4
    $this->endpoints_entitydifferent[1]['entity_id'] = $this->node4->nid;
    $this
      ->saveRelation($this->relation_type_directional_entitydifferent, $this->endpoints_entitydifferent);
  }

  /**
   * Creates an Octopus (4-ary) relation.
   */
  function createRelationOctopus() {

    // Nodes 1, 2, 3, 4 are related.
    $this->relation_type_octopus = $this->relation_types['octopus']['relation_type'];
    $this->rid_octopus = $this
      ->saveRelation($this->relation_type_octopus, $this->endpoints_4);
  }

  /**
   * Creates an Unary relation.
   */
  function createRelationUnary() {

    // Page 5 <--> Page 5
    $this->relation_type_unary = $this->relation_types['unary']['relation_type'];
    $this->rid_unary = $this
      ->saveRelation($this->relation_type_unary, $this->endpoints_unary);
  }

  /**
   * Saves a relation.
   */
  function saveRelation($relation_type, $endpoints) {
    $relation = relation_create($relation_type, $endpoints);
    $rid = relation_save($relation);
    if ($this->sleep) {
      sleep(1);
    }
    return $rid;
  }

}

/**
 * Tests Relation API.
 *
 * Create nodes, add relations and verify that they are related.
 * This test suite also checks all methods available in RelationQuery.
 */
class RelationAPITestCase extends RelationTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Relation test',
      'description' => 'Tests Relation API.',
      'group' => 'Relation',
    );
  }
  function setUp() {

    // This is necessary for the ->propertyOrderBy('created', 'DESC') test.
    $this->sleep = TRUE;
    parent::setUp();
  }

  /**
   * Tests all available methods in RelationQuery.
   * Creates some nodes, add some relations and checks if they are related.
   */
  function testRelationQuery() {
    $relations = entity_load('relation', array_keys(relation_query('node', $this->node1->nid)
      ->execute()));

    // Check that symmetric relation is correctly related to node 4.
    $this
      ->assertEqual($relations[$this->rid_symmetric]->endpoints[LANGUAGE_NONE][1]['entity_id'], $this->node4->nid, 'Correct entity is related: ' . $relations[$this->rid_symmetric]->endpoints[LANGUAGE_NONE][1]['entity_id'] . '==' . $this->node4->nid);

    // Symmetric relation is Article 1 <--> Page 4
    $entity_keys = array(
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node4->nid,
      ),
      array(
        'entity_type' => 'node',
        'entity_id' => $this->node4->nid,
      ),
    );
    $this
      ->assertFalse(relation_relation_exists($entity_keys, 'symmetric'), 'node4 is not related to node4.');

    // Get relations for node 1, should return 3 relations.
    $count = count($relations);
    $this
      ->assertEqual($count, 3);

    // Get number of relations for node 4, should return 6 relations.
    $count = relation_query('node', $this->node4->nid)
      ->count()
      ->execute();
    $this
      ->assertEqual($count, 6);

    // Get number of relations for node 5, should return 2 relations.
    $count = relation_query('node', $this->node5->nid)
      ->count()
      ->execute();
    $this
      ->assertEqual($count, 2);

    // Get relations between entities 2 and 5 (none).
    $count = relation_query('node', $this->node2->nid)
      ->related('node', $this->node5->nid)
      ->count()
      ->execute();
    $this
      ->assertFalse($count);

    // Get directed relations for node 3 using index, should return 2 relations.
    // The other node 3 relation has an r_index 0.
    $relations = relation_query('node', $this->node3->nid, 1)
      ->execute();
    $this
      ->assertEqual(count($relations), 3);
    $this
      ->assertTrue(isset($relations[$this->rid_directional]), 'Got the correct directional relation for nid=3.');

    // Get relations between entities 2 and 3 (octopus).
    $relations = relation_query('node', $this->node2->nid)
      ->related('node', $this->node3->nid)
      ->execute();
    $count = count($relations);
    $this
      ->assertEqual($count, 1);

    // Check that we have the correct relations
    $this
      ->assertEqual(isset($relations[$this->rid_octopus]), 'Got one correct relation.');

    // Get relations for node 1 (symmetric, directional, octopus), limit to
    // directional and octopus with relation_type().
    $relations = relation_query('node', $this->node1->nid)
      ->propertyCondition('relation_type', array(
      $this->relation_types['directional']['relation_type'],
      $this->relation_types['octopus']['relation_type'],
    ))
      ->execute();
    $count = count($relations);
    $this
      ->assertEqual($count, 2);

    // Check that we have the correct relations.
    $this
      ->assertTrue(isset($relations[$this->rid_directional]), 'Got one correct relation.');
    $this
      ->assertTrue(isset($relations[$this->rid_octopus]), 'Got a second one.');

    // Get last two relations for node 1.
    $relations = relation_query('node', $this->node1->nid)
      ->range(1, 2)
      ->propertyOrderBy('rid', 'ASC')
      ->execute();
    $count = count($relations);
    $this
      ->assertEqual($count, 2);

    // Check that we have the correct relations.
    $this
      ->assertTrue(isset($relations[$this->rid_directional]), 'Got one correct relation.');
    $this
      ->assertTrue(isset($relations[$this->rid_octopus]), 'Got a second one.');

    // Get all relations on node 1 and sort them in reverse created order.
    $relations = relation_query('node', $this->node1->nid)
      ->propertyOrderBy('created', 'DESC')
      ->execute();
    $this
      ->assertEqual(array_keys($relations), array(
      $this->rid_octopus,
      $this->rid_directional,
      $this->rid_symmetric,
    ));

    // Create 10 more symmetric relations and verify that the count works with
    // double digit counts as well.
    for ($i = 0; $i < 10; $i++) {
      $this
        ->createRelationSymmetric();
    }
    $count = relation_query('node', $this->node4->nid)
      ->count()
      ->execute();
    $this
      ->assertEqual($count, 16);
  }

  /**
   * Tests relation types.
   */
  function testRelationTypes() {

    // Symmetric.
    $related = relation_get_related_entity('node', $this->node1->nid);
    $this
      ->assertEqual($this->node4->nid, $related->nid);

    // Confirm this works once the related entity has been cached.
    $related = relation_get_related_entity('node', $this->node1->nid);
    $this
      ->assertEqual($this->node4->nid, $related->nid);

    // Directional.
    // From Parent to Grandparent.
    $related = relation_get_related_entity('node', $this->node3->nid, $this->relation_types['directional']['relation_type'], 1);
    $this
      ->assertEqual($this->node1->nid, $related->nid);

    // From Parent to Child.
    $related = relation_get_related_entity('node', $this->node3->nid, $this->relation_types['directional']['relation_type'], 0);
    $this
      ->assertEqual($this->node4->nid, $related->nid);

    // Delete all relations related to node 4, then confirm that these can
    // no longer be found as related entities.
    $relations = relation_query('node', $this->node4->nid)
      ->execute();
    foreach ($relations as $relation) {
      relation_delete($relation->rid);
    }
    $this
      ->assertFalse(relation_get_related_entity('node', $this->node4->nid), 'The entity was not loaded after the relation was deleted.');
  }

  /**
   * Tests saving of relations.
   */
  function testRelationSave() {
    foreach ($this->relation_types as $value) {
      $relation_type = $value['relation_type'];
      $endpoints = $this->endpoints;
      if (isset($value['min_arity'])) {
        $endpoints = $value['min_arity'] == 1 ? $this->endpoints_unary : $this->endpoints_4;
      }
      if ($relation_type == 'directional_entitydifferent') {
        $endpoints = $this->endpoints_entitydifferent;
      }
      $relation = relation_create($relation_type, $endpoints);
      $rid = relation_save($relation);
      $this
        ->assertTrue($rid, 'Relation created.');
      $count = count($relation->endpoints[LANGUAGE_NONE]);
      $this
        ->assertEqual($count, count($endpoints));
      $this
        ->assertEqual($relation->arity, count($endpoints));
      $this
        ->assertEqual($relation->relation_type, $relation_type);
      foreach ($relation->endpoints[LANGUAGE_NONE] as $endpoint) {
        $need_ids[$endpoint['entity_id']] = TRUE;
      }
      foreach ($relation->endpoints[LANGUAGE_NONE] as $delta => $endpoint) {
        $this
          ->assertEqual($endpoint['entity_type'], $endpoints[$delta]['entity_type'], 'The entity type is ' . $endpoints[$delta]['entity_type'] . ': ' . $endpoint['entity_type']);
        $this
          ->assertTrue(isset($need_ids[$endpoint['entity_id']]), 'The entity ID is correct: ' . $need_ids[$endpoint['entity_id']]);
        unset($need_ids[$endpoint['entity_id']]);
      }
      $this
        ->assertFalse($need_ids, 'All ids found.');

      // Confirm the rid in revision table.
      $revision = db_select('relation_revision', 'v')
        ->fields('v', array(
        'rid',
      ))
        ->condition('vid', $relation->vid)
        ->execute()
        ->fetchAllAssoc('rid');
      $this
        ->assertTrue(array_key_exists($rid, $revision), 'Relation revision created.');

      // Confirm ability to save relation multiple times in code without reload.
      $rid = $relation->rid;
      $vid = $relation->vid;
      relation_save($relation);
      $this
        ->assertEqual($relation->rid, $rid, 'Each revision has the same rid.');
      $this
        ->assertNotIdentical($relation->vid, $vid, 'Each revision has a different vid.');
    }
  }

  /**
   * Tests relation delete.
   */
  function testRelationDelete() {

    // Invalid relations are deleted when any endpoint entity is deleted.
    // Octopus relation is valid with 3 endpoints, currently it has 4.
    node_delete($this->node1->nid);
    $this
      ->assertTrue(relation_load($this->rid_octopus, NULL, TRUE), 'Relation is not deleted.');
    node_delete($this->node2->nid);
    $this
      ->assertFalse(relation_load($this->rid_octopus, NULL, TRUE), 'Relation is deleted.');
  }

  /**
   * Tests relation revisions.
   */
  function testRelationRevision() {
    $first_user = $this
      ->drupalCreateUser(array(
      'edit relations',
    ));
    $second_user = $this
      ->drupalCreateUser(array(
      'edit relations',
    ));
    $this
      ->drupalLogin($first_user);
    $relation = relation_create($this->relation_type_octopus, $this->endpoints_4, $first_user);
    $rid = relation_save($relation, $first_user);
    $this
      ->assertEqual($relation->uid, $first_user->uid);
    $vid = $relation->vid;

    // Relation should still be owned by the first user
    $this
      ->drupalLogin($second_user);
    $relation = relation_load($rid);
    relation_save($relation, $second_user);
    $this
      ->assertEqual($relation->uid, $first_user->uid);

    // Relation revision authors should not be identical though.
    $first_revision = relation_load($rid, $vid);
    $second_revision = relation_load($rid, $relation->vid);
    $this
      ->assertNotIdentical($first_revision->revision_uid, $second_revision->revision_uid, 'Each revision has a distinct user.');
  }

}

Classes

Namesort descending Description
RelationAPITestCase Tests Relation API.
RelationTestCase Relation helper class.