RestfulListTestCase.test in RESTful 7
Same filename and directory in other branches
Contains RestfulListTestCase
File
tests/RestfulListTestCase.testView source
<?php
/**
* @file
* Contains RestfulListTestCase
*/
class RestfulListTestCase extends RestfulCurlBaseTestCase {
public static function getInfo() {
return array(
'name' => 'List entities',
'description' => 'Test the listing of entities.',
'group' => 'RESTful',
);
}
function setUp() {
parent::setUp('restful_example', 'restful_test');
}
/**
* Test the sorting of entities.
*/
function testSort() {
$user1 = $this
->drupalCreateUser();
$user2 = $this
->drupalCreateUser();
$settings = array(
'type' => 'article',
);
$info = array(
'abc' => $user1->uid,
'xyz' => $user1->uid,
'efg' => $user2->uid,
);
foreach ($info as $title => $uid) {
$settings['title'] = $title;
$settings['uid'] = $uid;
$node = $this
->drupalCreateNode($settings);
$nodes[$title] = $node->nid;
}
// Add unpublished node, to confirm it is not listed.
$settings['status'] = NODE_NOT_PUBLISHED;
$this
->drupalCreateNode($settings);
$handler = restful_get_restful_handler('articles');
$request['fields'] = 'id,label';
// No sorting (default sorting).
$result = $handler
->get('', $request);
$expected_result = array(
array(
'id' => $nodes['abc'],
'label' => 'abc',
),
array(
'id' => $nodes['xyz'],
'label' => 'xyz',
),
array(
'id' => $nodes['efg'],
'label' => 'efg',
),
);
$this
->assertEqual($result, $expected_result, 'No sorting (default sorting).');
// Sort by ID descending.
$request['sort'] = '-id';
$result = $handler
->get('', $request);
$expected_result = array(
array(
'id' => $nodes['efg'],
'label' => 'efg',
),
array(
'id' => $nodes['xyz'],
'label' => 'xyz',
),
array(
'id' => $nodes['abc'],
'label' => 'abc',
),
);
$this
->assertEqual($result, $expected_result, 'Sort by ID descending.');
// Sort by label ascending.
$request['sort'] = 'label';
$result = $handler
->get('', $request);
$expected_result = array(
array(
'id' => $nodes['abc'],
'label' => 'abc',
),
array(
'id' => $nodes['efg'],
'label' => 'efg',
),
array(
'id' => $nodes['xyz'],
'label' => 'xyz',
),
);
$this
->assertEqual($result, $expected_result, 'Sort by label ascending.');
// Sort by label and by ID. For that we add another node titled "abc".
$settings = array(
'type' => 'article',
'title' => 'abc',
);
$node = $this
->drupalCreateNode($settings);
$request['sort'] = 'label,id';
$result = $handler
->get('', $request);
$expected_result = array(
array(
'id' => $nodes['abc'],
'label' => 'abc',
),
array(
'id' => $node->nid,
'label' => 'abc',
),
array(
'id' => $nodes['efg'],
'label' => 'efg',
),
array(
'id' => $nodes['xyz'],
'label' => 'xyz',
),
);
$this
->assertEqual($result, $expected_result, 'Sort by ID and by label.');
// Test default sorting from plugin definition; by label, then by reverse id.
$handler = restful_get_restful_handler('test_articles', 1, 1);
unset($request['sort']);
$result = $handler
->get('', $request);
$expected_result = array(
array(
'id' => $node->nid,
'label' => 'abc',
),
array(
'id' => $nodes['abc'],
'label' => 'abc',
),
array(
'id' => $nodes['efg'],
'label' => 'efg',
),
array(
'id' => $nodes['xyz'],
'label' => 'xyz',
),
);
$this
->assertEqual($result, $expected_result, 'Default sort by ID and by label.');
// Test that the default sort can be overridden.
$request['sort'] = 'id';
$result = $handler
->get('', $request);
$expected_result = array(
array(
'id' => $nodes['abc'],
'label' => 'abc',
),
array(
'id' => $nodes['xyz'],
'label' => 'xyz',
),
array(
'id' => $nodes['efg'],
'label' => 'efg',
),
array(
'id' => $node->nid,
'label' => 'abc',
),
);
$this
->assertEqual($result, $expected_result, 'Sort by ID, overriding default sort.');
// Illegal sort property.
$request['sort'] = 'wrong_key';
try {
$handler
->get('', $request);
$this
->fail('Illegal sort property used.');
} catch (RestfulBadRequestException $e) {
$this
->pass('Exception thrown on illegal sort property.');
}
// Illegal sort property, descending.
$request['sort'] = '-wrong_key';
try {
$handler
->get('', $request);
$this
->fail('Illegal sort property, descending, used.');
} catch (RestfulBadRequestException $e) {
$this
->pass('Exception thrown on illegal sort property, descending.');
}
// Test valid sort with sort params disabled.
$handler
->setPluginKey('url_params', array(
'filter' => TRUE,
'sort' => FALSE,
'range' => TRUE,
));
$request['sort'] = 'label,id';
try {
$handler
->get('', $request);
$this
->fail('Exception not raised for disabled sort parameter.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Exception raised for disabled sort parameter.');
}
// Test the range overrides.
unset($request['sort']);
$request['range'] = 2;
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), $request['range'], 'Range parameter overridden correctly');
// Test invalid range.
$request['range'] = $this
->randomName();
try {
$handler
->get('', $request);
$this
->fail('Exception not raised on invalid range parameter.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Exception raised on invalid range parameter.');
}
// Test valid range with range params disabled.
$handler
->setPluginKey('url_params', array(
'filter' => TRUE,
'sort' => TRUE,
'range' => FALSE,
));
$request['range'] = 2;
try {
$handler
->get('', $request);
$this
->fail('Exception not raised for disabled range parameter.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Exception raised for disabled range parameter.');
}
// Test the administrator's content listing.
$role_name = 'administrator';
$handler = restful_get_restful_handler_by_name('per_role_content__1_0:' . $role_name);
// Force the user 1 to be identified.
$handler
->setAccount(user_load(1));
$settings = array(
'type' => 'article',
'title' => $this
->randomName(),
'uid' => 1,
);
$this
->drupalCreateNode($settings);
$request = array(
'fields' => 'roles',
);
$response = $handler
->get('', $request);
foreach ($response as $item) {
$roles = array_map('trim', explode(',', $item['roles']));
$this
->assertTrue(in_array($role_name, $roles), format_string('%role role found in content list.', array(
'%role' => $role_name,
)));
}
// Sort by an entity metadata wrapper property that is different from the
// DB column name.
$handler = restful_get_restful_handler('articles', 1, 5);
$request = array(
'sort' => '-user',
);
$result = $handler
->get('', $request);
$this
->assertEqual($result[0]['user']['id'], 3, 'List sorted by the "author" entity metadata wrapper property, which maps to the "uid" DB column name.');
$request = array(
'sort' => 'static',
);
try {
$handler
->get('', $request);
$this
->fail('Exception not thrown for invalid sort.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Exception thrown for invalid sort.');
}
}
/**
* Test filtering.
*/
function testFilter() {
$user1 = $this
->drupalCreateUser();
$user2 = $this
->drupalCreateUser();
$this
->addIntegerFields();
$info = array(
array(
'title' => 'abc',
'integer_single' => 1,
'integer_multiple' => array(
1,
2,
3,
),
'uid' => $user1->uid,
),
array(
'title' => 'another abc',
'integer_single' => 5,
'integer_multiple' => array(
3,
4,
5,
),
'uid' => $user1->uid,
),
array(
'title' => 'last',
'integer_single' => NULL,
'integer_multiple' => array(),
'uid' => $user2->uid,
),
);
$nodes = array();
// We set the 'created' property of the node in order to test the operator
// 'BETWEEN' on a property.
$nodes_created = array(
'abc' => strtotime('june 1 1971'),
'another abc' => strtotime('june 1 1986'),
'last' => strtotime('june 1 1996'),
);
foreach ($info as $row) {
$title = $row['title'];
$settings = array(
'type' => 'article',
'title' => $title,
);
$settings['integer_single'][LANGUAGE_NONE][0]['value'] = $row['integer_single'];
foreach ($row['integer_multiple'] as $key => $value) {
$settings['integer_multiple'][LANGUAGE_NONE][$key]['value'] = $value;
}
$settings['uid'] = $row['uid'];
// Setting the 'created' time of the node.
$settings['created'] = $nodes_created[$title];
$node = $this
->drupalCreateNode($settings);
$nodes[$title] = $node->nid;
}
$handler = restful_get_restful_handler('test_articles', 1, 2);
$fields = array(
'id',
'label',
'integer_single',
'intger_multiple',
);
$request['fields'] = implode(',', $fields);
// Single value property.
$request['filter'] = array(
'label' => 'abc',
);
$result = $handler
->get('', $request);
$this
->assertEqual($result[0]['id'], $nodes['abc'], 'Filter list by single value property.');
// Assert count is correct.
$formatter_handler = restful_get_formatter_handler('hal_json', $handler);
$output = $formatter_handler
->prepare($result);
$this
->assertEqual($output['count'], 1, '"count" property is correct.');
// Single value field.
$request['filter'] = array(
'integer_single' => '1',
);
$result = $handler
->get('', $request);
$this
->assertEqual($result[0]['id'], $nodes['abc'], 'Filter list by Single value field.');
// LIKE operator.
$request['filter'] = array(
'label' => array(
'value' => '%nothe%',
'operator' => 'LIKE',
),
);
$result = $handler
->get('', $request);
$this
->assertEqual($result[0]['id'], $nodes['another abc'], 'Filter list using LIKE operator.');
// STARTS_WITH operator.
$request['filter'] = array(
'label' => array(
'value' => 'las',
'operator' => 'STARTS_WITH',
),
);
$result = $handler
->get('', $request);
$this
->assertEqual($result[0]['id'], $nodes['last'], 'Filter list using STARTS_WITH operator.');
// CONTAINS operator.
$request['filter'] = array(
'label' => array(
'value' => 'bc',
'operator' => 'CONTAINS',
),
);
$result = $handler
->get('', $request);
// Sort the results before checking it.
usort($result, function ($a, $b) {
return strcmp($a['label'], $b['label']);
});
$this
->assertEqual($result[0]['id'], $nodes['abc'], 'Filter list using CONTAINS operator.');
$this
->assertEqual($result[1]['id'], $nodes['another abc'], 'Filter list using CONTAINS operator.');
// Multiple value field.
$request['filter'] = array(
'integer_multiple' => array(
'value' => array(
4,
5,
),
'operator' => 'BETWEEN',
),
);
$result = $handler
->get('', $request);
$this
->assertEqual($result[0]['id'], $nodes['another abc'], 'Filter list by multiple value field.');
// Invalid key.
$request['filter'] = array(
'invalid_key' => '3',
);
try {
$handler
->get('', $request);
$this
->fail('No exception was thrown on invalid key for filter.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Correct exception was thrown on invalid key for filter.');
} catch (\Exception $e) {
$this
->fail('Incorrect exception was thrown on invalid key for filter.');
}
// Assert filtering doesn't apply for non-list request
// (e.g. /api/v1.0/articles/1?filter[label]=foo), as this might be called from
// a formatter plugin, after RESTful's error handling has finished.
$query = array(
'filter' => array(
'invalid-key' => 'foo',
),
);
$result = $this
->httpRequest('api/v1.0/articles/1', \RestfulInterface::GET, $query);
$this
->assertEqual($result['code'], '200', 'Invalid filter key was ignored on non-list query.');
// Test the 'BETWEEN' operator on the 'created' property.
$request = array(
'filter' => array(
'created' => array(
'value' => array(
0,
$nodes_created['abc'],
),
'operator' => 'BETWEEN',
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 1);
$request['filter']['created']['value'] = array(
$nodes_created['abc'],
$nodes_created['last'] - 1,
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 2);
$request['filter']['created']['value'] = array(
$nodes_created['abc'],
);
try {
$handler
->get('', $request);
$this
->fail('Exception not raised when using one value on operator BETWEEN (on a property).');
} catch (\PDOException $e) {
$this
->pass('Exception raised when using one value on operator BETWEEN (on a property).');
}
// Test multiple filters on the same field.
$request = array(
'filter' => array(
'integer_single' => array(
'value' => array(
1,
4,
),
'operator' => array(
'>',
'<>',
),
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual($nodes['another abc'], $result[0]['id']);
$request = array(
'filter' => array(
'integer_single' => array(
'value' => array(
1,
5,
),
'operator' => array(
'>',
'<>',
),
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual($result, array());
$request = array(
'filter' => array(
'integer_multiple' => array(
'value' => array(
3,
4,
),
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual($nodes['another abc'], $result[0]['id']);
// Test valid filter with filter params disabled.
$handler
->setPluginKey('url_params', array(
'filter' => FALSE,
'sort' => TRUE,
'range' => TRUE,
));
$request['filter'] = array(
'label' => 'abc',
);
try {
$handler
->get('', $request);
$this
->fail('Exception not raised for disabled filter parameter.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Exception raised for disabled filter parameter.');
}
// Filter by an entity metadata wrapper property that is different from the
// DB column name.
$handler = restful_get_restful_handler('articles', 1, 5);
$request = array(
'filter' => array(
'user' => array(
'value' => $user1->uid,
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 2, 'List filtered by the "author" entity metadata wrapper property, which maps to the "uid" DB column name.');
// Filter by an entity metadata wrapper property that is different from the
// DB column name using the 'IN' operator.
$request = array(
'filter' => array(
'user' => array(
'value' => array(
$user1->uid,
$user2->uid,
),
'operator' => 'IN',
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 3, 'List filtered by the "author" entity metadata wrapper property, which maps to the "uid" DB column name, using the "IN" operator.');
// Filter by an entity metadata wrapper property that is different from the
// DB column name using the 'NOT IN' operator.
$request = array(
'filter' => array(
'user' => array(
'value' => array(
$user1->uid,
$user2->uid,
),
'operator' => 'NOT IN',
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 0, 'List filtered by the "author" entity metadata wrapper property, which maps to the "uid" DB column name, using the "NOT IN" operator.');
// Filter by an entity metadata wrapper property that is different from the
// DB column name using the 'NOT IN' operator.
$request = array(
'filter' => array(
'user' => array(
'value' => array(
$user2->uid,
),
'operator' => 'NOT IN',
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 2, 'List filtered by the "author" entity metadata wrapper property, which maps to the "uid" DB column name, using the "NOT IN" operator.');
// Filter by an entity metadata wrapper property that is different from the
// DB column name using the 'NOT IN' operator.
$request = array(
'filter' => array(
'user' => array(
'value' => array(),
'operator' => 'NOT IN',
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 3, 'List filtered by the "author" entity metadata wrapper property, which maps to the "uid" DB column name, using the "NOT IN" operator.');
// Filter by an entity metadata wrapper property that is different from the
// DB column name using the 'IN' operator.
$request = array(
'filter' => array(
'user' => array(
'value' => array(),
'operator' => 'IN',
),
),
);
$result = $handler
->get('', $request);
$this
->assertEqual(count($result), 0, 'List filtered by the "author" entity metadata wrapper property, which maps to the "uid" DB column name, using the "IN" operator.');
$request = array(
'filter' => array(
'static' => array(
'value' => 0,
),
),
);
try {
$handler
->get('', $request);
$this
->fail('Exception not thrown for invalid filter.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Exception thrown for invalid filter.');
}
}
/**
* Test pagination.
*/
function testPagination() {
foreach (range(1, 9) as $key) {
$settings = array(
'type' => 'article',
'title' => $key,
);
$this
->drupalCreateNode($settings);
}
$handler = restful_get_restful_handler('articles');
// Set a smaller range for the pagination.
$handler
->setRange(3);
// Check pagination of first page.
$result = $handler
->get('', array(
'page' => 1,
));
$output = drupal_json_decode($handler
->format($result));
$this
->assertEqual(count($result), 3);
$this
->assertTrue($output['next'], '"Next" link exists on the first page.');
$this
->assertTrue(empty($output['previous']), '"Previous" link does not exist on the first page.');
// Check pagination of middle pages
$result = $handler
->get('', array(
'page' => 2,
));
$output = drupal_json_decode($handler
->format($result));
$this
->assertTrue($output['next'], '"Next" link exists on the middle page.');
$this
->assertEqual($output['next']['href'], $handler
->versionedUrl('', array(
'query' => array(
'page' => 3,
),
)));
$this
->assertTrue($output['previous'], '"Previous" link exists on the middle page.');
$this
->assertEqual($output['previous']['href'], $handler
->versionedUrl('', array(
'query' => array(
'page' => 1,
),
)));
// Check pagination of last page.
$result = $handler
->get('', array(
'page' => 3,
));
$output = drupal_json_decode($handler
->format($result));
$this
->assertTrue(empty($output['next']), '"Next" link does not exist on the last page.');
$this
->assertTrue($output['previous'], '"Previous" link exists on the last page.');
// Check other query strings are retained in the _links.
$result = $handler
->get('', array(
'page' => 3,
'sort' => '-id',
));
$output = drupal_json_decode($handler
->format($result));
$this
->assertTrue(strpos($output['previous']['href'], 'sort=-id'), 'Query strings are retained in the _links.');
// Check pagination with non-numeric value.
try {
$handler
->get('', array(
'page' => 'string',
));
$this
->fail('No exception thrown for pagination with non-numeric value.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Correct exception thrown for pagination with non-numeric value.');
} catch (\Exception $e) {
$this
->fail('Incorrect exception thrown for pagination with non-numeric value.');
}
// Check pagination with 0 value.
try {
$handler
->get('', array(
'page' => 0,
));
$this
->fail('No exception thrown for pagination with 0 value.');
} catch (\RestfulBadRequestException $e) {
$this
->pass('Correct exception thrown for pagination with 0 value.');
} catch (\Exception $e) {
$this
->fail('Incorrect exception thrown for pagination with 0 value.');
}
// Check pagination with high number, where there are not items, yielded no
// results, but is a valid call.
$result = $handler
->get('', array(
'page' => 100,
));
$this
->assertEqual($result, array(), 'pagination with high number, where there are not items yielded no results.');
// Check total number of results.
$result = $handler
->get('', array(
'page' => 3,
));
$output = drupal_json_decode($handler
->format($result));
$this
->assertEqual($output['count'], 9, 'Total count exists and is correct.');
}
/**
* Test node count and pager when there are unpublished nodes.
*/
function testCountWithUnpublished() {
foreach (range(1, 9) as $key) {
$settings = array(
'type' => 'article',
'title' => $key,
'status' => NODE_PUBLISHED,
);
$this
->drupalCreateNode($settings);
}
foreach (range(1, 3) as $key) {
$settings = array(
'type' => 'article',
'title' => $key,
'status' => NODE_NOT_PUBLISHED,
);
$this
->drupalCreateNode($settings);
}
/** @var RestfulInterface $handler */
$handler = restful_get_restful_handler('articles');
// Set a range for pagination to check only .
$handler
->setRange(9);
// Check pagination of first page.
$result = $handler
->get('', array(
'page' => 1,
));
$output = drupal_json_decode($handler
->format($result));
$this
->assertEqual(count($result), 9, 'Number of results displayed');
$this
->assertEqual(count($result), $handler
->getTotalCount(), 'Count of results takes into account unpublished nodes');
$this
->assertTrue(empty($output['next']), '"Next" link does not exist on the first page.');
$this
->assertTrue(empty($output['previous']), '"Previous" link does not exist on the first page.');
}
/**
* Helper function; Add single and multiple integer fields.
*/
private function addIntegerFields() {
// Integer - single.
$field = array(
'field_name' => 'integer_single',
'type' => 'number_integer',
'entity_types' => array(
'node',
),
'cardinality' => 1,
);
field_create_field($field);
$instance = array(
'field_name' => 'integer_single',
'bundle' => 'article',
'entity_type' => 'node',
'label' => t('Integer single'),
);
field_create_instance($instance);
// Integer - multiple.
$field = array(
'field_name' => 'integer_multiple',
'type' => 'number_integer',
'entity_types' => array(
'node',
),
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
);
field_create_field($field);
$instance = array(
'field_name' => 'integer_multiple',
'bundle' => 'article',
'entity_type' => 'node',
'label' => t('Integer multiple'),
);
field_create_instance($instance);
}
/**
* Test error handeling when no access is granted to an entity in a list.
*/
function testAccessHandeling() {
$settings = array(
'type' => 'article',
);
$node1 = $this
->drupalCreateNode($settings);
$node2 = $this
->drupalCreateNode($settings);
$node3 = $this
->drupalCreateNode($settings);
$user1 = $this
->drupalCreateUser();
// Deny access via hook_node_access() to a specific node.
restful_test_deny_access_node($node2->nid);
$handler = restful_get_restful_handler('articles');
$handler
->setAccount($user1);
$result = $handler
->get();
$this
->assertEqual(count($result), 2, 'List returned and ignored un-accessible entity.');
// Get a list with specific IDs.
$ids = array(
$node1->nid,
$node2->nid,
$node3->nid,
);
try {
$handler
->get(implode(',', $ids));
$this
->fail('Exception was not thrown for un-accessible node for specific IDs list.');
} catch (\RestfulForbiddenException $e) {
$this
->pass('Exception was thrown for un-accessible node for specific IDs list.');
} catch (\Exception $e) {
$this
->fail('Exception of wrong type was thrown for un-accessible node for specific IDs list.');
}
}
}
Classes
Name | Description |
---|---|
RestfulListTestCase | @file Contains RestfulListTestCase |