diff --git a/README.md b/README.md index a998265..f9af929 100644 --- a/README.md +++ b/README.md @@ -121,5 +121,59 @@ The Greenhouse packages requires you to do it like this: This prevents issues that arise for systems that do not understand the array-indexed nomenclature preferred by Libcurl. +# The Harvest Service +Use this service to interact with the Harvest API in Greenhouse. Documentation for the Harvest API [can be found here.](https://developers.greenhouse.io/harvest.html/) The purpose of this service is to make interactions with the Harvest API easier. To create a Harvest Service object, you must supply an active Harvest API key. Note that these are different than Job Board API keys. +``` +getHarvestService(); +?> +``` + +Via the Harvest service, you can interact with any Harvest methods outlined in the Greenhouse Harvest docs. Harvest URLs fit mostly in to one of the following three formats: + +1. `https://harvest.greenhouse.io/v1/`: This is the most common URL format for GET methods in Greenhouse. For endpoints in this format, the method will look like `$harvestService->getObject()`. Examples of this are `$harvestService->getJobs()` or `$harvestService->getCandidates()` +2. `https://harvest.greenhouse.io/v1//`: This will get the object with the given ID. This is expected to only return or operate on one object. The ID will always be supplied by an parameter array with a key named `id`. For instance: `$harvestService->getCandidate($parameters);` +3. `https://harvest.greenhouse.io/v1///`: URLs in this format usually mean that you want to get all the sub_objects for the object with the object id. Examples of this are `$harvestService->getJobStagesForJob(array('id' => 123))` and `$harvestService->getOffersForApplication(array('id' => 123))` +4. Some method calls and URLs do not exactly fit this format, but the methods were named as close to fitting that format as possible. These include: + * `getActivityFeedForCandidate`: [Get a candidate's activity feed](https://developers.greenhouse.io/harvest.html#retrieve-activity-feed-for-candidate) + * `postNoteForCandidate`: [Add a note to a candidate](https://developers.greenhouse.io/harvest.html#create-a-candidate-39-s-note) + * `putAnonymizeCandidate`: [Anonymize some fields on a candidate](https://developers.greenhouse.io/harvest.html#anonymize-a-candidate) + * `getCurrentOfferForApplication`: [Get only the current offer for a candidate](https://developers.greenhouse.io/harvest.html#retrieve-current-offer-for-application) + * `postAdvanceApplication`: [Advance an application to the next stage](https://developers.greenhouse.io/harvest.html#advance-an-application) + * `postMoveApplication`: [Move an application to any stage.](https://developers.greenhouse.io/harvest.html#move-an-application) + * `postRejectApplication`: [Reject an application](https://developers.greenhouse.io/harvest.html#reject-an-application) + +You should use the parameters array to supply any URL parameters and headers required by the harvest methods. For any items that require a JSON body, this will also be supplied in the parameter array. + + +Ex: [Moving an application](https://developers.greenhouse.io/harvest.html#move-an-application) +``` +$parameters = array( + 'id' => $applicationId, + 'headers' => array('On-Behalf-Of' => $auditUserId), + 'body' => '{"from_stage_id": 123, "to_stage_id": 234}' +); +$harvestService->moveApplication($parameters); +``` + +Note you do not have to supply the authorization header in the `headers` array. This will be appended to the headers array automatically presuming the supplied API key is valid. + +The parameters array is also used to supply any paging and filtering options that would normally be supplied as a GET query string. Anything that is not in the `id`, `headers`, or `body` key will be assumed to be a URL parameter. + +Ex: [Getting a page of applications](https://developers.greenhouse.io/harvest.html#list-applications) +``` +$parameters = array( + 'per_page' => 100, + 'page' => 2 +); +$harvestService->getApplications($parameters); +// Will call https://harvest.greenhouse.io/v1/applications?per_page=100&page=2 +``` + +If the ID key is supplied in any way, that will take precedence. + +**A note on future development**: The Harvest package makes use PHP's magic `__call` method. This is to handle Greenhouse's Harvest API advancing past this package. New endpoint URLs should work automatically. If Greenhouse adds a GET `https://harvest.greenhouse.io/v1/widgets` endpoint, calling `$harvestService->getWidgets()` should be supported by this package. + + # Exceptions All exceptions raised by the Greenhouse Service library extend from `GreenhouseException`. Catch this exception to catch anything thrown from this library. diff --git a/src/Clients/ApiClientInterface.php b/src/Clients/ApiClientInterface.php index b709933..0708be1 100644 --- a/src/Clients/ApiClientInterface.php +++ b/src/Clients/ApiClientInterface.php @@ -40,4 +40,11 @@ public function post(Array $postParams, Array $headers, $url); * @return mixed Whatever method of sending POST that $this->post understands */ public function formatPostParameters(Array $postParameters); + + /** + * Send is a catch-all method that allows you to use a magic method to catch any type of request + * and forward it on. This is based on the Guzzle send method, but can be altered to fit any other + * future client. + */ + public function send($method, $url, Array $options); } \ No newline at end of file diff --git a/src/Clients/GuzzleClient.php b/src/Clients/GuzzleClient.php index 33cd394..0b7bd96 100644 --- a/src/Clients/GuzzleClient.php +++ b/src/Clients/GuzzleClient.php @@ -75,6 +75,17 @@ public function post(Array $postVars, Array $headers, $url=null) return (string) $guzzleResponse->getBody(); } + public function send($method, $url, Array $options=array()) + { + try { + $guzzleResponse = $this->_client->request($method, $url, $options); + } catch (RequestException $e) { + throw new GreenhouseAPIResponseException($e->getMessage(), 0, $e); + } + + return (string) $guzzleResponse->getBody(); + } + /** * Return a Guzzle post parameter array that can be entered in to the 'multipart' * argument of a post request. For details on this, see the Guzzle diff --git a/src/GreenhouseService.php b/src/GreenhouseService.php index 78fa4f7..d413912 100644 --- a/src/GreenhouseService.php +++ b/src/GreenhouseService.php @@ -50,4 +50,9 @@ public function getJobBoardService() { return new \Greenhouse\GreenhouseToolsPhp\Services\JobBoardService($this->_boardToken); } + + public function getHarvestService() + { + return new \Greenhouse\GreenhouseToolsPhp\Services\HarvestService($this->_apiKey); + } } \ No newline at end of file diff --git a/src/Services/ApiService.php b/src/Services/ApiService.php index 8d44622..3173fd8 100644 --- a/src/Services/ApiService.php +++ b/src/Services/ApiService.php @@ -2,7 +2,6 @@ namespace Greenhouse\GreenhouseToolsPhp\Services; -use Greenhouse\GreenhouseToolsPhp\Services\ApiService; use Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException; class ApiService @@ -10,9 +9,11 @@ class ApiService protected $_apiClient; protected $_clientToken; protected $_apiKey; + protected $_authorizationHeader; const APPLICATION_URL = 'https://api.greenhouse.io/v1/applications/'; const API_V1_URL = 'https://api.greenhouse.io/v1/'; + const HARVEST_V1_URL = 'https://harvest.greenhouse.io/v1/'; public function setClient($apiClient) { diff --git a/src/Services/ApplicationService.php b/src/Services/ApplicationService.php index 3452b1b..a97200c 100644 --- a/src/Services/ApplicationService.php +++ b/src/Services/ApplicationService.php @@ -17,7 +17,6 @@ */ class ApplicationService extends ApiService { - private $_authorizationHeader; private $_jobApiService; /** diff --git a/src/Services/HarvestService.php b/src/Services/HarvestService.php new file mode 100644 index 0000000..4e81d87 --- /dev/null +++ b/src/Services/HarvestService.php @@ -0,0 +1,133 @@ +_apiKey = $apiKey; + $client = new GuzzleClient(array('base_uri' => self::HARVEST_V1_URL)); + $this->setClient($client); + $this->_authorizationHeader = $this->getAuthorizationHeader($apiKey); + $this->_harvestHelper = new HarvestHelper(); + } + + public function getHarvest() + { + return $this->_harvest; + } + + public function sendRequest() + { + $authHeader = array('Authorization' => $this->_authorizationHeader); + $allHeaders = array_merge($this->_harvest['headers'], $authHeader); + $requestUrl = $this->_harvestHelper->addQueryString($this->_harvest['url'], $this->_harvest['parameters']); + $options = array( + 'headers' => $allHeaders, + 'body' => $this->_harvest['body'], + ); + + return $this->_apiClient->send($this->_harvest['method'], $requestUrl, $options); + } + + /** + * In order to keep up to date with changes to the Harvest api and not trigger a re-release of this + * package each time a new method is created, the magic Call method is used to construct URLs to the + * Harvest API. This will use the called method and the arguments provided to create the proper URL + * to request the service. This should return the response from the API on success and raise an + * exception on failure. In most cases, this should be straightforward parsing. + * + * 1) getApplications() will transform in to a Get request to "applications" + * 2) getApplications(array('id' => 12345)) will translate to a GET request to "applications/12345" + * 3) getScorecardsForApplications(array('id' => 12345)) will translate to + * "applications/12345/scorecards + */ + public function __call($name, $arguments) + { + $args = sizeof($arguments) > 0 ? $arguments[0] : array(); + $this->_harvest = $this->_harvestHelper->parse($name, $args); + return $this->sendRequest(); + } + + /** + * All methods below this point are methods that don't fit in the standard url format. Either the + * words are not pluralized (application/12345/move instead of moves) or there is an additional word + * at the end of the URL (application/123/offers/current_offer) which we can't handle in the magic method + * above. Standard URLs that fit the common Harvest format will work automatically going forward. Any + * exceptions should go below this line. + */ + + public function getActivityFeedForCandidate($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('getActivityFeedForCandidate', $parameters); + return $this->_trimUrlAndSendRequest(); + } + + public function postNoteForCandidate($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('postActivityFeedForCandidate', $parameters); + $this->_harvest['url'] = 'candidates/' . $parameters['id'] . '/activity_feed/notes'; + $this->sendRequest(); + } + + public function putAnonymizeCandidate($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('putAnonymizeForCandidate', $parameters); + return $this->_trimUrlAndSendRequest(); + } + + public function getJobPostsForJob($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('getJobPostForJob', $parameters); + return $this->_trimUrlAndSendRequest(); + } + + public function getJobStagesForJob($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('getStagesForJob', $parameters); + return $this->sendRequest(); + } + + public function getCurrentOfferForApplication($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('getOffersForApplication', $parameters); + $this->_harvest['url'] = $this->_harvest['url'] . '/current_offer'; + return $this->sendRequest(); + } + + public function postAdvanceApplication($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('postAdvanceForApplication', $parameters); + return $this->_trimUrlAndSendRequest(); + } + + public function postMoveApplication($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('postMoveForApplication', $parameters); + return $this->_trimUrlAndSendRequest(); + } + + public function postRejectApplication($parameters=array()) + { + $this->_harvest = $this->_harvestHelper->parse('postRejectForApplication', $parameters); + return $this->_trimUrlAndSendRequest(); + } + + private function _trimUrlAndSendRequest() + { + $this->_harvest['url'] = substr($this->_harvest['url'], 0, -1); + return $this->sendRequest(); + } +} \ No newline at end of file diff --git a/src/Tools/HarvestHelper.php b/src/Tools/HarvestHelper.php new file mode 100644 index 0000000..f6f5cef --- /dev/null +++ b/src/Tools/HarvestHelper.php @@ -0,0 +1,80 @@ +methodToEndpoint($matches[2], $parameters); + + if (isset($parameters['id'])) unset($parameters['id']); + if (isset($parameters['headers'])) { + $return['headers'] = $parameters['headers']; + unset($parameters['headers']); + } else { + $return['headers'] = array(); + } + if (isset($parameters['body'])) { + $return['body'] = $parameters['body']; + unset($parameters['body']); + } else { + $return['body'] = null; + } + + $return['parameters'] = $parameters; + + return $return; + } + + public function methodToEndpoint($methodText, $parameters) + { + $id = isset($parameters['id']) ? $parameters['id'] : null; + $objects = explode('For', $methodText); + + // A single object, just return the snaked version of it. + if (sizeof($objects) == 1) { + $url = $this->_decamelizeAndPluralize($objects[0]); + if ($id) $url .= "/$id"; + + // Double object, expect the format object/id/object + } else if (sizeof($objects) == 2) { + if (!$id) throw new GreenhouseServiceException("Harvest Service: method call $methodText must include an id parameter"); + $url = $this->_decamelizeAndPluralize($objects[1]) . "/$id/" . $this->_decamelizeAndPluralize($objects[0]); + } else { + throw new GreenhouseServiceException("Harvest Service: Invalid method call $methodText."); + } + + return $url; + } + + public function addQueryString($url, $parameters=array()) + { + if (sizeof($parameters)) { + return $url . '?' . http_build_query($parameters); + } else { + return $url; + } + } + + private function _decamelizeAndPluralize($string) + { + $decamelized = strtolower(preg_replace(['/([a-z0-9])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string)); + if (substr($decamelized, -1) != 's') $decamelized .= 's'; + + return $decamelized; + } +} diff --git a/tests/GreenhouseServiceTest.php b/tests/GreenhouseServiceTest.php index 3f55779..b10540d 100644 --- a/tests/GreenhouseServiceTest.php +++ b/tests/GreenhouseServiceTest.php @@ -74,4 +74,15 @@ public function testGetApplicationService() $this->assertEquals($baseUrl, $service->getJobBoardBaseUrl()); $this->assertEquals($authHeader, $service->getAuthorizationHeader()); } + + public function testGetHarvestService() + { + $service = $this->greenhouseService->getHarvestService(); + $this->assertInstanceOf( + '\Greenhouse\GreenhouseToolsPhp\Services\HarvestService', + $service + ); + $authHeader = 'Basic ' . base64_encode($this->apiKey . ':'); + $this->assertEquals($authHeader, $service->getAuthorizationHeader()); + } } diff --git a/tests/Services/HarvestServiceTest.php b/tests/Services/HarvestServiceTest.php new file mode 100644 index 0000000..19027bc --- /dev/null +++ b/tests/Services/HarvestServiceTest.php @@ -0,0 +1,892 @@ +harvestService = new HarvestService('greenhouse'); + $apiStub = $this->getMockBuilder('\Greenhouse\GreenhouseToolsPhp\Client\GuzzleClient') + ->setMethods(array('send')) + ->getMock(); + $this->harvestService->setClient($apiStub); + $this->expectedAuth = 'Basic Z3JlZW5ob3VzZTo='; + } + + public function testGetActivityFeed() + { + $expected = array( + 'method' => 'get', + 'url' => 'candidates/12345/activity_feed', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getActivityFeedForCandidate($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetActivityFeedRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->getActivityFeedForCandidate($params); + } + + public function testGetApplicationsNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getApplications($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetApplicationsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'applications', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getApplications($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetApplication() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getApplications($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPostAdvanceApplication() + { + $expected = array( + 'method' => 'post', + 'url' => 'applications/12345/advance', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"from_stage_id": 345}', + 'parameters' => array() + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"from_stage_id": 345}', + 'id' => 12345 + ); + + $this->harvestService->postAdvanceApplication($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPostMoveApplication() + { + $expected = array( + 'method' => 'post', + 'url' => 'applications/12345/move', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"from_stage_id": 345}', + 'parameters' => array() + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"from_stage_id": 345}', + 'id' => 12345 + ); + + $this->harvestService->postMoveApplication($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPostRejectApplication() + { + $expected = array( + 'method' => 'post', + 'url' => 'applications/12345/reject', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"from_stage_id": 345}', + 'parameters' => array() + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"from_stage_id": 345}', + 'id' => 12345 + ); + + $this->harvestService->postRejectApplication($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testMoveApplicationRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->postMoveApplication($params); + } + + public function testAdvanceApplicationRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->postAdvanceApplication($params); + } + + public function testRejectApplicationRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->postRejectApplication($params); + } + + public function testGetCandidatesNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'candidates', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getCandidates($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetCandidatesPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'candidates', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getCandidates($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetCandidate() + { + $expected = array( + 'method' => 'get', + 'url' => 'candidates/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getCandidates($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPatchCandidate() + { + $expected = array( + 'method' => 'patch', + 'url' => 'candidates/12345', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'parameters' => array() + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'id' => 12345 + ); + + $this->harvestService->patchCandidate($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPostAttachment() + { + $expected = array( + 'method' => 'post', + 'url' => 'candidates/12345/attachments', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'parameters' => array() + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'id' => 12345 + ); + + $this->harvestService->postAttachmentForCandidate($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPutAnonymize() + { + $expected = array( + 'method' => 'put', + 'url' => 'candidates/12345/anonymize', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'parameters' => array('fields' => 'some,fields,go,here') + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'id' => 12345, + 'fields' => 'some,fields,go,here' + ); + + $this->harvestService->putAnonymizeCandidate($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testPostNote() + { + $expected = array( + 'method' => 'post', + 'url' => 'candidates/12345/activity_feed/notes', + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'parameters' => array() + ); + $params = array( + 'headers' => array('On-Behalf-Of' => 234), + 'body' => '{"update_json": "is_here"}', + 'id' => 12345 + ); + + $this->harvestService->postNoteForCandidate($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetDepartmentsNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'departments', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getDepartments($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetDepartmentsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'departments', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getDepartments($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetDepartment() + { + $expected = array( + 'method' => 'get', + 'url' => 'departments/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getDepartments($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetEmailTemplatesNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'email_templates', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getEmailTemplates($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetEmailTemplatesPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'email_templates', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getEmailTemplates($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetEmailTemplate() + { + $expected = array( + 'method' => 'get', + 'url' => 'email_templates/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getEmailTemplates($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJobPosts() + { + $expected = array( + 'method' => 'get', + 'url' => 'job_posts', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getJobPosts($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJobPostsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'job_posts', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getJobPosts($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJobPostsForJob() + { + $expected = array( + 'method' => 'get', + 'url' => 'jobs/12345/job_post', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getJobPostsForJob($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJobStagesForJob() + { + $expected = array( + 'method' => 'get', + 'url' => 'jobs/12345/stages', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getJobStagesForJob($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJobsNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'jobs', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getJobs($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJobsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'jobs', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getJobs($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetJob() + { + $expected = array( + 'method' => 'get', + 'url' => 'jobs/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getJobs($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOfferNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'offers', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getOffers($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOffersPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'offers', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getOffers($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOffer() + { + $expected = array( + 'method' => 'get', + 'url' => 'offers/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getOffers($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOffersForApplications() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications/12345/offers', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getOffersForApplication($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOffersForApplicationRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->getOffersForApplication($params); + } + + public function testGetCurrentOfferForApplication() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications/12345/offers/current_offer', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getCurrentOfferForApplication($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetCurrentOfferForApplicationRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->getCurrentOfferForApplication($params); + } + + public function testGetOfficesNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'offices', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getOffices($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOfficesPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'offices', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getOffices($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetOffice() + { + $expected = array( + 'method' => 'get', + 'url' => 'offices/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getOffices($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetRejectionReasonsNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'rejection_reasons', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getRejectionReasons($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetRejectionReasonsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'rejection_reasons', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getRejectionReasons($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetSecheduledInterviewsNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'scheduled_interviews', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getScheduledInterviews($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetScheduledInterviewsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'scheduled_interviews', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getScheduledInterviews($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetScorecardsNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'scorecards', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getScorecards($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetScorecardsPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'scorecards', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getScorecards($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetScorecard() + { + $expected = array( + 'method' => 'get', + 'url' => 'scorecards/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getScorecards($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetScorecardForApplication() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications/12345/scorecards', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getScorecardsForApplication($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetScorecardForApplicationRequiresId() + { + $params = array('noid' => 12345); + + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->harvestService->getScorecardsForApplication($params); + } + + public function testGetSourcesNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'sources', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getSource($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetSourcesPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'sources', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getSource($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetSource() + { + $expected = array( + 'method' => 'get', + 'url' => 'sources/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getSource($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetUsersNoPaging() + { + $expected = array( + 'method' => 'get', + 'url' => 'users', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array(); + + $this->harvestService->getUsers($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetUsersPaging() + { + $params = array('page' => 2, 'per_page' => 100); + $expected = array( + 'method' => 'get', + 'url' => 'users', + 'headers' => array(), + 'body' => null, + 'parameters' => $params + ); + + $this->harvestService->getUsers($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } + + public function testGetUser() + { + $expected = array( + 'method' => 'get', + 'url' => 'users/12345', + 'headers' => array(), + 'body' => null, + 'parameters' => array() + ); + $params = array('id' => 12345); + + $this->harvestService->getUsers($params); + $this->assertEquals($expected, $this->harvestService->getHarvest()); + $this->assertEquals($this->expectedAuth, $this->harvestService->getAuthorizationHeader()); + } +} \ No newline at end of file diff --git a/tests/Tools/HarvestHelperTest.php b/tests/Tools/HarvestHelperTest.php new file mode 100644 index 0000000..e4944d3 --- /dev/null +++ b/tests/Tools/HarvestHelperTest.php @@ -0,0 +1,131 @@ +json = file_get_contents("$root/../files/test_json/single_job_response.json"); + $this->parser = new HarvestHelper(); + $this->parameters = array('per_page' => 10, 'page' => 2); + } + + public function testParseGetSingleWordMethodNoId() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications', + 'parameters' => $this->parameters, + 'headers' => array(), + 'body' => null + ); + $this->assertEquals($expected, $this->parser->parse('getApplications', $this->parameters)); + } + + public function testParseGetSingleWordMethodWithId() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications/12345', + 'parameters' => $this->parameters, + 'headers' => array(), + 'body' => null + ); + $params = array_merge($this->parameters, array('id' => 12345)); + $this->assertEquals($expected, $this->parser->parse('getApplications', $params)); + } + + public function testParseGetDoubleWordMethodNoId() + { + $expected = array( + 'method' => 'get', + 'url' => 'email_templates', + 'parameters' => $this->parameters, + 'headers' => array(), + 'body' => null + ); + $this->assertEquals($expected, $this->parser->parse('getEmailTemplates', $this->parameters)); + } + + public function testParseGetDoubleWordMethodWithId() + { + $expected = array( + 'method' => 'get', + 'url' => 'email_templates/12345', + 'parameters' => array(), + 'headers' => array(), + 'body' => null + ); + $this->assertEquals($expected, $this->parser->parse('getEmailTemplates', array('id' => 12345))); + } + + public function testParseGetSingleWordMethodWithForWithId() + { + $expected = array( + 'method' => 'get', + 'url' => 'applications/12345/scorecards', + 'parameters' => $this->parameters, + 'headers' => array(), + 'body' => null + ); + $params = array_merge($this->parameters, array('id' => 12345)); + $this->assertEquals($expected, $this->parser->parse('getScorecardsForApplication', $params)); + } + + public function testParseGetDoubleWordMethodWithForWithId() + { + $expected = array( + 'method' => 'get', + 'url' => 'activity_feeds/12345/email_templates', + 'parameters' => $this->parameters, + 'headers' => array(), + 'body' => null + ); + $params = array_merge($this->parameters, array('id' => 12345)); + $this->assertEquals($expected, $this->parser->parse('getEmailTemplatesForActivityFeeds', $params)); + } + + public function testParseGetDoubleWordMethodWithForWithIdPluralized() + { + $expected = array( + 'method' => 'get', + 'url' => 'activity_feeds/12345/email_templates', + 'parameters' => $this->parameters, + 'headers' => array(), + 'body' => null + ); + $params = array_merge($this->parameters, array('id' => 12345)); + $this->assertEquals($expected, $this->parser->parse('getEmailTemplateForActivityFeed', $params)); + } + + public function testParseGetDoubleWordMethodWithForNoId() + { + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->parser->parse('getScorecardsForApplication', array()); + } + + public function testBadHttpMethodFails() + { + $this->expectException('\Greenhouse\GreenhouseToolsPhp\Services\Exceptions\GreenhouseServiceException'); + $this->parser->parse('testCandidates', array()); + } + + public function testAddQueryString() + { + $expected = 'candidate/12345/person?per_page=10&page=2'; + $this->assertEquals($expected, $this->parser->addQueryString('candidate/12345/person', $this->parameters)); + } + + public function testAddQueryStringWithNoParameters() + { + $expected = 'candidate/12345/person'; + $this->assertEquals($expected, $this->parser->addQueryString('candidate/12345/person')); + } +}