Exemplo n.º 1
0
 public function testAddUserSettingMultiple()
 {
     $settingKey = "tagColors";
     $value = array(array("name" => "_READ", "color" => "#990000"));
     // TODO: multiple, once more settings are supported
     $libraryVersion = API::getLibraryVersion();
     $json = array($settingKey => array("value" => $value));
     $response = API::userPost(self::$config['userID'], "settings?key=" . self::$config['apiKey'], json_encode($json), array("Content-Type: application/json"));
     $this->assert204($response);
     // Multi-object GET
     $response = API::userGet(self::$config['userID'], "settings?key=" . self::$config['apiKey']);
     $this->assert200($response);
     $this->assertContentType("application/json", $response);
     $json = json_decode($response->getBody(), true);
     $this->assertNotNull($json);
     $this->assertArrayHasKey($settingKey, $json);
     $this->assertEquals($value, $json[$settingKey]['value']);
     $this->assertEquals($libraryVersion + 1, $json[$settingKey]['version']);
     // Single-object GET
     $response = API::userGet(self::$config['userID'], "settings/{$settingKey}?key=" . self::$config['apiKey']);
     $this->assert200($response);
     $this->assertContentType("application/json", $response);
     $json = json_decode($response->getBody(), true);
     $this->assertNotNull($json);
     $this->assertEquals($value, $json['value']);
     $this->assertEquals($libraryVersion + 1, $json['version']);
 }
Exemplo n.º 2
0
 public function testZoteroWriteToken()
 {
     $json = API::getItemTemplate("book");
     $token = md5(uniqid());
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(array("items" => array($json))), array("Content-Type: application/json", "Zotero-Write-Token: {$token}"));
     $this->assert200ForObject($response);
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(array("items" => array($json))), array("Content-Type: application/json", "Zotero-Write-Token: {$token}"));
     $this->assert412($response);
 }
Exemplo n.º 3
0
 public function testNewSingleCollectionWithoutParentProperty()
 {
     $name = "Test Collection";
     $json = array('name' => $name);
     $response = API::userPost(self::$config['userID'], "collections?key=" . self::$config['apiKey'], json_encode($json), array("Content-Type: application/json"));
     $this->assert200($response);
     $xml = API::getXMLFromResponse($response);
     $this->assertEquals(1, (int) array_shift($xml->xpath('/atom:feed/zapi:totalResults')));
     $data = API::parseDataFromAtomEntry($xml);
     $json = json_decode($data['content']);
     $this->assertEquals($name, (string) $json->name);
 }
Exemplo n.º 4
0
 public function testCreateItemWithChildren()
 {
     $json = API::getItemTemplate("newspaperArticle");
     $noteJSON = API::getItemTemplate("note");
     $noteJSON->note = "<p>Here's a test note</p>";
     $json->notes = array($noteJSON);
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(array("items" => array($json))));
     $this->assert201($response);
     $xml = API::getXMLFromResponse($response);
     $this->assertNumResults(1, $response);
     $this->assertEquals(1, (int) array_shift($xml->xpath('//atom:entry/zapi:numChildren')));
 }
Exemplo n.º 5
0
 public function testWebTranslationMultiple()
 {
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(["url" => "http://www.amazon.com/s/field-keywords=zotero+guide+librarians"]), array("Content-Type: application/json"));
     $this->assert300($response);
     $json = json_decode($response->getBody());
     $results = get_object_vars($json);
     $key = array_keys($results)[0];
     $val = array_values($results)[0];
     $this->assertEquals(0, strpos($key, 'http'));
     $this->assertEquals('Zotero: A Guide for Librarians, Researchers and Educators', $val);
     // Can't test posting on v1, because generated token isn't returned
 }
Exemplo n.º 6
0
 public function testKeyNoteAccess()
 {
     API::userClear(self::$config['userID']);
     API::setKeyOption(self::$config['userID'], self::$config['apiKey'], 'libraryNotes', 1);
     $keys = array();
     $topLevelKeys = array();
     $bookKeys = array();
     $xml = API::createItem('book', array("title" => "A"), $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     $topKeys[] = $data['key'];
     $bookKeys[] = $data['key'];
     $xml = API::createNoteItem("B", false, $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     $topKeys[] = $data['key'];
     $xml = API::createNoteItem("C", false, $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     $topKeys[] = $data['key'];
     $xml = API::createNoteItem("D", false, $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     $topKeys[] = $data['key'];
     $xml = API::createNoteItem("E", false, $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     $topKeys[] = $data['key'];
     $xml = API::createItem('book', array("title" => "F"), $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     $topKeys[] = $data['key'];
     $bookKeys[] = $data['key'];
     $xml = API::createNoteItem("G", $data['key'], $this);
     $data = API::parseDataFromAtomEntry($xml);
     $keys[] = $data['key'];
     // Create collection and add items to it
     $response = API::userPost(self::$config['userID'], "collections?key=" . self::$config['apiKey'], json_encode(array("collections" => array(array("name" => "Test", "parentCollection" => false)))), array("Content-Type: application/json"));
     $this->assert200ForObject($response);
     $collectionKey = API::getFirstSuccessKeyFromResponse($response);
     $response = API::userPost(self::$config['userID'], "collections/{$collectionKey}/items?key=" . self::$config['apiKey'], implode(" ", $topKeys));
     $this->assert204($response);
     //
     // format=atom
     //
     // Root
     $response = API::userGet(self::$config['userID'], "items?key=" . self::$config['apiKey']);
     $this->assertNumResults(sizeOf($keys), $response);
     $this->assertTotalResults(sizeOf($keys), $response);
     // Top
     $response = API::userGet(self::$config['userID'], "items/top?key=" . self::$config['apiKey']);
     $this->assertNumResults(sizeOf($topKeys), $response);
     $this->assertTotalResults(sizeOf($topKeys), $response);
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items/top?key=" . self::$config['apiKey']);
     $this->assertNumResults(sizeOf($topKeys), $response);
     $this->assertTotalResults(sizeOf($topKeys), $response);
     //
     // format=keys
     //
     // Root
     $response = API::userGet(self::$config['userID'], "items?key=" . self::$config['apiKey'] . "&format=keys");
     $this->assert200($response);
     $this->assertCount(sizeOf($keys), explode("\n", trim($response->getBody())));
     // Top
     $response = API::userGet(self::$config['userID'], "items/top?key=" . self::$config['apiKey'] . "&format=keys");
     $this->assert200($response);
     $this->assertCount(sizeOf($topKeys), explode("\n", trim($response->getBody())));
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items/top?key=" . self::$config['apiKey'] . "&format=keys");
     $this->assert200($response);
     $this->assertCount(sizeOf($topKeys), explode("\n", trim($response->getBody())));
     // Remove notes privilege from key
     API::setKeyOption(self::$config['userID'], self::$config['apiKey'], 'libraryNotes', 0);
     //
     // format=atom
     //
     // totalResults with limit
     $response = API::userGet(self::$config['userID'], "items?key=" . self::$config['apiKey'] . "&limit=1");
     $this->assertNumResults(1, $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // And without limit
     $response = API::userGet(self::$config['userID'], "items?key=" . self::$config['apiKey']);
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // Top
     $response = API::userGet(self::$config['userID'], "items/top?key=" . self::$config['apiKey']);
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     // Collection
     $response = API::userGet(self::$config['userID'], "collections/{$collectionKey}/items?key=" . self::$config['apiKey']);
     $this->assertNumResults(sizeOf($bookKeys), $response);
     $this->assertTotalResults(sizeOf($bookKeys), $response);
     //
     // format=keys
     //
     $response = API::userGet(self::$config['userID'], "items?key=" . self::$config['apiKey'] . "&format=keys");
     $keys = explode("\n", trim($response->getBody()));
     sort($keys);
     $this->assertEmpty(array_merge(array_diff($bookKeys, $keys), array_diff($keys, $bookKeys)));
 }
Exemplo n.º 7
0
 public function testInvalidCollectionRelation()
 {
     $json = array("name" => "Test", "relations" => array("foo:unknown" => "http://zotero.org/groups/1/collections/AAAAAAAA"));
     $response = API::userPost(self::$config['userID'], "collections?key=" . self::$config['apiKey'], json_encode(array("collections" => array($json))));
     $this->assert400ForObject($response, "Unsupported predicate 'foo:unknown'");
     $json["relations"] = array("owl:sameAs" => "Not a URI");
     $response = API::userPost(self::$config['userID'], "collections?key=" . self::$config['apiKey'], json_encode(array("collections" => array($json))));
     $this->assert400ForObject($response, "'relations' values currently must be Zotero collection URIs");
     $json["relations"] = ["http://zotero.org/groups/1/collections/AAAAAAAA"];
     $response = API::userPost(self::$config['userID'], "collections?key=" . self::$config['apiKey'], json_encode(array("collections" => array($json))));
     $this->assert400ForObject($response, "'relations' property must be an object");
 }
Exemplo n.º 8
0
 public function testNoteTooLongWithinHTMLTags()
 {
     $this->json->note = "&nbsp;\n<p><!-- " . $this->content . " --></p>";
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(array("items" => array($this->json))), array("Content-Type: application/json"));
     $this->assert400ForObject($response, "Note '&lt;p&gt;&lt;!-- 1234567890123456789012345678901234567890123456789012345678901234...' too long");
 }
Exemplo n.º 9
0
 public function testAddFileLinkedAttachment()
 {
     $xml = API::createAttachmentItem("linked_file", [], false, $this);
     $data = API::parseDataFromAtomEntry($xml);
     $file = "work/file";
     $fileContents = self::getRandomUnicodeString();
     file_put_contents($file, $fileContents);
     $hash = md5_file($file);
     $filename = "test_" . $fileContents;
     $mtime = filemtime($file) * 1000;
     $size = filesize($file);
     $contentType = "text/plain";
     $charset = "utf-8";
     // Get upload authorization
     $response = API::userPost(self::$config['userID'], "items/{$data['key']}/file?key=" . self::$config['apiKey'], $this->implodeParams(array("md5" => $hash, "filename" => $filename, "filesize" => $size, "mtime" => $mtime, "contentType" => $contentType, "charset" => $charset)), array("Content-Type: application/x-www-form-urlencoded", "If-None-Match: *"));
     $this->assert400($response);
 }
Exemplo n.º 10
0
 public function testMappedCreatorTypes()
 {
     $json = array("items" => array(array('itemType' => 'presentation', 'title' => 'Test', 'creators' => array(array("creatorType" => "author", "name" => "Foo"))), array('itemType' => 'presentation', 'title' => 'Test', 'creators' => array(array("creatorType" => "editor", "name" => "Foo")))));
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode($json));
     // 'author' gets mapped automatically
     $this->assert200ForObject($response);
     // Others don't
     $this->assert400ForObject($response, false, 1);
 }
Exemplo n.º 11
0
 public function testReverseSameAs()
 {
     $items = array();
     $item = ["key" => API::createItem("book", false, null, 'key'), "relations" => [["owl:sameAs", "http://zotero.org/groups/1/items/AAAAAAAA"]]];
     $xml = Sync::updated(self::$sessionID);
     $updateKey = $xml['updateKey'];
     $lastSyncTimestamp = $xml['timestamp'];
     $xmlstr = '<data version="9">' . '<relations>';
     $subject = 'http://zotero.org/users/' . self::$config['userID'] . '/items/' . $item['key'];
     // Insert backwards, as client does via classic sync
     // if group item is dragged to personal library
     foreach ($item['relations'] as $rel) {
         $xmlstr .= '<relation libraryID="' . self::$config['libraryID'] . '">' . "<subject>{$rel[1]}</subject>" . "<predicate>{$rel[0]}</predicate>" . "<object>{$subject}</object>" . '</relation>';
     }
     $xmlstr .= '</relations>' . '</data>';
     $response = Sync::upload(self::$sessionID, $updateKey, $xmlstr);
     Sync::waitForUpload(self::$sessionID, $response, $this);
     // Check via API
     $response = API::userGet(self::$config['userID'], "items/{$item['key']}?key=" . self::$config['apiKey'] . "&content=json");
     $content = API::getContentFromResponse($response);
     $json = json_decode($content, true);
     $uniquePredicates = array_unique(array_map(function ($x) {
         return $x[0];
     }, $item['relations']));
     $this->assertCount(sizeOf($uniquePredicates), $json['relations']);
     foreach ($item['relations'] as $rel) {
         $this->assertArrayHasKey($rel[0], $json['relations']);
         $this->assertContains($rel[1], $json['relations'][$rel[0]]);
     }
     // PUT via API, which should be unchanged
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(["items" => [$json]]));
     $results = json_decode($response->getBody(), true);
     $this->assertArrayHasKey('unchanged', $results);
     $this->assertContains($item['key'], $results['unchanged']);
     // Add another owl:sameAs via API
     if (is_string($json['relations']['owl:sameAs'])) {
         $json['relations']['owl:sameAs'] = [$json['relations']['owl:sameAs']];
     }
     $newURI = "http://zotero.org/groups/1/items/BBBBBBBB";
     $json['relations']['owl:sameAs'][] = $newURI;
     $item['relations'][] = ['owl:sameAs', $newURI];
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(["items" => [$json]]));
     $this->assertEquals(200, $response->getStatus());
     $results = json_decode($response->getBody(), true);
     $this->assertArrayHasKey('success', $results);
     $this->assertContains($item['key'], $results['success']);
     // Check via API
     $response = API::userGet(self::$config['userID'], "items/{$item['key']}?key=" . self::$config['apiKey'] . "&content=json");
     $content = API::getContentFromResponse($response);
     $json = json_decode($content, true);
     $uniquePredicates = array_unique(array_map(function ($x) {
         return $x[0];
     }, $item['relations']));
     $this->assertCount(sizeOf($uniquePredicates), $json['relations']);
     foreach ($item['relations'] as $rel) {
         $this->assertArrayHasKey($rel[0], $json['relations']);
         $this->assertContains($rel[1], $json['relations'][$rel[0]]);
     }
     $this->assertArrayHasKey("owl:sameAs", $json['relations']);
     $this->assertContains($newURI, $json['relations']['owl:sameAs']);
     $xml = Sync::updated(self::$sessionID);
     $updateKey = $xml['updateKey'];
     // First URL should still be in reverse order
     $this->assertEquals(2, sizeOf($xml->updated[0]->relations->xpath("//relations/relation")));
     $subRel = $xml->updated[0]->relations->xpath("//relations/relation[subject/text() = '{$item['relations'][0][1]}']");
     $objRel = $xml->updated[0]->relations->xpath("//relations/relation[object/text() = '{$newURI}']");
     $this->assertEquals(1, sizeOf($subRel));
     $this->assertEquals($subject, $subRel[0]->object);
     $this->assertEquals(1, sizeOf($objRel));
     $this->assertEquals($subject, $objRel[0]->subject);
     // Resave second relation via classic sync in reverse order
     $xmlstr = '<data version="9"><relations>';
     $xmlstr .= '<relation libraryID="' . self::$config['libraryID'] . '">' . "<subject>{$newURI}</subject>" . "<predicate>owl:sameAs</predicate>" . "<object>{$subject}</object>" . "</relation></relations></data>";
     $response = Sync::upload(self::$sessionID, $updateKey, $xmlstr);
     Sync::waitForUpload(self::$sessionID, $response, $this);
     $xml = Sync::updated(self::$sessionID);
     $this->assertEquals(2, sizeOf($xml->updated[0]->relations->xpath("//relations/relation")));
     // Delete reverse relation via API
     $response = API::userGet(self::$config['userID'], "items/{$item['key']}?key=" . self::$config['apiKey'] . "&content=json");
     $content = API::getContentFromResponse($response);
     $json = json_decode($content, true);
     // Leave just the relation that's entered in normal order
     $json['relations']['owl:sameAs'] = [$newURI];
     $item['relations'] = ['owl:sameAs', $newURI];
     $response = API::userPost(self::$config['userID'], "items?key=" . self::$config['apiKey'], json_encode(["items" => [$json]]));
     $this->assertEquals(200, $response->getStatus());
     $results = json_decode($response->getBody(), true);
     $this->assertArrayHasKey('success', $results);
     $this->assertContains($item['key'], $results['success']);
     $response = API::userGet(self::$config['userID'], "items/{$item['key']}?key=" . self::$config['apiKey'] . "&content=json");
     $content = API::getContentFromResponse($response);
     $json = json_decode($content, true);
     $this->assertArrayHasKey("owl:sameAs", $json['relations']);
     $this->assertContains($newURI, $json['relations']['owl:sameAs']);
     // Should only have one relation left
     $this->assertEquals(1, sizeOf($json['relations']['owl:sameAs']));
 }
Exemplo n.º 12
0
 private function _testMultiObjectLastModifiedVersion($objectType)
 {
     $objectTypePlural = API::getPluralObjectType($objectType);
     $objectKeyProp = $objectType . "Key";
     $objectVersionProp = $objectType . "Version";
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'] . "&limit=1");
     $version = $response->getHeader("Last-Modified-Version");
     $this->assertTrue(is_numeric($version));
     switch ($objectType) {
         case 'collection':
             $json = new \stdClass();
             $json->name = "Name";
             break;
         case 'item':
             $json = API::getItemTemplate("book");
             break;
         case 'search':
             $json = new \stdClass();
             $json->name = "Name";
             $json->conditions = array(array("condition" => "title", "operator" => "contains", "value" => "test"));
             break;
     }
     // Outdated library version
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode(array($objectTypePlural => array($json))), array("Content-Type: application/json", "If-Unmodified-Since-Version: " . ($version - 1)));
     $this->assert412($response);
     // Make sure version didn't change during failure
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'] . "&limit=1");
     $this->assertEquals($version, $response->getHeader("Last-Modified-Version"));
     // Create a new object, using library timestamp
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode(array($objectTypePlural => array($json))), array("Content-Type: application/json", "If-Unmodified-Since-Version: {$version}"));
     $this->assert200($response);
     $version2 = $response->getHeader("Last-Modified-Version");
     $this->assertTrue(is_numeric($version2));
     // Version should be incremented on new object
     $this->assertGreaterThan($version, $version2);
     $objectKey = API::getFirstSuccessKeyFromResponse($response);
     // Check single-object request
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}/{$objectKey}?key=" . self::$config['apiKey'] . "&content=json");
     $this->assert200($response);
     $version = $response->getHeader("Last-Modified-Version");
     $this->assertTrue(is_numeric($version));
     $this->assertEquals($version, $version2);
     $json = json_decode(API::getContentFromResponse($response));
     // Modify object
     $json->{$objectKeyProp} = $objectKey;
     switch ($objectType) {
         case 'collection':
             $json->name = "New Name";
             break;
         case 'item':
             $json->title = "New Title";
             break;
         case 'search':
             $json->name = "New Name";
             break;
     }
     // No If-Unmodified-Since-Version or object version property
     unset($json->{$objectVersionProp});
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode(array($objectTypePlural => array($json))), array("Content-Type: application/json"));
     $this->assert428ForObject($response);
     // Outdated object version property
     $json->{$objectVersionProp} = $version - 1;
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode(array($objectTypePlural => array($json))), array("Content-Type: application/json"));
     $this->assert412ForObject($response, ucwords($objectType) . " has been modified since specified version " . "(expected {$json->{$objectVersionProp}}, found {$version})");
     // Modify object, using object version property
     $json->{$objectVersionProp} = $version;
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode(array($objectTypePlural => array($json))), array("Content-Type: application/json"));
     $this->assert200($response);
     // Version should be incremented on modified object
     $version3 = $response->getHeader("Last-Modified-Version");
     $this->assertTrue(is_numeric($version3));
     $this->assertGreaterThan($version2, $version3);
     // Check library version
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey']);
     $version = $response->getHeader("Last-Modified-Version");
     $this->assertTrue(is_numeric($version));
     $this->assertEquals($version, $version3);
     // Check single-object request
     $response = API::userGet(self::$config['userID'], "{$objectTypePlural}/{$objectKey}?key=" . self::$config['apiKey']);
     $version = $response->getHeader("Last-Modified-Version");
     $this->assertTrue(is_numeric($version));
     $this->assertEquals($version, $version3);
     // TODO: Version should be incremented on deleted item
 }
Exemplo n.º 13
0
 public function testEditMultipleCollections()
 {
     $xml = API::createCollection("Test 1", false, $this, 'atom');
     $data = API::parseDataFromAtomEntry($xml);
     $key1 = $data['key'];
     $xml = API::createCollection("Test 2", false, $this, 'atom');
     $data = API::parseDataFromAtomEntry($xml);
     $key2 = $data['key'];
     $newName1 = "Test 1 Modified";
     $newName2 = "Test 2 Modified";
     $response = API::userPost(self::$config['userID'], "collections?key=" . self::$config['apiKey'], json_encode(array("collections" => array(array('collectionKey' => $key1, 'name' => $newName1), array('collectionKey' => $key2, 'name' => $newName2)))), array("Content-Type: application/json", "If-Unmodified-Since-Version: " . $data['version']));
     $this->assert200($response);
     $json = API::getJSONFromResponse($response);
     $this->assertCount(2, $json['success']);
     $xml = API::getCollectionXML($json['success']);
     $this->assertEquals(2, (int) array_shift($xml->xpath('/atom:feed/zapi:totalResults')));
     $contents = $xml->xpath('/atom:feed/atom:entry/atom:content');
     $content = json_decode(array_shift($contents));
     $this->assertEquals($newName1, $content->name);
     $this->assertFalse($content->parentCollection);
     $content = json_decode(array_shift($contents));
     $this->assertEquals($newName2, $content->name);
     $this->assertFalse($content->parentCollection);
 }
Exemplo n.º 14
0
 private function _testMultiObjectWriteInvalidObject($objectType)
 {
     $objectTypePlural = API::getPluralObjectType($objectType);
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode([[]]), array("Content-Type: application/json"));
     $this->assert400($response, "Uploaded data must be a JSON object");
     $response = API::userPost(self::$config['userID'], "{$objectTypePlural}?key=" . self::$config['apiKey'], json_encode(array("{$objectTypePlural}" => array("foo" => "bar"))), array("Content-Type: application/json"));
     $this->assert400($response, "'{$objectTypePlural}' must be an array");
 }