diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f06b7a0..4cff3d41 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New interface `Redmine\Http\Request` for sending data with new minimalistic HTTP clients.
- New method `Redmine\Api\...::getLastResponse()` to get the last response made by the API class.
+### Changed
+
+- Calling `Redmine\Api\IssueRelation::create()` without the mandatory parameter `issue_to_id` throws a `Redmine\Exception\MissingParameterException` instead of returning a error array
+
### Fixed
- Parameter types for IDs were fixed in API for attachments, groups, issues, project, users and versions.
@@ -23,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Deprecated
- `Redmine\Api\AbstractApi::get()` is deprecated, use `\Redmine\Http\HttpClient::request()` instead.
+- `Redmine\Api\AbstractApi::post()` is deprecated, use `\Redmine\Http\HttpClient::request()` instead.
## [v2.5.0](https://github.com/kbsali/php-redmine-api/compare/v2.4.0...v2.5.0) - 2024-02-05
diff --git a/src/Redmine/Api/AbstractApi.php b/src/Redmine/Api/AbstractApi.php
index 823df935..af329ca9 100644
--- a/src/Redmine/Api/AbstractApi.php
+++ b/src/Redmine/Api/AbstractApi.php
@@ -2,7 +2,6 @@
namespace Redmine\Api;
-use Closure;
use InvalidArgumentException;
use Redmine\Api;
use Redmine\Client\Client;
@@ -142,6 +141,8 @@ protected function get($path, $decodeIfJson = true)
/**
* Perform the client post() method.
*
+ * @deprecated since v2.6.0, use `\Redmine\Http\HttpClient::request()` instead
+ *
* @param string $path
* @param string $data
*
@@ -149,6 +150,8 @@ protected function get($path, $decodeIfJson = true)
*/
protected function post($path, $data)
{
+ @trigger_error('`' . __METHOD__ . '()` is deprecated since v2.6.0, use `\Redmine\Http\HttpClient::request()` instead.', E_USER_DEPRECATED);
+
$this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeRequest(
'POST',
strval($path),
diff --git a/src/Redmine/Api/Attachment.php b/src/Redmine/Api/Attachment.php
index a1f3491c..6ad17939 100644
--- a/src/Redmine/Api/Attachment.php
+++ b/src/Redmine/Api/Attachment.php
@@ -6,6 +6,7 @@
use Redmine\Http\HttpFactory;
use Redmine\Serializer\JsonSerializer;
use Redmine\Serializer\PathSerializer;
+use SimpleXMLElement;
/**
* Attachment details.
@@ -80,10 +81,14 @@ public function download($id)
*/
public function upload($attachment, $params = [])
{
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeRequest(
+ 'POST',
PathSerializer::create('/uploads.json', $params)->getPath(),
+ 'application/octet-stream',
$attachment
- );
+ ));
+
+ return $this->lastResponse->getContent();
}
/**
@@ -93,7 +98,7 @@ public function upload($attachment, $params = [])
*
* @param int $id id of the attachment
*
- * @return false|\SimpleXMLElement|string
+ * @return false|SimpleXMLElement|string
*/
public function remove($id)
{
diff --git a/src/Redmine/Api/Group.php b/src/Redmine/Api/Group.php
index 42052cce..442f848b 100644
--- a/src/Redmine/Api/Group.php
+++ b/src/Redmine/Api/Group.php
@@ -120,10 +120,19 @@ public function create(array $params = [])
throw new MissingParameterException('Theses parameters are mandatory: `name`');
}
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/groups.xml',
XmlSerializer::createFromArray(['group' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ($body === '') {
+ return $body;
+ }
+
+ return new SimpleXMLElement($body);
}
/**
@@ -205,14 +214,23 @@ public function remove($id)
* @param int $id id of the group
* @param int $userId id of the user
*
- * @return string
+ * @return SimpleXMLElement|string
*/
public function addUser($id, $userId)
{
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/groups/' . $id . '/users.xml',
XmlSerializer::createFromArray(['user_id' => $userId])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ($body === '') {
+ return $body;
+ }
+
+ return new SimpleXMLElement($body);
}
/**
diff --git a/src/Redmine/Api/Issue.php b/src/Redmine/Api/Issue.php
index f8b8ebc7..f56a7ea2 100644
--- a/src/Redmine/Api/Issue.php
+++ b/src/Redmine/Api/Issue.php
@@ -189,10 +189,24 @@ public function create(array $params = [])
$params = $this->cleanParams($params);
$params = $this->sanitizeParams($defaults, $params);
- return $this->post(
+ // FIXME: Throw exception on missing mandatory parameters
+ // if (!isset($params['subject']) || !isset($params['project_id']) || !isset($params['tracker_id']) || !isset($params['priority_id']) || !isset($params['status_id'])) {
+ // throw new MissingParameterException('Theses parameters are mandatory: `subject`, `project_id|project`, `tracker_id|tracker`, `priority_id|priority`, `status_id|status`');
+ // }
+
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/issues.xml',
XmlSerializer::createFromArray(['issue' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ($body === '') {
+ return $body;
+ }
+
+ return new SimpleXMLElement($body);
}
/**
@@ -236,21 +250,30 @@ public function update($id, array $params)
* @param int $id
* @param int $watcherUserId
*
- * @return false|string
+ * @return SimpleXMLElement|string
*/
public function addWatcher($id, $watcherUserId)
{
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/issues/' . urlencode(strval($id)) . '/watchers.xml',
XmlSerializer::createFromArray(['user_id' => urlencode(strval($watcherUserId))])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ($body === '') {
+ return $body;
+ }
+
+ return new SimpleXMLElement($body);
}
/**
* @param int $id
* @param int $watcherUserId
*
- * @return false|\SimpleXMLElement|string
+ * @return false|SimpleXMLElement|string
*/
public function removeWatcher($id, $watcherUserId)
{
@@ -385,7 +408,7 @@ public function attachMany($id, array $attachments)
*
* @param int $id the issue number
*
- * @return false|\SimpleXMLElement|string
+ * @return false|SimpleXMLElement|string
*/
public function remove($id)
{
diff --git a/src/Redmine/Api/IssueCategory.php b/src/Redmine/Api/IssueCategory.php
index bd635ba1..903aabf3 100644
--- a/src/Redmine/Api/IssueCategory.php
+++ b/src/Redmine/Api/IssueCategory.php
@@ -11,6 +11,7 @@
use Redmine\Serializer\JsonSerializer;
use Redmine\Serializer\PathSerializer;
use Redmine\Serializer\XmlSerializer;
+use SimpleXMLElement;
/**
* Listing issue categories, creating, editing.
@@ -161,7 +162,7 @@ public function show($id)
*
* @throws MissingParameterException Missing mandatory parameters
*
- * @return string|false
+ * @return SimpleXMLElement|string
*/
public function create($project, array $params = [])
{
@@ -177,10 +178,19 @@ public function create($project, array $params = [])
throw new MissingParameterException('Theses parameters are mandatory: `name`');
}
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/projects/' . $project . '/issue_categories.xml',
XmlSerializer::createFromArray(['issue_category' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ($body === '') {
+ return $body;
+ }
+
+ return new SimpleXMLElement($body);
}
/**
diff --git a/src/Redmine/Api/IssueRelation.php b/src/Redmine/Api/IssueRelation.php
index 57ef6ae1..5cb90b96 100644
--- a/src/Redmine/Api/IssueRelation.php
+++ b/src/Redmine/Api/IssueRelation.php
@@ -3,6 +3,7 @@
namespace Redmine\Api;
use Redmine\Exception;
+use Redmine\Exception\MissingParameterException;
use Redmine\Exception\SerializerException;
use Redmine\Exception\UnexpectedResponseException;
use Redmine\Http\HttpFactory;
@@ -127,10 +128,17 @@ public function remove($id)
* Create a new issue relation.
*
* @see http://www.redmine.org/projects/redmine/wiki/Rest_IssueRelations#POST
+ * available $params:
+ * - issue_to_id (required): the id of the related issue
+ * - relation_type (required to explicit : default "relates"): the type of relation
+ * (in: "relates", "duplicates", "duplicated", "blocks", "blocked", "precedes", "follows", "copied_to", "copied_from")
+ * - delay (optional): the delay for a "precedes" or "follows" relation
*
* @param int $issueId the ID of the issue we are creating the relation on
* @param array $params the new issue relation data
*
+ * @throws MissingParameterException Missing mandatory parameters
+ *
* @return array
*/
public function create($issueId, array $params = [])
@@ -143,11 +151,18 @@ public function create($issueId, array $params = [])
$params = $this->sanitizeParams($defaults, $params);
- $response = $this->post(
+ if (!isset($params['issue_to_id'])) {
+ throw new MissingParameterException('Theses parameters are mandatory: `issue_to_id`');
+ }
+
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeJsonRequest(
+ 'POST',
'/issues/' . urlencode(strval($issueId)) . '/relations.json',
JsonSerializer::createFromArray(['relation' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
- return JsonSerializer::createFromString($response)->getNormalized();
+ return JsonSerializer::createFromString($body)->getNormalized();
}
}
diff --git a/src/Redmine/Api/Membership.php b/src/Redmine/Api/Membership.php
index 265af375..583be03c 100644
--- a/src/Redmine/Api/Membership.php
+++ b/src/Redmine/Api/Membership.php
@@ -7,7 +7,9 @@
use Redmine\Exception\MissingParameterException;
use Redmine\Exception\SerializerException;
use Redmine\Exception\UnexpectedResponseException;
+use Redmine\Http\HttpFactory;
use Redmine\Serializer\XmlSerializer;
+use SimpleXMLElement;
/**
* Handling project memberships.
@@ -92,7 +94,7 @@ public function all($project, array $params = [])
*
* @throws MissingParameterException Missing mandatory parameters
*
- * @return string|false
+ * @return SimpleXMLElement|string
*/
public function create($project, array $params = [])
{
@@ -106,10 +108,19 @@ public function create($project, array $params = [])
throw new MissingParameterException('Theses parameters are mandatory: `user_id`, `role_ids`');
}
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/projects/' . $project . '/memberships.xml',
XmlSerializer::createFromArray(['membership' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ('' !== $body) {
+ return new SimpleXMLElement($body);
+ }
+
+ return $body;
}
/**
diff --git a/src/Redmine/Api/Project.php b/src/Redmine/Api/Project.php
index 28e4e556..9daa6d6c 100755
--- a/src/Redmine/Api/Project.php
+++ b/src/Redmine/Api/Project.php
@@ -162,7 +162,7 @@ public function show($id, array $params = [])
*
* @throws MissingParameterException
*
- * @return string|SimpleXMLElement|false
+ * @return SimpleXMLElement|string
*/
public function create(array $params = [])
{
@@ -180,10 +180,19 @@ public function create(array $params = [])
throw new MissingParameterException('Theses parameters are mandatory: `name`, `identifier`');
}
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/projects.xml',
XmlSerializer::createFromArray(['project' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ('' !== $body) {
+ return new SimpleXMLElement($body);
+ }
+
+ return $body;
}
/**
diff --git a/src/Redmine/Api/TimeEntry.php b/src/Redmine/Api/TimeEntry.php
index 4c1940bb..5aa63c85 100644
--- a/src/Redmine/Api/TimeEntry.php
+++ b/src/Redmine/Api/TimeEntry.php
@@ -9,6 +9,7 @@
use Redmine\Http\HttpFactory;
use Redmine\Serializer\JsonSerializer;
use Redmine\Serializer\XmlSerializer;
+use SimpleXMLElement;
/**
* Listing time entries, creating, editing.
@@ -111,7 +112,7 @@ public function show($id)
*
* @throws MissingParameterException Missing mandatory parameters
*
- * @return string|false
+ * @return SimpleXMLElement|string
*/
public function create(array $params = [])
{
@@ -132,10 +133,19 @@ public function create(array $params = [])
throw new MissingParameterException('Theses parameters are mandatory: `issue_id` or `project_id`, `hours`');
}
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/time_entries.xml',
XmlSerializer::createFromArray(['time_entry' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ('' !== $body) {
+ return new SimpleXMLElement($body);
+ }
+
+ return $body;
}
/**
diff --git a/src/Redmine/Api/User.php b/src/Redmine/Api/User.php
index ac6ff612..b6ea1aad 100644
--- a/src/Redmine/Api/User.php
+++ b/src/Redmine/Api/User.php
@@ -10,6 +10,7 @@
use Redmine\Serializer\JsonSerializer;
use Redmine\Serializer\PathSerializer;
use Redmine\Serializer\XmlSerializer;
+use SimpleXMLElement;
/**
* Listing users, creating, editing.
@@ -187,7 +188,7 @@ public function show($id, array $params = [])
*
* @throws MissingParameterException Missing mandatory parameters
*
- * @return string|false
+ * @return SimpleXMLElement|string
*/
public function create(array $params = [])
{
@@ -209,10 +210,19 @@ public function create(array $params = [])
throw new MissingParameterException('Theses parameters are mandatory: `login`, `lastname`, `firstname`, `mail`');
}
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/users.xml',
XmlSerializer::createFromArray(['user' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ('' !== $body) {
+ return new SimpleXMLElement($body);
+ }
+
+ return $body;
}
/**
diff --git a/src/Redmine/Api/Version.php b/src/Redmine/Api/Version.php
index be0ccb3e..4fd8faba 100644
--- a/src/Redmine/Api/Version.php
+++ b/src/Redmine/Api/Version.php
@@ -10,6 +10,7 @@
use Redmine\Http\HttpFactory;
use Redmine\Serializer\JsonSerializer;
use Redmine\Serializer\XmlSerializer;
+use SimpleXMLElement;
/**
* Listing versions, creating, editing.
@@ -164,7 +165,7 @@ public function show($id)
*
* @throws MissingParameterException Missing mandatory parameters
*
- * @return string|false
+ * @return SimpleXMLElement|string
*/
public function create($project, array $params = [])
{
@@ -185,10 +186,19 @@ public function create($project, array $params = [])
$this->validateStatus($params);
$this->validateSharing($params);
- return $this->post(
+ $this->lastResponse = $this->getHttpClient()->request(HttpFactory::makeXmlRequest(
+ 'POST',
'/projects/' . $project . '/versions.xml',
XmlSerializer::createFromArray(['version' => $params])->getEncoded()
- );
+ ));
+
+ $body = $this->lastResponse->getContent();
+
+ if ('' !== $body) {
+ return new SimpleXMLElement($body);
+ }
+
+ return $body;
}
/**
diff --git a/src/Redmine/Client/NativeCurlClient.php b/src/Redmine/Client/NativeCurlClient.php
index f2129020..f22e40ce 100644
--- a/src/Redmine/Client/NativeCurlClient.php
+++ b/src/Redmine/Client/NativeCurlClient.php
@@ -298,7 +298,7 @@ private function createCurl(string $method, string $path, string $body = '', str
case 'POST':
$curlOptions[CURLOPT_POST] = 1;
if ($this->isUploadCall($path) && $this->isValidFilePath($body)) {
- @trigger_error('Uploading an attachment by filepath is deprecated, use file_get_contents() to upload the file content instead.', E_USER_DEPRECATED);
+ @trigger_error('Uploading an attachment by filepath is deprecated since v2.1.0, use file_get_contents() to upload the file content instead.', E_USER_DEPRECATED);
$file = fopen($body, 'r');
$size = filesize($body);
diff --git a/src/Redmine/Client/Psr18Client.php b/src/Redmine/Client/Psr18Client.php
index f5f1899b..e83806ab 100644
--- a/src/Redmine/Client/Psr18Client.php
+++ b/src/Redmine/Client/Psr18Client.php
@@ -254,7 +254,7 @@ private function createRequest(string $method, string $path, string $body = '',
switch ($method) {
case 'POST':
if ($this->isUploadCall($path) && $this->isValidFilePath($body)) {
- @trigger_error('Uploading an attachment by filepath is deprecated, use file_get_contents() to upload the file content instead.', E_USER_DEPRECATED);
+ @trigger_error('Uploading an attachment by filepath is deprecated since v2.1.0, use file_get_contents() to upload the file content instead.', E_USER_DEPRECATED);
$request = $request->withBody(
$this->streamFactory->createStreamFromFile($body)
diff --git a/src/Redmine/Http/HttpFactory.php b/src/Redmine/Http/HttpFactory.php
index 77246d69..47222037 100644
--- a/src/Redmine/Http/HttpFactory.php
+++ b/src/Redmine/Http/HttpFactory.php
@@ -84,4 +84,9 @@ public static function makeJsonRequest(string $method, string $path, string $con
{
return static::makeRequest($method, $path, 'application/json', $content);
}
+
+ public static function makeXmlRequest(string $method, string $path, string $content = ''): Request
+ {
+ return static::makeRequest($method, $path, 'application/xml', $content);
+ }
}
diff --git a/tests/Behat/Bootstrap/FeatureContext.php b/tests/Behat/Bootstrap/FeatureContext.php
index d51a9fa2..19821c2e 100644
--- a/tests/Behat/Bootstrap/FeatureContext.php
+++ b/tests/Behat/Bootstrap/FeatureContext.php
@@ -6,7 +6,6 @@
use Behat\Behat\Context\Context;
use Behat\Behat\Hook\Scope\AfterScenarioScope;
-use Behat\Behat\Tester\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;
use Behat\Testwork\Hook\Scope\AfterSuiteScope;
@@ -25,9 +24,14 @@ final class FeatureContext extends TestCase implements Context
{
use AttachmentContextTrait;
use GroupContextTrait;
+ use IssueContextTrait;
+ use IssuePriorityContextTrait;
+ use IssueRelationContextTrait;
+ use IssueStatusContextTrait;
use ProjectContextTrait;
use TimeEntryActivityContextTrait;
use TimeEntryContextTrait;
+ use TrackerContextTrait;
use UserContextTrait;
use VersionContextTrait;
use WikiContextTrait;
diff --git a/tests/Behat/Bootstrap/IssueContextTrait.php b/tests/Behat/Bootstrap/IssueContextTrait.php
new file mode 100644
index 00000000..c536b4aa
--- /dev/null
+++ b/tests/Behat/Bootstrap/IssueContextTrait.php
@@ -0,0 +1,46 @@
+getNativeCurlClient()->getApi('issue');
+
+ $this->registerClientResponse(
+ $api->create($data),
+ $api->getLastResponse()
+ );
+ }
+
+ /**
+ * @When I show the issue with id :issueId
+ */
+ public function iShowTheIssueWithId($issueId)
+ {
+ /** @var Issue */
+ $api = $this->getNativeCurlClient()->getApi('issue');
+
+ $this->registerClientResponse(
+ $api->show($issueId),
+ $api->getLastResponse()
+ );
+ }
+}
diff --git a/tests/Behat/Bootstrap/IssuePriorityContextTrait.php b/tests/Behat/Bootstrap/IssuePriorityContextTrait.php
new file mode 100644
index 00000000..e9eab7ca
--- /dev/null
+++ b/tests/Behat/Bootstrap/IssuePriorityContextTrait.php
@@ -0,0 +1,27 @@
+redmine->excecuteDatabaseQuery(
+ 'INSERT INTO enumerations(name, position, is_default, type, active) VALUES(:name, :position, :is_default, :type, :active);',
+ [],
+ [
+ ':name' => $priority,
+ ':position' => 1,
+ ':is_default' => 1,
+ ':type' => 'IssuePriority',
+ ':active' => 1,
+ ],
+ );
+ }
+}
diff --git a/tests/Behat/Bootstrap/IssueRelationContextTrait.php b/tests/Behat/Bootstrap/IssueRelationContextTrait.php
new file mode 100644
index 00000000..95b0bec1
--- /dev/null
+++ b/tests/Behat/Bootstrap/IssueRelationContextTrait.php
@@ -0,0 +1,31 @@
+getNativeCurlClient()->getApi('issue_relation');
+
+ $this->registerClientResponse(
+ $api->create($issueId, $data),
+ $api->getLastResponse()
+ );
+ }
+}
diff --git a/tests/Behat/Bootstrap/IssueStatusContextTrait.php b/tests/Behat/Bootstrap/IssueStatusContextTrait.php
new file mode 100644
index 00000000..f8c8d16f
--- /dev/null
+++ b/tests/Behat/Bootstrap/IssueStatusContextTrait.php
@@ -0,0 +1,25 @@
+redmine->excecuteDatabaseQuery(
+ 'INSERT INTO issue_statuses(name, is_closed, position) VALUES(:name, :is_closed, :position);',
+ [],
+ [
+ ':name' => $issueStatusName,
+ ':is_closed' => 0,
+ ':position' => 1,
+ ],
+ );
+ }
+}
diff --git a/tests/Behat/Bootstrap/TrackerContextTrait.php b/tests/Behat/Bootstrap/TrackerContextTrait.php
new file mode 100644
index 00000000..d44f2e46
--- /dev/null
+++ b/tests/Behat/Bootstrap/TrackerContextTrait.php
@@ -0,0 +1,27 @@
+redmine->excecuteDatabaseQuery(
+ 'INSERT INTO trackers(name, position, is_in_roadmap, fields_bits, default_status_id) VALUES(:name, :position, :is_in_roadmap, :fields_bits, :default_status_id);',
+ [],
+ [
+ ':name' => $trackerName,
+ ':position' => 1,
+ ':is_in_roadmap' => 1,
+ ':fields_bits' => 0,
+ ':default_status_id' => $statusId,
+ ],
+ );
+ }
+}
diff --git a/tests/Behat/Bootstrap/UserContextTrait.php b/tests/Behat/Bootstrap/UserContextTrait.php
index 42b71ba8..cbd05631 100644
--- a/tests/Behat/Bootstrap/UserContextTrait.php
+++ b/tests/Behat/Bootstrap/UserContextTrait.php
@@ -4,10 +4,31 @@
namespace Redmine\Tests\Behat\Bootstrap;
+use Behat\Gherkin\Node\TableNode;
use Redmine\Api\User;
trait UserContextTrait
{
+ /**
+ * @When I create a user with the following data
+ */
+ public function iCreateAUserWithTheFollowingData(TableNode $table)
+ {
+ $data = [];
+
+ foreach ($table as $row) {
+ $data[$row['property']] = $row['value'];
+ }
+
+ /** @var User */
+ $api = $this->getNativeCurlClient()->getApi('user');
+
+ $this->registerClientResponse(
+ $api->create($data),
+ $api->getLastResponse()
+ );
+ }
+
/**
* @When I show the user with id :userId
*/
diff --git a/tests/Behat/features/issue.feature b/tests/Behat/features/issue.feature
new file mode 100644
index 00000000..58238d5a
--- /dev/null
+++ b/tests/Behat/features/issue.feature
@@ -0,0 +1,123 @@
+Feature: Interacting with the REST API for issues
+ In order to interact with REST API for issues
+ As a user
+ I want to make sure the Redmine server replies with the correct response
+
+ @issue
+ Scenario: Creating an issue with miminal data
+ Given I have a "NativeCurlClient" client
+ And I have an issue status with the name "New"
+ And I have an issue priority with the name "Normal"
+ And I have a tracker with the name "Defect" and default status id "1"
+ And I create a project with name "Test Project" and identifier "test-project"
+ When I create an issue with the following data
+ | property | value |
+ | subject | issue subject |
+ | project | Test Project |
+ | tracker | Defect |
+ | priority | Normal |
+ | status | New |
+ Then the response has the status code "201"
+ And the response has the content type "application/xml"
+ And the returned data is an instance of "SimpleXMLElement"
+ And the returned data has only the following properties
+ """
+ id
+ project
+ tracker
+ status
+ priority
+ author
+ subject
+ description
+ start_date
+ due_date
+ done_ratio
+ is_private
+ estimated_hours
+ total_estimated_hours
+ created_on
+ updated_on
+ closed_on
+ """
+ And the returned data has proterties with the following data
+ | property | value |
+ | id | 1 |
+ | subject | issue subject |
+ | description | [] |
+ | due_date | [] |
+ | done_ratio | 0 |
+ | is_private | false |
+ | estimated_hours | [] |
+ | total_estimated_hours | [] |
+ And the returned data "project" property is an array
+ And the returned data "project" property contains "1" items
+ And the returned data "project.@attributes" property is an array
+ And the returned data "project.@attributes" property has only the following properties
+ """
+ id
+ name
+ """
+ And the returned data "project.@attributes" property contains the following data
+ | property | value |
+ | id | 1 |
+ | name | Test Project |
+ And the returned data "tracker" property is an array
+ And the returned data "tracker" property contains "1" items
+ And the returned data "tracker.@attributes" property is an array
+ And the returned data "tracker.@attributes" property has only the following properties
+ """
+ id
+ name
+ """
+ And the returned data "tracker.@attributes" property contains the following data
+ | property | value |
+ | id | 1 |
+ | name | Defect |
+ And the returned data "status" property is an array
+ And the returned data "status" property contains "1" items
+ And the returned data "status.@attributes" property is an array
+ And the returned data "status.@attributes" property has only the following properties
+ """
+ id
+ name
+ is_closed
+ """
+ And the returned data "status.@attributes" property contains the following data
+ | property | value |
+ | id | 1 |
+ | name | New |
+ | is_closed | false |
+ And the returned data "priority" property is an array
+ And the returned data "priority" property contains "1" items
+ And the returned data "priority.@attributes" property is an array
+ And the returned data "priority.@attributes" property has only the following properties
+ """
+ id
+ name
+ """
+ And the returned data "priority.@attributes" property contains the following data
+ | property | value |
+ | id | 1 |
+ | name | Normal |
+ And the returned data "author" property is an array
+ And the returned data "author" property contains "1" items
+ And the returned data "author.@attributes" property is an array
+ And the returned data "author.@attributes" property has only the following properties
+ """
+ id
+ name
+ """
+ And the returned data "author.@attributes" property contains the following data
+ | property | value |
+ | id | 1 |
+ | name | Redmine Admin |
+
+ @issue @error
+ Scenario: Showing a not existing issue
+ Given I have a "NativeCurlClient" client
+ When I show the issue with id "10"
+ Then the response has the status code "404"
+ And the response has the content type "application/json"
+ And the response has the content ""
+ And the returned data is false
diff --git a/tests/Behat/features/issue_relation.feature b/tests/Behat/features/issue_relation.feature
new file mode 100644
index 00000000..7b5db667
--- /dev/null
+++ b/tests/Behat/features/issue_relation.feature
@@ -0,0 +1,51 @@
+Feature: Interacting with the REST API for issue relations
+ In order to interact with REST API for issue relations
+ As a user
+ I want to make sure the Redmine server replies with the correct response
+
+ @issue_relation
+ Scenario: Creating an issue relation with miminal data
+ Given I have a "NativeCurlClient" client
+ And I have an issue status with the name "New"
+ And I have an issue priority with the name "Normal"
+ And I have a tracker with the name "Defect" and default status id "1"
+ And I create a project with name "Test Project" and identifier "test-project"
+ And I create an issue with the following data
+ | property | value |
+ | subject | first issue |
+ | project | Test Project |
+ | tracker | Defect |
+ | priority | Normal |
+ | status | New |
+ And I create an issue with the following data
+ | property | value |
+ | subject | second issue |
+ | project | Test Project |
+ | tracker | Defect |
+ | priority | Normal |
+ | status | New |
+ When I create an issue relation for issue id "1" with the following data
+ | property | value |
+ | issue_to_id | 2 |
+ Then the response has the status code "201"
+ And the response has the content type "application/json"
+ And the returned data has only the following properties
+ """
+ relation
+ """
+ And the returned data "relation" property is an array
+ And the returned data "relation" property has only the following properties
+ """
+ id
+ issue_id
+ issue_to_id
+ relation_type
+ delay
+ """
+ And the returned data "relation" property contains the following data
+ | property | value |
+ | id | 1 |
+ | issue_id | 1 |
+ | issue_to_id | 2 |
+ | relation_type | relates |
+ | delay | null |
diff --git a/tests/Behat/features/user.feature b/tests/Behat/features/user.feature
index a46619fc..fce3ee8b 100644
--- a/tests/Behat/features/user.feature
+++ b/tests/Behat/features/user.feature
@@ -3,6 +3,47 @@ Feature: Interacting with the REST API for users
As a user
I want to make sure the Redmine server replies with the correct response
+ @user
+ Scenario: Creating a user
+ Given I have a "NativeCurlClient" client
+ When I create a user with the following data
+ | property | value |
+ | login | username |
+ | firstname | first |
+ | lastname | last |
+ | mail | mail@example.com |
+ Then the response has the status code "201"
+ And the response has the content type "application/xml"
+ And the returned data is an instance of "SimpleXMLElement"
+ And the returned data has only the following properties
+ """
+ id
+ login
+ admin
+ firstname
+ lastname
+ mail
+ created_on
+ updated_on
+ last_login_on
+ passwd_changed_on
+ twofa_scheme
+ api_key
+ status
+ """
+ And the returned data has proterties with the following data
+ | property | value |
+ | id | 4 |
+ | login | username |
+ | admin | false |
+ | firstname | first |
+ | lastname | last |
+ | mail | mail@example.com |
+ | last_login_on | [] |
+ | passwd_changed_on | [] |
+ | twofa_scheme | [] |
+ | status | 1 |
+
@user
Scenario: Showing a user
Given I have a "NativeCurlClient" client
diff --git a/tests/Integration/GroupXmlTest.php b/tests/Integration/GroupXmlTest.php
index 6b64ce41..6ac92200 100644
--- a/tests/Integration/GroupXmlTest.php
+++ b/tests/Integration/GroupXmlTest.php
@@ -3,50 +3,10 @@
namespace Redmine\Tests\Integration;
use PHPUnit\Framework\TestCase;
-use Redmine\Exception\MissingParameterException;
use Redmine\Tests\Fixtures\MockClient;
class GroupXmlTest extends TestCase
{
- public function testCreateBlank()
- {
- /** @var \Redmine\Api\Group */
- $api = MockClient::create()->getApi('group');
- $this->assertInstanceOf('Redmine\Api\Group', $api);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
-
- $api->create();
- }
-
- public function testCreateComplex()
- {
- /** @var \Redmine\Api\Group */
- $api = MockClient::create()->getApi('group');
- $res = $api->create([
- 'name' => 'Developers',
- 'user_ids' => [3, 5],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/groups.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- Developers
-
- 3
- 5
-
-
- XML,
- $response['data']
- );
- }
-
public function testUpdateComplex()
{
/** @var \Redmine\Api\Group */
diff --git a/tests/Integration/IssueCategoryXmlTest.php b/tests/Integration/IssueCategoryXmlTest.php
index 80493131..355e401d 100644
--- a/tests/Integration/IssueCategoryXmlTest.php
+++ b/tests/Integration/IssueCategoryXmlTest.php
@@ -20,28 +20,6 @@ public function testCreateBlank()
$api->create('aProject');
}
- public function testCreateComplex()
- {
- /** @var \Redmine\Api\IssueCategory */
- $api = MockClient::create()->getApi('issue_category');
- $res = $api->create('otherProject', [
- 'name' => 'test category',
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/projects/otherProject/issue_categories.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- test category
-
- XML,
- $response['data']
- );
- }
-
public function testUpdate()
{
/** @var \Redmine\Api\IssueCategory */
diff --git a/tests/Integration/IssueXmlTest.php b/tests/Integration/IssueXmlTest.php
index e1de9248..ebe70756 100644
--- a/tests/Integration/IssueXmlTest.php
+++ b/tests/Integration/IssueXmlTest.php
@@ -7,171 +7,6 @@
class IssueXmlTest extends TestCase
{
- public function testCreateBlank()
- {
- /** @var \Redmine\Api\Issue */
- $api = MockClient::create()->getApi('issue');
- $this->assertInstanceOf('Redmine\Api\Issue', $api);
-
- $res = $api->create();
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/issues.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- XML,
- $response['data']
- );
- }
-
- public function testCreateComplexWithUpload()
- {
- /** @var \Redmine\Api\Issue */
- $api = MockClient::create()->getApi('issue');
- $res = $api->create([
- 'project_id' => 'myproject',
- 'subject' => 'A test issue',
- 'description' => 'Here goes the issue description',
- 'uploads' => [
- [
- 'token' => 'asdfasdfasdfasdf',
- 'filename' => 'MyFile.pdf',
- 'description' => 'MyFile is better then YourFile...',
- 'content_type' => 'application/pdf',
- ],
- ],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/issues.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- A test issue
- Here goes the issue description
- myproject
-
-
- asdfasdfasdfasdf
- MyFile.pdf
- MyFile is better then YourFile...
- application/pdf
-
-
-
- XML,
- $response['data']
- );
- }
-
- public function testCreateComplex()
- {
- /** @var \Redmine\Api\Issue */
- $api = MockClient::create()->getApi('issue');
- $res = $api->create([
- 'project_id' => 'test',
- 'subject' => 'test api (xml) 3',
- 'description' => 'test api',
- 'assigned_to_id' => 1,
- 'custom_fields' => [
- [
- 'id' => 2,
- 'name' => 'Issuer',
- 'value' => 'asdf',
- ],
- [
- 'id' => 5,
- 'name' => 'Phone',
- 'value' => '9939494',
- ],
- [
- 'id' => '8',
- 'name' => 'Email',
- 'value' => 'asdf@asdf.com',
- ],
- ],
- 'watcher_user_ids' => [],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/issues.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- test api (xml) 3
- test api
- test
- 1
-
- asdf
- 9939494
- asdf@asdf.com
-
-
- XML,
- $response['data']
- );
- }
-
- public function testCreateComplexWithLineBreakInDescription()
- {
- /** @var \Redmine\Api\Issue */
- $api = MockClient::create()->getApi('issue');
- $res = $api->create([
- 'project_id' => 'test',
- 'subject' => 'test api (xml) 3',
- 'description' => "line1\nline2",
- 'assigned_to_id' => 1,
- 'custom_fields' => [
- [
- 'id' => 2,
- 'name' => 'Issuer',
- 'value' => 'asdf',
- ],
- [
- 'id' => 5,
- 'name' => 'Phone',
- 'value' => '9939494',
- ],
- [
- 'id' => '8',
- 'name' => 'Email',
- 'value' => 'asdf@asdf.com',
- ],
- ],
- 'watcher_user_ids' => [],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/issues.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- test api (xml) 3
- line1
- line2
- test
- 1
-
- asdf
- 9939494
- asdf@asdf.com
-
-
- XML,
- $response['data']
- );
- }
-
public function testUpdateIssue()
{
/** @var \Redmine\Api\Issue */
diff --git a/tests/Integration/MembershipXmlTest.php b/tests/Integration/MembershipXmlTest.php
index e4fa1488..9eb35907 100644
--- a/tests/Integration/MembershipXmlTest.php
+++ b/tests/Integration/MembershipXmlTest.php
@@ -3,50 +3,10 @@
namespace Redmine\Tests\Integration;
use PHPUnit\Framework\TestCase;
-use Redmine\Exception\MissingParameterException;
use Redmine\Tests\Fixtures\MockClient;
class MembershipXmlTest extends TestCase
{
- public function testCreateBlank()
- {
- /** @var \Redmine\Api\Membership */
- $api = MockClient::create()->getApi('membership');
- $this->assertInstanceOf('Redmine\Api\Membership', $api);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `user_id`, `role_ids`');
-
- $api->create('aProject');
- }
-
- public function testCreateComplex()
- {
- /** @var \Redmine\Api\Membership */
- $api = MockClient::create()->getApi('membership');
- $res = $api->create('otherProject', [
- 'user_id' => 1,
- 'role_ids' => [1, 2],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/projects/otherProject/memberships.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- 1
-
- 1
- 2
-
-
- XML,
- $response['data']
- );
- }
-
public function testUpdate()
{
/** @var \Redmine\Api\Membership */
diff --git a/tests/Integration/ProjectXmlTest.php b/tests/Integration/ProjectXmlTest.php
index c0fc42b0..06ba06fe 100644
--- a/tests/Integration/ProjectXmlTest.php
+++ b/tests/Integration/ProjectXmlTest.php
@@ -8,91 +8,6 @@
class ProjectXmlTest extends TestCase
{
- public function testCreateBlank()
- {
- /** @var \Redmine\Api\Project */
- $api = MockClient::create()->getApi('project');
- $this->assertInstanceOf('Redmine\Api\Project', $api);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`, `identifier`');
-
- $api->create();
- }
-
- public function testCreateComplex()
- {
- /** @var \Redmine\Api\Project */
- $api = MockClient::create()->getApi('project');
- $res = $api->create([
- 'name' => 'some name',
- 'identifier' => 'the_identifier',
- 'custom_fields' => [
- [
- 'id' => 123,
- 'name' => 'cf_name',
- 'field_format' => 'string',
- 'value' => [1, 2, 3],
- ],
- ],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/projects.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- some name
- the_identifier
-
-
-
- 1
- 2
- 3
-
-
-
-
- XML,
- $response['data']
- );
- }
-
- public function testCreateComplexWithTrackerIds()
- {
- /** @var \Redmine\Api\Project */
- $api = MockClient::create()->getApi('project');
- $res = $api->create([
- 'name' => 'some name',
- 'identifier' => 'the_identifier',
- 'tracker_ids' => [
- 1, 2, 3,
- ],
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/projects.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- some name
- the_identifier
-
- 1
- 2
- 3
-
-
- XML,
- $response['data']
- );
- }
-
public function testUpdate()
{
/** @var \Redmine\Api\Project */
diff --git a/tests/Integration/UrlTest.php b/tests/Integration/UrlTest.php
index 34affe41..4c226947 100644
--- a/tests/Integration/UrlTest.php
+++ b/tests/Integration/UrlTest.php
@@ -15,12 +15,6 @@ public function testAttachment()
$this->assertEquals('/attachments/1.json', $res['path']);
$this->assertEquals('GET', $res['method']);
-
- $res = $api->upload('asdf');
- $res = json_decode($res, true);
-
- $this->assertEquals('/uploads.json', $res['path']);
- $this->assertEquals('POST', $res['method']);
}
public function testCustomFields()
@@ -37,13 +31,6 @@ public function testGroup()
{
/** @var \Redmine\Api\Group */
$api = MockClient::create()->getApi('group');
- $res = $api->create([
- 'name' => 'asdf',
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/groups.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->all();
@@ -61,12 +48,6 @@ public function testGroup()
$this->assertEquals('/groups/1.xml', $res['path']);
$this->assertEquals('DELETE', $res['method']);
- $res = $api->addUser(1, 1);
- $res = json_decode($res, true);
-
- $this->assertEquals('/groups/1/users.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
-
$res = $api->removeUser(1, 1);
$res = json_decode($res, true);
@@ -78,13 +59,6 @@ public function testIssue()
{
/** @var \Redmine\Api\Issue */
$api = MockClient::create()->getApi('issue');
- $res = $api->create([
- 'name' => 'asdf',
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/issues.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, [
'name' => 'asdf',
@@ -135,13 +109,6 @@ public function testIssueCategory()
{
/** @var \Redmine\Api\IssueCategory */
$api = MockClient::create()->getApi('issue_category');
- $res = $api->create('testProject', [
- 'name' => 'asdf',
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/projects/testProject/issue_categories.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, [
'name' => 'asdf',
@@ -217,14 +184,6 @@ public function testMembership()
{
/** @var \Redmine\Api\Membership */
$api = MockClient::create()->getApi('membership');
- $res = $api->create('testProject', [
- 'user_id' => 1,
- 'role_ids' => [1],
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/projects/testProject/memberships.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, [
'user_id' => 1,
@@ -266,14 +225,6 @@ public function testProject()
{
/** @var \Redmine\Api\Project */
$api = MockClient::create()->getApi('project');
- $res = $api->create([
- 'name' => 'asdf',
- 'identifier' => 'asdf',
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/projects.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, [
'name' => 'asdf',
@@ -329,14 +280,6 @@ public function testTimeEntry()
{
/** @var \Redmine\Api\TimeEntry */
$api = MockClient::create()->getApi('time_entry');
- $res = $api->create([
- 'issue_id' => 1,
- 'hours' => 12,
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/time_entries.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, []);
$res = json_decode($res, true);
@@ -399,16 +342,6 @@ public function testUser()
{
/** @var \Redmine\Api\User */
$api = MockClient::create()->getApi('user');
- $res = $api->create([
- 'login' => 'asdf',
- 'lastname' => 'asdf',
- 'firstname' => 'asdf',
- 'mail' => 'asdf',
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/users.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, []);
$res = json_decode($res, true);
@@ -452,13 +385,6 @@ public function testVersion()
{
/** @var \Redmine\Api\Version */
$api = MockClient::create()->getApi('version');
- $res = $api->create('testProject', [
- 'name' => 'asdf',
- ]);
- $res = json_decode($res, true);
-
- $this->assertEquals('/projects/testProject/versions.xml', $res['path']);
- $this->assertEquals('POST', $res['method']);
$res = $api->update(1, []);
$res = json_decode($res, true);
diff --git a/tests/Integration/UserXmlTest.php b/tests/Integration/UserXmlTest.php
index 38de230b..9c817b0f 100644
--- a/tests/Integration/UserXmlTest.php
+++ b/tests/Integration/UserXmlTest.php
@@ -20,34 +20,6 @@ public function testCreateBlank()
$api->create();
}
- public function testCreateComplex()
- {
- /** @var \Redmine\Api\User */
- $api = MockClient::create()->getApi('user');
- $res = $api->create([
- 'login' => 'test',
- 'firstname' => 'test',
- 'lastname' => 'test',
- 'mail' => 'test@example.com',
- ]);
- $response = json_decode($res, true);
-
- $this->assertEquals('POST', $response['method']);
- $this->assertEquals('/users.xml', $response['path']);
- $this->assertXmlStringEqualsXmlString(
- <<< XML
-
-
- test
- test
- test
- test@example.com
-
- XML,
- $response['data']
- );
- }
-
public function testUpdate()
{
/** @var \Redmine\Api\User */
diff --git a/tests/Unit/Api/AbstractApiTest.php b/tests/Unit/Api/AbstractApiTest.php
index 07302875..39a473c7 100644
--- a/tests/Unit/Api/AbstractApiTest.php
+++ b/tests/Unit/Api/AbstractApiTest.php
@@ -58,7 +58,12 @@ public function testGetTriggersDeprecationWarning()
{
$client = $this->createMock(HttpClient::class);
- $api = new class ($client) extends AbstractApi {};
+ $api = new class ($client) extends AbstractApi {
+ public function runGet($path)
+ {
+ return $this->get($path);
+ }
+ };
// PHPUnit 10 compatible way to test trigger_error().
set_error_handler(
@@ -74,10 +79,7 @@ function ($errno, $errstr): bool {
E_USER_DEPRECATED
);
- $method = new ReflectionMethod($api, 'get');
- $method->setAccessible(true);
-
- $method->invoke($api, '/path.json');
+ $api->runGet('/path.json');
}
/**
@@ -92,6 +94,37 @@ public function testGetLastResponseWithHttpClientWorks()
$this->assertInstanceOf(Response::class, $api->getLastResponse());
}
+ /**
+ * @covers ::post
+ */
+ public function testPostTriggersDeprecationWarning()
+ {
+ $client = $this->createMock(HttpClient::class);
+
+ $api = new class ($client) extends AbstractApi {
+ public function runPost($path, $data)
+ {
+ return $this->post($path, $data);
+ }
+ };
+
+ // PHPUnit 10 compatible way to test trigger_error().
+ set_error_handler(
+ function ($errno, $errstr): bool {
+ $this->assertSame(
+ '`Redmine\Api\AbstractApi::post()` is deprecated since v2.6.0, use `\Redmine\Http\HttpClient::request()` instead.',
+ $errstr
+ );
+
+ restore_error_handler();
+ return true;
+ },
+ E_USER_DEPRECATED
+ );
+
+ $api->runPost('/path.json', 'data');
+ }
+
/**
* @test
* @dataProvider getIsNotNullReturnsCorrectBooleanData
diff --git a/tests/Unit/Api/Attachment/UploadTest.php b/tests/Unit/Api/Attachment/UploadTest.php
new file mode 100644
index 00000000..f7eabdaf
--- /dev/null
+++ b/tests/Unit/Api/Attachment/UploadTest.php
@@ -0,0 +1,84 @@
+assertSame($expectedReturn, $api->upload($attachment, $params));
+ }
+
+ public static function getUploadData(): array
+ {
+ return [
+ 'test attachment without params' => [
+ 'attachment-content',
+ [],
+ 'attachment-content',
+ '/uploads.json',
+ 201,
+ '{}',
+ '{}',
+ ],
+ 'test attachment returns empty string' => [
+ 'attachment-content',
+ [],
+ 'attachment-content',
+ '/uploads.json',
+ 201,
+ '',
+ '',
+ ],
+ 'test attachment with params' => [
+ 'attachment-content',
+ [
+ 'filename' => 'testfile.txt'
+ ],
+ 'attachment-content',
+ '/uploads.json?filename=testfile.txt',
+ 201,
+ '{"upload":{}}',
+ '{"upload":{}}',
+ ],
+ 'test attachment with filepath' => [
+ '/path/to/testfile_01.txt',
+ [
+ 'filename' => 'testfile.txt'
+ ],
+ '/path/to/testfile_01.txt',
+ '/uploads.json?filename=testfile.txt',
+ 201,
+ '{"upload":{}}',
+ '{"upload":{}}',
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/AttachmentTest.php b/tests/Unit/Api/AttachmentTest.php
index d37f2c9e..67171210 100644
--- a/tests/Unit/Api/AttachmentTest.php
+++ b/tests/Unit/Api/AttachmentTest.php
@@ -57,37 +57,4 @@ public static function responseCodeProvider(): array
[500, true],
];
}
-
- /**
- * Test upload().
- *
- * @covers ::post
- * @covers ::upload
- * @test
- */
- public function testUploadReturnsClientPostResponse()
- {
- // Test values
- $postRequestData = 'API Response';
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- $this->stringStartsWith('/uploads.json'),
- $this->equalTo($postRequestData)
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Attachment($client);
-
- // Perform the tests
- $this->assertSame($response, $api->upload($postRequestData));
- }
}
diff --git a/tests/Unit/Api/Group/AddUserTest.php b/tests/Unit/Api/Group/AddUserTest.php
new file mode 100644
index 00000000..175c6a05
--- /dev/null
+++ b/tests/Unit/Api/Group/AddUserTest.php
@@ -0,0 +1,83 @@
+addUser($groupId, $userId);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getAddUserData(): array
+ {
+ return [
+ 'test with integers' => [
+ 25,
+ 5,
+ '/groups/25/users.xml',
+ <<
+ 5
+ XML,
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testAddUserReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/groups/1/users.xml',
+ 'application/xml',
+ '2',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Group($client);
+
+ // Perform the tests
+ $return = $api->addUser(1, 2);
+
+ $this->assertSame('', $return);
+ }
+}
diff --git a/tests/Unit/Api/Group/CreateTest.php b/tests/Unit/Api/Group/CreateTest.php
index 6cc1ef3c..b99238f4 100644
--- a/tests/Unit/Api/Group/CreateTest.php
+++ b/tests/Unit/Api/Group/CreateTest.php
@@ -16,18 +16,21 @@
*/
class CreateTest extends TestCase
{
- public function testCreateWithNameCreatesGroup()
+ /**
+ * @dataProvider getCreateData
+ */
+ public function testCreateReturnsCorrectResponse($parameters, $expectedPath, $expectedBody, $responseCode, $response)
{
$client = AssertingHttpClient::create(
$this,
[
'POST',
- '/groups.xml',
+ $expectedPath,
'application/xml',
- 'Group Name',
- 200,
+ $expectedBody,
+ $responseCode,
'application/xml',
- ''
+ $response
]
);
@@ -35,44 +38,75 @@ public function testCreateWithNameCreatesGroup()
$api = new Group($client);
// Perform the tests
- $xmlElement = $api->create(['name' => 'Group Name']);
+ $return = $api->create($parameters);
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
}
- public function testCreateWithNameAndUserIdsCreatesGroup()
+ public static function getCreateData(): array
{
- $client = AssertingHttpClient::create(
- $this,
- [
- 'POST',
+ return [
+ 'test with minimal parameters' => [
+ [
+ 'name' => 'Group Name',
+ ],
'/groups.xml',
- 'application/xml',
- 'Group Name123',
- 200,
- 'application/xml',
- ''
- ]
- );
-
- // Create the object under test
- $api = new Group($client);
-
- // Perform the tests
- $xmlElement = $api->create(['name' => 'Group Name', 'user_ids' => [1, 2, 3]]);
-
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
+ <<
+
+ Group Name
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with user ids' => [
+ [
+ 'name' => 'Group Name',
+ 'user_ids' => [1, 2, 3],
+ ],
+ '/groups.xml',
+ <<
+
+ Group Name
+
+ 1
+ 2
+ 3
+
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with custom fields' => [
+ [
+ 'name' => 'Group Name',
+ 'custom_fields' => [
+ ['id' => 1, 'value' => 5],
+ ],
+ ],
+ '/groups.xml',
+ <<
+
+ Group Name
+
+
+ 5
+
+
+
+ XML,
+ 201,
+ '',
+ ],
+ ];
}
- public function testCreateWithNameAndCustomFieldsCreatesGroup()
+ public function testCreateReturnsEmptyString()
{
$client = AssertingHttpClient::create(
$this,
@@ -80,10 +114,10 @@ public function testCreateWithNameAndCustomFieldsCreatesGroup()
'POST',
'/groups.xml',
'application/xml',
- 'Group Name5',
- 200,
- 'application/xml',
- ''
+ 'Group Name',
+ 500,
+ '',
+ ''
]
);
@@ -91,18 +125,9 @@ public function testCreateWithNameAndCustomFieldsCreatesGroup()
$api = new Group($client);
// Perform the tests
- $xmlElement = $api->create([
- 'name' => 'Group Name',
- 'custom_fields' => [
- ['id' => 1, 'value' => 5],
- ],
- ]);
+ $return = $api->create(['name' => 'Group Name']);
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
+ $this->assertSame('', $return);
}
public function testCreateThrowsExceptionIfNameIsMissing()
diff --git a/tests/Unit/Api/GroupTest.php b/tests/Unit/Api/GroupTest.php
index 84bf87c9..d4acdde6 100644
--- a/tests/Unit/Api/GroupTest.php
+++ b/tests/Unit/Api/GroupTest.php
@@ -272,44 +272,6 @@ public function testRemoveCallsDelete()
$this->assertSame($expectedReturn, $api->remove(5));
}
- /**
- * Test removeUser().
- *
- * @covers ::addUser
- * @covers ::post
- * @test
- */
- public function testAddUserCallsPost()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- $this->logicalAnd(
- $this->stringStartsWith('/groups/5/users'),
- $this->logicalXor(
- $this->stringEndsWith('.json'),
- $this->stringEndsWith('.xml')
- )
- ),
- $this->stringContains('10')
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Group($client);
-
- // Perform the tests
- $this->assertSame($response, $api->addUser(5, 10));
- }
-
/**
* Test removeUser().
*
diff --git a/tests/Unit/Api/Issue/AddWatcherTest.php b/tests/Unit/Api/Issue/AddWatcherTest.php
new file mode 100644
index 00000000..9e1d6492
--- /dev/null
+++ b/tests/Unit/Api/Issue/AddWatcherTest.php
@@ -0,0 +1,83 @@
+addWatcher($issueId, $watcherUserId);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getAddWatcherData(): array
+ {
+ return [
+ 'test with integers' => [
+ 25,
+ 5,
+ '/issues/25/watchers.xml',
+ <<
+ 5
+ XML,
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testAddWatcherReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/issues/1/watchers.xml',
+ 'application/xml',
+ '2',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $return = $api->addWatcher(1, 2);
+
+ $this->assertSame('', $return);
+ }
+}
diff --git a/tests/Unit/Api/Issue/CreateTest.php b/tests/Unit/Api/Issue/CreateTest.php
new file mode 100644
index 00000000..1334a8ea
--- /dev/null
+++ b/tests/Unit/Api/Issue/CreateTest.php
@@ -0,0 +1,564 @@
+create($parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test without parameters' => [
+ [],
+ '/issues.xml',
+ <<
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with minimal parameters' => [
+ [
+ 'subject' => 'Issue subject',
+ 'project_id' => 1,
+ 'tracker_id' => 2,
+ 'priority_id' => 3,
+ 'status_id' => 4,
+ ],
+ '/issues.xml',
+ <<
+
+ Issue subject
+ 1
+ 3
+ 4
+ 2
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with line break in description' => [
+ [
+ 'subject' => 'Issue subject',
+ 'description' => "line1\nline2",
+ 'project_id' => 1,
+ 'tracker_id' => 2,
+ 'priority_id' => 3,
+ 'status_id' => 4,
+ ],
+ '/issues.xml',
+ <<
+
+ Issue subject
+ line1
+ line2
+ 1
+ 3
+ 4
+ 2
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with with some xml entities' => [
+ [
+ 'subject' => 'Issue subject with some xml entities: & < > " \' ',
+ 'project_id' => 1,
+ 'tracker_id' => 2,
+ 'priority_id' => 3,
+ 'status_id' => 4,
+ 'description' => 'Description with some xml entities: & < > " \' ',
+ ],
+ '/issues.xml',
+ <<
+
+ Issue subject with some xml entities: & < > " '
+ Description with some xml entities: & < > " '
+ 1
+ 3
+ 4
+ 2
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with all possible parameters' => [
+ [
+ 'project_id' => 1,
+ 'tracker_id' => 2,
+ 'status_id' => 3,
+ 'priority_id' => 4,
+ 'subject' => 'Issue subject',
+ 'description' => 'Issue description',
+ 'category_id' => 5,
+ 'fixed_version_id' => 6,
+ 'assigned_to_id' => 7,
+ 'parent_issue_id' => 8,
+ 'custom_fields' => [
+ [
+ 'id' => 9,
+ 'name' => 'Custom field 9',
+ 'value' => 'value of cf9',
+ ],
+ [
+ 'id' => 123,
+ 'name' => 'cf_name',
+ 'field_format' => 'string',
+ 'value' => [1, 2, 3],
+ ],
+ [
+ 'id' => 321,
+ 'value' => 'https://example.com/?one=first&two=second',
+ ],
+ ],
+ 'watcher_user_ids' => [10, 11],
+ 'is_private' => false,
+ 'estimated_hours' => 2.5,
+ 'author_id' => 12,
+ 'due_date' => '2024-12-31',
+ 'start_date' => '2024-01-01',
+ 'uploads' => [
+ [
+ 'token' => '1.first-token',
+ 'filename' => 'SomeRandomFile.txt',
+ 'description' => 'Simple description',
+ 'content_type' => 'text/plain',
+ ],
+ [
+ 'token' => '2.second-token',
+ 'filename' => 'An-Other-File.css',
+ 'content_type' => 'text/css',
+ ],
+ ],
+ ],
+ '/issues.xml',
+ <<
+
+ Issue subject
+ Issue description
+ 1
+ 5
+ 4
+ 3
+ 2
+ 7
+ 12
+ 2024-12-31
+ 2024-01-01
+
+ 10
+ 11
+
+ 6
+ 8
+
+
+ value of cf9
+
+
+
+ 1
+ 2
+ 3
+
+
+
+ https://example.com/?one=first&two=second
+
+
+ 2.5
+
+
+ 1.first-token
+ SomeRandomFile.txt
+ Simple description
+ text/plain
+
+
+ 2.second-token
+ An-Other-File.css
+ text/css
+
+
+
+ XML,
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ '',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $return = $api->create([]);
+
+ $this->assertSame('', $return);
+ }
+
+ /**
+ * @covers \Redmine\Api\Issue::cleanParams
+ * @covers \Redmine\Api\Issue::getIssueStatusApi
+ */
+ public function testCreateWithHttpClientRetrievesIssueStatusId()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'GET',
+ '/issue_statuses.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"issue_statuses":[{"name":"Status Name","id":123}]}'
+ ],
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ '123',
+ 200,
+ 'application/xml',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $xmlElement = $api->create(['status' => 'Status Name']);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
+ $this->assertXmlStringEqualsXmlString(
+ '',
+ $xmlElement->asXml(),
+ );
+ }
+
+ /**
+ * @covers \Redmine\Api\Issue::cleanParams
+ * @covers \Redmine\Api\Issue::getProjectApi
+ */
+ public function testCreateWithHttpClientRetrievesProjectId()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'GET',
+ '/projects.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"projects":[{"name":"Project Name","id":3}]}'
+ ],
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ '3',
+ 200,
+ 'application/xml',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $xmlElement = $api->create(['project' => 'Project Name']);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
+ $this->assertXmlStringEqualsXmlString(
+ '',
+ $xmlElement->asXml(),
+ );
+ }
+
+ /**
+ * @covers \Redmine\Api\Issue::cleanParams
+ * @covers \Redmine\Api\Issue::getIssueCategoryApi
+ */
+ public function testCreateWithHttpClientRetrievesIssueCategoryId()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'GET',
+ '/projects/3/issue_categories.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"issue_categories":[{"name":"Category Name","id":45}]}'
+ ],
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ '345',
+ 200,
+ 'application/xml',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $xmlElement = $api->create(['project_id' => 3, 'category' => 'Category Name']);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
+ $this->assertXmlStringEqualsXmlString(
+ '',
+ $xmlElement->asXml(),
+ );
+ }
+
+ /**
+ * @covers \Redmine\Api\Issue::cleanParams
+ * @covers \Redmine\Api\Issue::getTrackerApi
+ */
+ public function testCreateWithHttpClientRetrievesTrackerId()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'GET',
+ '/trackers.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"trackers":[{"name":"Tracker Name","id":9}]}'
+ ],
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ '9',
+ 200,
+ 'application/xml',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $xmlElement = $api->create(['tracker' => 'Tracker Name']);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
+ $this->assertXmlStringEqualsXmlString(
+ '',
+ $xmlElement->asXml(),
+ );
+ }
+
+ /**
+ * @covers \Redmine\Api\Issue::cleanParams
+ * @covers \Redmine\Api\Issue::getUserApi
+ */
+ public function testCreateWithHttpClientRetrievesUserId()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'GET',
+ '/users.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}'
+ ],
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ '65',
+ 200,
+ 'application/xml',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $xmlElement = $api->create(['assigned_to' => 'Assigned to User Name', 'author' => 'Author Name']);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
+ $this->assertXmlStringEqualsXmlString(
+ '',
+ $xmlElement->asXml(),
+ );
+ }
+
+ /**
+ * Test cleanParams().
+ *
+ * @covers \Redmine\Api\Issue::cleanParams
+ * @covers \Redmine\Api\Issue::getIssueCategoryApi
+ * @covers \Redmine\Api\Issue::getIssueStatusApi
+ * @covers \Redmine\Api\Issue::getProjectApi
+ * @covers \Redmine\Api\Issue::getTrackerApi
+ * @covers \Redmine\Api\Issue::getUserApi
+ */
+ public function testCreateWithClientCleansParameters()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'GET',
+ '/projects.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"projects":[{"name":"Project Name","id":3}]}'
+ ],
+ [
+ 'GET',
+ '/projects/3/issue_categories.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"issue_categories":[{"name":"Category Name","id":45}]}'
+ ],
+ [
+ 'GET',
+ '/issue_statuses.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"issue_statuses":[{"name":"Status Name","id":123}]}'
+ ],
+ [
+ 'GET',
+ '/trackers.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"trackers":[{"name":"Tracker Name","id":9}]}'
+ ],
+ [
+ 'GET',
+ '/users.json',
+ 'application/json',
+ '',
+ 200,
+ 'application/json',
+ '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}'
+ ],
+ [
+ 'POST',
+ '/issues.xml',
+ 'application/xml',
+ <<
+
+ 3
+ 45
+ 123
+ 9
+ 6
+ 5
+
+ XML,
+ 200,
+ 'application/xml',
+ ''
+ ]
+ );
+
+ $parameters = [
+ 'project' => 'Project Name',
+ 'category' => 'Category Name',
+ 'status' => 'Status Name',
+ 'tracker' => 'Tracker Name',
+ 'assigned_to' => 'Assigned to User Name',
+ 'author' => 'Author Name',
+ ];
+
+ // Create the object under test
+ $api = new Issue($client);
+
+ // Perform the tests
+ $xmlElement = $api->create($parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
+ $this->assertXmlStringEqualsXmlString(
+ '',
+ $xmlElement->asXml(),
+ );
+ }
+}
diff --git a/tests/Unit/Api/IssueCategory/CreateTest.php b/tests/Unit/Api/IssueCategory/CreateTest.php
new file mode 100644
index 00000000..588c3b5f
--- /dev/null
+++ b/tests/Unit/Api/IssueCategory/CreateTest.php
@@ -0,0 +1,150 @@
+create($identifier, $parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with minimal parameters' => [
+ 5,
+ ['name' => 'Test Category'],
+ '/projects/5/issue_categories.xml',
+ 'Test Category',
+ 201,
+ '',
+ ],
+ 'test with minimal parameters and project identifier as string' => [
+ 'test-project',
+ ['name' => 'Test Category'],
+ '/projects/test-project/issue_categories.xml',
+ 'Test Category',
+ 201,
+ '',
+ ],
+ 'test with all parameters' => [
+ 5,
+ ['name' => 'Test Category', 'assigned_to_id' => 2],
+ '/projects/5/issue_categories.xml',
+ 'Test Category2',
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/projects/5/issue_categories.xml',
+ 'application/xml',
+ 'Test Category',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new IssueCategory($client);
+
+ // Perform the tests
+ $return = $api->create(5, ['name' => 'Test Category']);
+
+ $this->assertSame('', $return);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new IssueCategory($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `name');
+
+ // Perform the tests
+ $api->create(5);
+ }
+
+ /**
+ * @dataProvider incompleteCreateParameterProvider
+ */
+ public function testCreateThrowsExceptionIfMandatoyParametersAreMissing($parameters)
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new IssueCategory($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `name');
+
+ // Perform the tests
+ $api->create('5', $parameters);
+ }
+
+ /**
+ * Provider for incomplete create parameters.
+ *
+ * @return array[]
+ */
+ public static function incompleteCreateParameterProvider(): array
+ {
+ return [
+ 'missing all mandatory parameters' => [
+ [],
+ ],
+ 'missing `name` parameter' => [
+ [
+ 'assigned_to_id' => 2,
+ ],
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/IssueCategoryTest.php b/tests/Unit/Api/IssueCategoryTest.php
index 36caaec4..00b854ba 100644
--- a/tests/Unit/Api/IssueCategoryTest.php
+++ b/tests/Unit/Api/IssueCategoryTest.php
@@ -341,75 +341,6 @@ public function testGetIdByNameMakesGetRequest()
$this->assertSame(5, $api->getIdByName(5, 'IssueCategory 5'));
}
- /**
- * Test create().
- *
- * @covers ::post
- * @covers ::create
- * @test
- */
- public function testCreateThrowsExceptionIfNameIsMissing()
- {
- // Test values
- $parameters = [
- 'name' => null,
- 'assigned_to_id' => 2,
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new IssueCategory($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
-
- // Perform the tests
- $api->create(5, $parameters);
- }
-
- /**
- * Test create().
- *
- * @covers ::post
- * @covers ::create
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'name' => 'Test Category',
- 'assigned_to_id' => 2,
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects/5/issue_categories.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('Test Category'),
- $this->stringContains('2')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new IssueCategory($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create(5, $parameters));
- }
-
/**
* Test update().
*
diff --git a/tests/Unit/Api/IssueRelation/CreateTest.php b/tests/Unit/Api/IssueRelation/CreateTest.php
new file mode 100644
index 00000000..ecbf35a8
--- /dev/null
+++ b/tests/Unit/Api/IssueRelation/CreateTest.php
@@ -0,0 +1,136 @@
+create($issueId, $parameters);
+
+ $this->assertIsArray($return);
+ $this->assertSame($expectedReturn, $return);
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with minimal parameters' => [
+ 5,
+ ['issue_to_id' => 10],
+ '/issues/5/relations.json',
+ '{"relation":{"issue_to_id":10,"relation_type":"relates"}}',
+ 201,
+ '{"relation":{}}',
+ ['relation' => []],
+ ],
+ ];
+ }
+
+ public function testCreateThrowsExceptionIfResponseContainsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/issues/5/relations.json',
+ 'application/json',
+ '{"relation":{"issue_to_id":10,"relation_type":"relates"}}',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new IssueRelation($client);
+
+ $this->expectException(SerializerException::class);
+ $this->expectExceptionMessage('Catched error "Syntax error" while decoding JSON: ');
+
+ // Perform the tests
+ $api->create(5, ['issue_to_id' => 10]);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new IssueRelation($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `issue_to_id`');
+
+ // Perform the tests
+ $api->create(5);
+ }
+
+ /**
+ * @dataProvider incompleteCreateParameterProvider
+ */
+ public function testCreateThrowsExceptionIfMandatoyParametersAreMissing($parameters)
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new IssueRelation($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `issue_to_id`');
+
+ // Perform the tests
+ $api->create(5, $parameters);
+ }
+
+ /**
+ * Provider for incomplete create parameters.
+ *
+ * @return array[]
+ */
+ public static function incompleteCreateParameterProvider(): array
+ {
+ return [
+ 'missing all mandatory parameters' => [
+ [],
+ ],
+ 'missing `issue_to_id` parameter' => [
+ [
+ 'relation_type' => 'relates',
+ ],
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/IssueRelation/ShowTest.php b/tests/Unit/Api/IssueRelation/ShowTest.php
index e806c7db..144ac1e2 100644
--- a/tests/Unit/Api/IssueRelation/ShowTest.php
+++ b/tests/Unit/Api/IssueRelation/ShowTest.php
@@ -41,6 +41,7 @@ public static function getShowData(): array
return [
'array response with integer id' => [5, '/relations/5.json', '{"relation":{"child":[5,2,3]}}', ['child' => [5, 2, 3]]],
'array response with string id' => ['5', '/relations/5.json', '{"relation":{"child":[5,2,3]}}', ['child' => [5, 2, 3]]],
+ 'array response on object without relation key error' => [5, '/relations/5.json', '{}', []],
'array response on string error' => [5, '/relations/5.json', 'string', []],
'array response on empty error' => [5, '/relations/5.json', '', []],
];
diff --git a/tests/Unit/Api/IssueRelationTest.php b/tests/Unit/Api/IssueRelationTest.php
index bc939f02..ba97896c 100644
--- a/tests/Unit/Api/IssueRelationTest.php
+++ b/tests/Unit/Api/IssueRelationTest.php
@@ -156,45 +156,4 @@ public function testRemoveCallsDelete()
// Perform the tests
$this->assertSame($expectedReturn, $api->remove(5));
}
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $parameters = [];
- $response = '{"test":"response"}';
- $expectedReturn = ['test' => 'response'];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues/1/relations.json',
- json_encode([
- 'relation' => [
- 'relation_type' => 'relates',
- ],
- ])
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
- $client->expects($this->exactly(1))
- ->method('getLastResponseContentType')
- ->willReturn('application/json');
-
- // Create the object under test
- $api = new IssueRelation($client);
-
- // Perform the tests
- $this->assertSame($expectedReturn, $api->create(1, $parameters));
- }
}
diff --git a/tests/Unit/Api/IssueTest.php b/tests/Unit/Api/IssueTest.php
index 034cca23..a278d71e 100644
--- a/tests/Unit/Api/IssueTest.php
+++ b/tests/Unit/Api/IssueTest.php
@@ -226,37 +226,6 @@ public function testAttachCallsPut()
$this->assertSame($response, $api->attach(5, $attachment));
}
- /**
- * Test addWatcher().
- *
- * @covers ::addWatcher
- * @test
- */
- public function testAddWatcherCallsPost()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- $this->stringStartsWith('/issues/5/watchers.xml'),
- $this->stringEndsWith('10' . "\n")
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $this->assertSame($response, $api->addWatcher(5, 10));
- }
-
/**
* Test removeWatcher().
*
@@ -288,40 +257,7 @@ public function testRemoveWatcherCallsPost()
}
/**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues.xml',
- '' . "\n" . '' . "\n"
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test cleanParams().
+ * Test cleanParams() with Client for BC
*
* @covers ::create
* @covers ::cleanParams
@@ -335,7 +271,7 @@ public function testCreateCallsPost()
public function testCreateWithClientCleansParameters()
{
// Test values
- $response = 'API Response';
+ $response = '';
$parameters = [
'project' => 'Project Name',
'category' => 'Category Name',
@@ -391,281 +327,15 @@ public function testCreateWithClientCleansParameters()
$client->expects($this->exactly(1))
->method('getLastResponseBody')
->willReturn($response);
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * @covers ::create
- * @covers ::cleanParams
- * @covers ::getIssueStatusApi
- * @test
- */
- public function testCreateWithHttpClientRetrievesIssueStatusId()
- {
- $client = AssertingHttpClient::create(
- $this,
- [
- 'GET',
- '/issue_statuses.json',
- 'application/json',
- '',
- 200,
- 'application/json',
- '{"issue_statuses":[{"name":"Status Name","id":123}]}'
- ],
- [
- 'POST',
- '/issues.xml',
- 'application/xml',
- '123',
- 200,
- 'application/xml',
- ''
- ]
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- $xmlElement = $api->create(['status' => 'Status Name']);
-
- // Perform the tests
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
- }
-
- /**
- * @covers ::create
- * @covers ::cleanParams
- * @covers ::getProjectApi
- * @test
- */
- public function testCreateWithHttpClientRetrievesProjectId()
- {
- $client = AssertingHttpClient::create(
- $this,
- [
- 'GET',
- '/projects.json',
- 'application/json',
- '',
- 200,
- 'application/json',
- '{"projects":[{"name":"Project Name","id":3}]}'
- ],
- [
- 'POST',
- '/issues.xml',
- 'application/xml',
- '3',
- 200,
- 'application/xml',
- ''
- ]
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- $xmlElement = $api->create(['project' => 'Project Name']);
-
- // Perform the tests
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
- }
-
- /**
- * @covers ::create
- * @covers ::cleanParams
- * @covers ::getIssueCategoryApi
- * @test
- */
- public function testCreateWithHttpClientRetrievesIssueCategoryId()
- {
- $client = AssertingHttpClient::create(
- $this,
- [
- 'GET',
- '/projects/3/issue_categories.json',
- 'application/json',
- '',
- 200,
- 'application/json',
- '{"issue_categories":[{"name":"Category Name","id":45}]}'
- ],
- [
- 'POST',
- '/issues.xml',
- 'application/xml',
- '345',
- 200,
- 'application/xml',
- ''
- ]
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- $xmlElement = $api->create(['project_id' => 3, 'category' => 'Category Name']);
-
- // Perform the tests
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
- }
-
- /**
- * @covers ::create
- * @covers ::cleanParams
- * @covers ::getTrackerApi
- * @test
- */
- public function testCreateWithHttpClientRetrievesTrackerId()
- {
- $client = AssertingHttpClient::create(
- $this,
- [
- 'GET',
- '/trackers.json',
- 'application/json',
- '',
- 200,
- 'application/json',
- '{"trackers":[{"name":"Tracker Name","id":9}]}'
- ],
- [
- 'POST',
- '/issues.xml',
- 'application/xml',
- '9',
- 200,
- 'application/xml',
- ''
- ]
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- $xmlElement = $api->create(['tracker' => 'Tracker Name']);
-
- // Perform the tests
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
- }
-
- /**
- * @covers ::create
- * @covers ::cleanParams
- * @covers ::getUserApi
- * @test
- */
- public function testCreateWithHttpClientRetrievesUserId()
- {
- $client = AssertingHttpClient::create(
- $this,
- [
- 'GET',
- '/users.json',
- 'application/json',
- '',
- 200,
- 'application/json',
- '{"users":[{"login":"Author Name","id":5},{"login":"Assigned to User Name","id":6}]}'
- ],
- [
- 'POST',
- '/issues.xml',
- 'application/xml',
- '65',
- 200,
- 'application/xml',
- ''
- ]
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- $xmlElement = $api->create(['assigned_to' => 'Assigned to User Name', 'author' => 'Author Name']);
-
- // Perform the tests
- $this->assertInstanceOf(SimpleXMLElement::class, $xmlElement);
- $this->assertXmlStringEqualsXmlString(
- '',
- $xmlElement->asXml(),
- );
- }
-
- /**
- * Test create() and buildXML().
- *
- * @covers ::create
- * @covers ::attachCustomFieldXML
- * @test
- */
- public function testCreateBuildsXmlForCustomFields()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'custom_fields' => [
- [
- 'id' => 123,
- 'name' => 'cf_name',
- 'field_format' => 'string',
- 'value' => [1, 2, 3],
- ],
- ],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues.xml',
- $this->logicalAnd(
- $this->stringStartsWith(''),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains('1'),
- $this->stringContains('2'),
- $this->stringContains('3'),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringEndsWith('' . "\n")
- )
- )
- ->willReturn(true);
$client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
+ ->method('getLastResponseContentType')
+ ->willReturn('application/xml');
// Create the object under test
$api = new Issue($client);
// Perform the tests
- $this->assertSame($response, $api->create($parameters));
+ $this->assertXmlStringEqualsXmlString($response, $api->create($parameters)->asXML());
}
/**
@@ -901,203 +571,6 @@ public function testAddNoteToIssue()
$this->assertSame($response, $api->addNoteToIssue(5, 'Note content'));
}
- /**
- * Test buildXML().
- *
- * @test
- */
- public function testBuildXmlWithCustomFields()
- {
- // Test values
- $parameters = [
- 'custom_fields' => [
- ['id' => 225, 'value' => 'One Custom Field'],
- ['id' => 25, 'value' => 'Second Custom Field'],
- ['id' => 321, 'value' => 'http://test.local/?one=first&two=second'],
- ],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains('One Custom Field'),
- $this->stringContains('Second Custom Field'),
- $this->stringContains('http://test.local/?one=first&two=second')
- )
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $api->create($parameters);
- }
-
- /**
- * Test buildXML().
- *
- * @test
- */
- public function testBuildXmlWithWatchers()
- {
- // Test values
- $parameters = [
- 'watcher_user_ids' => [5, 25],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains('5'),
- $this->stringContains('25')
- )
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $api->create($parameters);
- }
-
- /**
- * Test buildXML().
- *
- * @test
- */
- public function testBuildXmlWithUploads()
- {
- // Test values
- $parameters = [
- 'uploads' => [
- [
- 'token' => 'first-token',
- 'filename' => 'SomeRandomFile.txt',
- 'description' => 'Simple description',
- 'content_type' => 'text/plain',
- ],
- [
- 'token' => 'second-token',
- 'filename' => 'An-Other-File.css',
- 'content_type' => 'text/css',
- ],
- ],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains(
- ''
- . 'first-token'
- . 'SomeRandomFile.txt'
- . 'Simple description'
- . 'text/plain'
- . ''
- ),
- $this->stringContains(
- ''
- . 'second-token'
- . 'An-Other-File.css'
- . 'text/css'
- . ''
- )
- )
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $api->create($parameters);
- }
-
- /**
- * Test buildXML().
- *
- * @test
- */
- public function testBuildXmlWithWatcherAndUploadAndCustomFieldAndStandard()
- {
- // Test values
- $parameters = [
- 'watcher_user_ids' => [5],
- 'subject' => 'Issue subject with some xml entities: & < > " \' ',
- 'description' => 'Description with some xml entities: & < > " \' ',
- 'uploads' => [
- [
- 'token' => 'first-token',
- 'filename' => 'SomeRandomFile.txt',
- 'description' => 'Simple description',
- 'content_type' => 'text/plain',
- ],
- ],
- 'custom_fields' => [
- ['id' => 25, 'value' => 'Second Custom Field'],
- ],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/issues.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains('5'),
- $this->stringContains(
- ''
- . 'first-token'
- . 'SomeRandomFile.txt'
- . 'Simple description'
- . 'text/plain'
- . ''
- ),
- $this->stringContains(
- ''
- . 'Second Custom Field'
- . ''
- ),
- $this->stringContains('Issue subject with some xml entities: & < > " \' '),
- $this->stringContains('Description with some xml entities: & < > " \' ')
- )
- );
-
- // Create the object under test
- $api = new Issue($client);
-
- // Perform the tests
- $api->create($parameters);
- }
-
/**
* Test assign an user to an issue.
*
diff --git a/tests/Unit/Api/Membership/CreateTest.php b/tests/Unit/Api/Membership/CreateTest.php
new file mode 100644
index 00000000..f736e52c
--- /dev/null
+++ b/tests/Unit/Api/Membership/CreateTest.php
@@ -0,0 +1,147 @@
+create($identifier, $parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with on role_id' => [
+ 5,
+ ['user_id' => 4, 'role_ids' => 2],
+ '/projects/5/memberships.xml',
+ '42',
+ 201,
+ '',
+ ],
+ 'test with multiple role_ids' => [
+ 5,
+ ['user_id' => 4, 'role_ids' => [5, 6]],
+ '/projects/5/memberships.xml',
+ '456',
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/projects/5/memberships.xml',
+ 'application/xml',
+ '42',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Membership($client);
+
+ // Perform the tests
+ $return = $api->create(5, ['user_id' => 4, 'role_ids' => 2]);
+
+ $this->assertSame('', $return);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Membership($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `user_id`, `role_ids`');
+
+ // Perform the tests
+ $api->create(5);
+ }
+
+ /**
+ * @dataProvider incompleteCreateParameterProvider
+ */
+ public function testCreateThrowsExceptionIfMandatoyParametersAreMissing($parameters)
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Membership($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `user_id`, `role_ids`');
+
+ // Perform the tests
+ $api->create('test', $parameters);
+ }
+
+ /**
+ * Provider for incomplete create parameters.
+ *
+ * @return array[]
+ */
+ public static function incompleteCreateParameterProvider(): array
+ {
+ return [
+ 'missing all mandatory parameters' => [
+ [],
+ ],
+ 'missing `user_id` parameter' => [
+ [
+ 'role_ids' => 2,
+ ],
+ ],
+ 'missing `role_ids` parameter' => [
+ [
+ 'user_id' => 4,
+ ],
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/MembershipTest.php b/tests/Unit/Api/MembershipTest.php
index f8522488..2e9a22a3 100644
--- a/tests/Unit/Api/MembershipTest.php
+++ b/tests/Unit/Api/MembershipTest.php
@@ -258,144 +258,6 @@ public function testRemoveMemberReturnsFalseIfMemberlistIsMissing()
$this->assertFalse($api->removeMember(1, 2));
}
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionWithEmptyParameters()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Membership($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `user_id`, `role_ids`');
-
- // Perform the tests
- $this->assertSame($response, $api->create(5));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionIfRoleIdsAreMissingInParameters()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Membership($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `user_id`, `role_ids`');
-
- // Perform the tests
- $this->assertSame($response, $api->create(5, ['user_id' => 4]));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'user_id' => 1,
- 'role_ids' => 1,
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- $this->logicalAnd(
- $this->stringStartsWith('/projects/5/memberships'),
- $this->stringEndsWith('.xml')
- ),
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n")
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Membership($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create(5, $parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @test
- */
- public function testCreateBuildsXml()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'user_id' => 10,
- 'role_ids' => [5, 6],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- $this->logicalAnd(
- $this->stringStartsWith('/projects/5/memberships'),
- $this->stringEndsWith('.xml')
- ),
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains(''),
- $this->stringContains('5'),
- $this->stringContains('6'),
- $this->stringContains(''),
- $this->stringContains('10')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Membership($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create(5, $parameters));
- }
-
/**
* Test update().
*
diff --git a/tests/Unit/Api/Project/CreateTest.php b/tests/Unit/Api/Project/CreateTest.php
new file mode 100644
index 00000000..780ab6f9
--- /dev/null
+++ b/tests/Unit/Api/Project/CreateTest.php
@@ -0,0 +1,215 @@
+create($parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with minimal parameters' => [
+ [
+ 'identifier' => 'test-project',
+ 'name' => 'Test Project',
+ ],
+ '/projects.xml',
+ 'Test Projecttest-project',
+ 201,
+ '',
+ ],
+ 'test with special chars in parameters' => [
+ [
+ 'identifier' => 'test-project',
+ 'name' => 'Test Project with some xml entities: & < > " \' ',
+ 'description' => 'Description with some xml entities: & < > " \' ',
+ ],
+ '/projects.xml',
+ <<
+
+ Test Project with some xml entities: & < > " '
+ test-project
+ Description with some xml entities: & < > " '
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with all parameters' => [
+ [
+ 'identifier' => 'test-project',
+ 'name' => 'Test Project',
+ 'tracker_ids' => [10, 5],
+ ],
+ '/projects.xml',
+ <<
+
+ Test Project
+ test-project
+
+ 10
+ 5
+
+
+ XML,
+ 201,
+ '',
+ ],
+ 'test with custom fields' => [
+ [
+ 'identifier' => 'test-project',
+ 'name' => 'Test Project',
+ 'custom_fields' => [
+ [
+ 'id' => 123,
+ 'name' => 'cf_name',
+ 'field_format' => 'string',
+ 'value' => [1, 2, 3],
+ ],
+ ],
+ ],
+ '/projects.xml',
+ <<
+
+ Test Project
+ test-project
+
+
+
+ 1
+ 2
+ 3
+
+
+
+
+ XML,
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/projects.xml',
+ 'application/xml',
+ 'Test Projecttest-project',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Project($client);
+
+ // Perform the tests
+ $return = $api->create(['identifier' => 'test-project', 'name' => 'Test Project']);
+
+ $this->assertSame('', $return);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Project($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `name`, `identifier`');
+
+ // Perform the tests
+ $api->create();
+ }
+
+ /**
+ * @dataProvider incompleteCreateParameterProvider
+ */
+ public function testCreateThrowsExceptionIfMandatoyParametersAreMissing($parameters)
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Project($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `name`, `identifier`');
+
+ // Perform the tests
+ $api->create($parameters);
+ }
+
+ /**
+ * Provider for incomplete create parameters.
+ *
+ * @return array[]
+ */
+ public static function incompleteCreateParameterProvider(): array
+ {
+ return [
+ 'missing all mandatory parameters' => [
+ [
+ 'description' => 'project description',
+ ],
+ ],
+ 'missing `identifier` parameters' => [
+ [
+ 'name' => 'Test Project',
+ ],
+ ],
+ 'missing `name` parameter' => [
+ [
+ 'identifier' => 'test-project',
+ ],
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/Project/ShowTest.php b/tests/Unit/Api/Project/ShowTest.php
index f023afcd..21429ee2 100644
--- a/tests/Unit/Api/Project/ShowTest.php
+++ b/tests/Unit/Api/Project/ShowTest.php
@@ -39,11 +39,63 @@ public function testShowReturnsCorrectResponse($identifier, array $params, $expe
public static function getShowData(): array
{
return [
- 'array response with integer id' => [5, [], '/projects/5.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations', '["API Response"]', ['API Response']],
- 'array response with string id' => ['test', [], '/projects/test.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations', '["API Response"]', ['API Response']],
- 'array response with parameters' => [5, ['parameter1', 'parameter2', 'enabled_modules'], '/projects/5.json?0=parameter1&1=parameter2&2=enabled_modules&include=trackers%2Cissue_categories%2Cattachments%2Crelations', '["API Response"]', ['API Response']],
- 'string response' => [5, [], '/projects/5.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations', 'string', 'Error decoding body as JSON: Syntax error'],
- 'false response' => [5, [], '/projects/5.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations', '', false],
+ 'array response with integer id' => [
+ 5,
+ [],
+ '/projects/5.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations',
+ '["API Response"]',
+ ['API Response'],
+ ],
+ 'array response with string id' => [
+ 'test',
+ [],
+ '/projects/test.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations',
+ '["API Response"]',
+ ['API Response'],
+ ],
+ 'test include parameter as array' => [
+ 'test',
+ [
+ 'include' => ['resource1', 'resource2'],
+ ],
+ '/projects/test.json?include=resource1%2Cresource2',
+ '["API Response"]',
+ ['API Response'],
+ ],
+ 'test include parameter as string will be ignored' => [
+ 'test',
+ [
+ 'include' => 'resource1,resource2',
+ ],
+ '/projects/test.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations',
+ '["API Response"]',
+ ['API Response'],
+ ],
+ 'array response with parameters' => [
+ 5,
+ [
+ 'parameter1',
+ 'parameter2',
+ 'enabled_modules',
+ ],
+ '/projects/5.json?0=parameter1&1=parameter2&2=enabled_modules&include=trackers%2Cissue_categories%2Cattachments%2Crelations',
+ '["API Response"]',
+ ['API Response'],
+ ],
+ 'string response' => [
+ 5,
+ [],
+ '/projects/5.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations',
+ 'string',
+ 'Error decoding body as JSON: Syntax error',
+ ],
+ 'false response' => [
+ 5,
+ [],
+ '/projects/5.json?include=trackers%2Cissue_categories%2Cattachments%2Crelations',
+ '',
+ false,
+ ],
];
}
}
diff --git a/tests/Unit/Api/ProjectTest.php b/tests/Unit/Api/ProjectTest.php
index ccaafa1c..18d07b6e 100644
--- a/tests/Unit/Api/ProjectTest.php
+++ b/tests/Unit/Api/ProjectTest.php
@@ -295,174 +295,6 @@ public function testGetIdByNameMakesGetRequest()
$this->assertSame(5, $api->getIdByName('Project 5'));
}
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionWithEmptyParameters()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Project($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`, `identifier`');
-
- // Perform the tests
- $this->assertSame($response, $api->create(['id' => 5]));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionIfIdentifierIsMissingInParameters()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'name' => 'Test Project',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Project($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`, `identifier`');
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionIfNameIsMissingInParameters()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'identifier' => 'test-project',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Project($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`, `identifier`');
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'identifier' => 'test-project',
- 'name' => 'Test Project with some xml entities: & < > " \' ',
- 'description' => 'Description with some xml entities: & < > " \' ',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('test-project'),
- $this->stringContains('Test Project with some xml entities: & < > " \' '),
- $this->stringContains('Description with some xml entities: & < > " \' ')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Project($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPostWithTrackers()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'identifier' => 'test-project',
- 'name' => 'Test Project',
- 'tracker_ids' => [10, 5],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains(''),
- $this->stringContains('10'),
- $this->stringContains('5'),
- $this->stringContains('')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Project($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
/**
* Test update().
*
diff --git a/tests/Unit/Api/TimeEntry/CreateTest.php b/tests/Unit/Api/TimeEntry/CreateTest.php
new file mode 100644
index 00000000..753735c1
--- /dev/null
+++ b/tests/Unit/Api/TimeEntry/CreateTest.php
@@ -0,0 +1,191 @@
+create($parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with issue_id' => [
+ ['issue_id' => 5, 'hours' => 5.25],
+ '/time_entries.xml',
+ '55.25',
+ 201,
+ '',
+ ],
+ 'test with project_id' => [
+ ['project_id' => 5, 'hours' => 5.25],
+ '/time_entries.xml',
+ '55.25',
+ 201,
+ '',
+ ],
+ 'test with all parameters' => [
+ [
+ 'issue_id' => '15',
+ 'project_id' => '25',
+ 'hours' => '5.25',
+ 'comments' => 'some text with xml entities: & < > " \' ',
+ 'custom_fields' => [
+ [
+ 'id' => 1,
+ 'name' => 'Affected version',
+ 'value' => '1.0.1',
+ ],
+ [
+ 'id' => 2,
+ 'name' => 'Resolution',
+ 'value' => 'Fixed',
+ ],
+ ],
+ ],
+ '/time_entries.xml',
+ <<
+
+ 15
+ 25
+ 5.25
+ some text with xml entities: & < > " '
+
+
+ 1.0.1
+
+
+ Fixed
+
+
+
+ XML,
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/time_entries.xml',
+ 'application/xml',
+ '55.25',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new TimeEntry($client);
+
+ // Perform the tests
+ $return = $api->create(['issue_id' => 5, 'hours' => 5.25]);
+
+ $this->assertSame('', $return);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Test values
+ $response = 'API Response';
+
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new TimeEntry($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `issue_id` or `project_id`, `hours`');
+
+ // Perform the tests
+ $this->assertSame($response, $api->create());
+ }
+
+ /**
+ * @dataProvider incompleteCreateParameterProvider
+ */
+ public function testCreateThrowsExceptionIfValueIsMissingInParameters($parameters)
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new TimeEntry($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `issue_id` or `project_id`, `hours`');
+
+ // Perform the tests
+ $api->create($parameters);
+ }
+
+ /**
+ * Provider for incomplete create parameters.
+ *
+ * @return array[]
+ */
+ public static function incompleteCreateParameterProvider(): array
+ {
+ return [
+ 'missing all mandatory parameters' => [
+ [
+ 'id' => '5',
+ ],
+ ],
+ 'missing `issue_id` or `project_id` parameters' => [
+ [
+ 'hours' => '5.25',
+ ],
+ ],
+ 'missing `hours` parameter' => [
+ [
+ 'issue_id' => 5,
+ 'project_id' => 5,
+ ],
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/TimeEntryTest.php b/tests/Unit/Api/TimeEntryTest.php
index d864f608..4f2f25e2 100644
--- a/tests/Unit/Api/TimeEntryTest.php
+++ b/tests/Unit/Api/TimeEntryTest.php
@@ -152,146 +152,6 @@ public function testRemoveCallsDelete()
$this->assertSame($response, $api->remove(5));
}
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionWithEmptyParameters()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new TimeEntry($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `issue_id` or `project_id`, `hours`');
-
- // Perform the tests
- $this->assertSame($response, $api->create(['id' => 5]));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionIfIssueIdAndProjectIdAreMissingInParameters()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'hours' => '5.25',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new TimeEntry($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `issue_id` or `project_id`, `hours`');
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionIfHoursAreMissingInParameters()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'issue_id' => '15',
- 'project_id' => '25',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new TimeEntry($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `issue_id` or `project_id`, `hours`');
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'issue_id' => '15',
- 'project_id' => '25',
- 'hours' => '5.25',
- 'comments' => 'some text with xml entities: & < > " \' ',
- 'custom_fields' => [
- [
- 'id' => 1,
- 'name' => 'Affected version',
- 'value' => '1.0.1',
- ],
- [
- 'id' => 2,
- 'name' => 'Resolution',
- 'value' => 'Fixed',
- ],
- ],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/time_entries.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('15'),
- $this->stringContains('25'),
- $this->stringContains('5.25'),
- $this->stringContains('some text with xml entities: & < > " \' '),
- $this->stringContains('1.0.1Fixed')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new TimeEntry($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
/**
* Test update().
*
diff --git a/tests/Unit/Api/User/CreateTest.php b/tests/Unit/Api/User/CreateTest.php
new file mode 100644
index 00000000..0bd6be32
--- /dev/null
+++ b/tests/Unit/Api/User/CreateTest.php
@@ -0,0 +1,198 @@
+create($parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with minimal parameters' => [
+ ['login' => 'user', 'lastname' => 'last', 'firstname' => 'first', 'mail' => 'mail@example.com'],
+ '/users.xml',
+ 'userlastfirstmail@example.com',
+ 201,
+ '',
+ ],
+ 'test with all parameters' => [
+ [
+ 'login' => 'user',
+ 'lastname' => 'last',
+ 'firstname' => 'first',
+ 'mail' => 'mail@example.com',
+ 'password' => 'secret',
+ 'custom_fields' => [
+ ['id' => 5, 'value' => 'Value 5'],
+ ['id' => 13, 'value' => 'Value 13', 'name' => 'CF Name'],
+ ],
+ ],
+ '/users.xml',
+ <<
+
+ user
+ secret
+ last
+ first
+ mail@example.com
+
+
+ Value 5
+
+
+ Value 13
+
+
+
+ XML,
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/users.xml',
+ 'application/xml',
+ 'userlastfirstmail@example.com',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new User($client);
+
+ // Perform the tests
+ $return = $api->create(['login' => 'user', 'lastname' => 'last', 'firstname' => 'first', 'mail' => 'mail@example.com']);
+
+ $this->assertSame('', $return);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Test values
+ $response = 'API Response';
+
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new User($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `login`, `lastname`, `firstname`, `mail`');
+
+ // Perform the tests
+ $this->assertSame($response, $api->create());
+ }
+
+ /**
+ * @dataProvider incompleteCreateParameterProvider
+ */
+ public function testCreateThrowsExceptionIfValueIsMissingInParameters($parameters)
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new User($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `login`, `lastname`, `firstname`, `mail`');
+
+ // Perform the tests
+ $api->create($parameters);
+ }
+
+ /**
+ * Provider for incomplete create parameters.
+ *
+ * @return array[]
+ */
+ public static function incompleteCreateParameterProvider(): array
+ {
+ return [
+ // Missing Login
+ [
+ [
+ 'password' => 'secretPass',
+ 'lastname' => 'Last Name',
+ 'firstname' => 'Firstname',
+ 'mail' => 'mail@example.com',
+ ],
+ ],
+ // Missing last name
+ [
+ [
+ 'login' => 'TestUser',
+ 'password' => 'secretPass',
+ 'firstname' => 'Firstname',
+ 'mail' => 'mail@example.com',
+ ],
+ ],
+ // Missing first name
+ [
+ [
+ 'login' => 'TestUser',
+ 'password' => 'secretPass',
+ 'lastname' => 'Last Name',
+ 'mail' => 'mail@example.com',
+ ],
+ ],
+ // Missing email
+ [
+ [
+ 'login' => 'TestUser',
+ 'password' => 'secretPass',
+ 'lastname' => 'Last Name',
+ 'firstname' => 'Firstname',
+ ],
+ ],
+ ];
+ }
+}
diff --git a/tests/Unit/Api/UserTest.php b/tests/Unit/Api/UserTest.php
index 1865bb6f..12f60e6d 100644
--- a/tests/Unit/Api/UserTest.php
+++ b/tests/Unit/Api/UserTest.php
@@ -5,7 +5,6 @@
use PHPUnit\Framework\TestCase;
use Redmine\Api\User;
use Redmine\Client\Client;
-use Redmine\Exception\MissingParameterException;
use Redmine\Tests\Fixtures\MockClient;
/**
@@ -224,209 +223,6 @@ public function testRemoveCallsDelete()
$this->assertSame($response, $api->remove(5));
}
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionWithEmptyParameters()
- {
- // Test values
- $response = 'API Response';
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new User($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `login`, `lastname`, `firstname`, `mail`');
-
- // Perform the tests
- $this->assertSame($response, $api->create());
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @dataProvider incompleteCreateParameterProvider
- *
- * @test
- *
- * @param array $parameters Parameters for create()
- */
- public function testCreateThrowsExceptionIfValueIsMissingInParameters($parameters)
- {
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new User($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `login`, `lastname`, `firstname`, `mail`');
-
- // Perform the tests
- $api->create($parameters);
- }
-
- /**
- * Provider for incomplete create parameters.
- *
- * @return array[]
- */
- public static function incompleteCreateParameterProvider(): array
- {
- return [
- // Missing Login
- [
- [
- 'password' => 'secretPass',
- 'lastname' => 'Last Name',
- 'firstname' => 'Firstname',
- 'mail' => 'mail@example.com',
- ],
- ],
- // Missing last name
- [
- [
- 'login' => 'TestUser',
- 'password' => 'secretPass',
- 'firstname' => 'Firstname',
- 'mail' => 'mail@example.com',
- ],
- ],
- // Missing first name
- [
- [
- 'login' => 'TestUser',
- 'password' => 'secretPass',
- 'lastname' => 'Last Name',
- 'mail' => 'mail@example.com',
- ],
- ],
- // Missing email
- [
- [
- 'login' => 'TestUser',
- 'password' => 'secretPass',
- 'lastname' => 'Last Name',
- 'firstname' => 'Firstname',
- ],
- ],
- ];
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'login' => 'TestUser',
- 'password' => 'secretPass',
- 'lastname' => 'Last Name',
- 'firstname' => 'Firstname',
- 'mail' => 'mail@example.com',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/users.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('TestUser'),
- $this->stringContains('secretPass'),
- $this->stringContains('Last Name'),
- $this->stringContains('Firstname'),
- $this->stringContains('mail@example.com')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new User($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @covers ::attachCustomFieldXML
- * @test
- */
- public function testCreateWithCustomField()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'login' => 'TestUser',
- 'password' => 'secretPass',
- 'lastname' => 'Last Name',
- 'firstname' => 'Firstname',
- 'mail' => 'mail@example.com',
- 'custom_fields' => [
- ['id' => 5, 'value' => 'Value 5'],
- ['id' => 13, 'value' => 'Value 13', 'name' => 'CF Name'],
- ],
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/users.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('TestUser'),
- $this->stringContains('secretPass'),
- $this->stringContains('Last Name'),
- $this->stringContains('Firstname'),
- $this->stringContains('mail@example.com'),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains(''),
- $this->stringContains('Value 13'),
- $this->stringContains(''),
- $this->stringContains('Value 5'),
- $this->stringContains('')
- )
- )
- ->willReturn(true);
- $client->expects($this->exactly(1))
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new User($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create($parameters));
- }
-
/**
* Test update().
*
diff --git a/tests/Unit/Api/Version/CreateTest.php b/tests/Unit/Api/Version/CreateTest.php
new file mode 100644
index 00000000..4531710c
--- /dev/null
+++ b/tests/Unit/Api/Version/CreateTest.php
@@ -0,0 +1,212 @@
+create($identifier, $parameters);
+
+ $this->assertInstanceOf(SimpleXMLElement::class, $return);
+ $this->assertXmlStringEqualsXmlString($response, $return->asXml());
+ }
+
+ public static function getCreateData(): array
+ {
+ return [
+ 'test with minimal parameters' => [
+ 5,
+ ['name' => 'test'],
+ '/projects/5/versions.xml',
+ 'test',
+ 201,
+ '',
+ ],
+ 'test with status parameter' => [
+ 5,
+ ['name' => 'test', 'status' => 'locked'],
+ '/projects/5/versions.xml',
+ 'testlocked',
+ 201,
+ '',
+ ],
+ 'test with sharing parameter none' => [
+ 5,
+ ['name' => 'test', 'sharing' => 'none'],
+ '/projects/5/versions.xml',
+ 'testnone',
+ 201,
+ '',
+ ],
+ 'test with sharing parameter descendants' => [
+ 5,
+ ['name' => 'test', 'sharing' => 'descendants'],
+ '/projects/5/versions.xml',
+ 'testdescendants',
+ 201,
+ '',
+ ],
+ 'test with sharing parameter hierarchy' => [
+ 5,
+ ['name' => 'test', 'sharing' => 'hierarchy'],
+ '/projects/5/versions.xml',
+ 'testhierarchy',
+ 201,
+ '',
+ ],
+ 'test with sharing parameter tree' => [
+ 5,
+ ['name' => 'test', 'sharing' => 'tree'],
+ '/projects/5/versions.xml',
+ 'testtree',
+ 201,
+ '',
+ ],
+ 'test with sharing parameter system' => [
+ 5,
+ ['name' => 'test', 'sharing' => 'system'],
+ '/projects/5/versions.xml',
+ 'testsystem',
+ 201,
+ '',
+ ],
+ 'test with empty sharing parameter null' => [
+ 5,
+ ['name' => 'test', 'sharing' => null],
+ '/projects/5/versions.xml',
+ 'test',
+ 201,
+ '',
+ ],
+ 'test with empty sharing parameter false' => [
+ 5,
+ ['name' => 'test', 'sharing' => false],
+ '/projects/5/versions.xml',
+ 'test',
+ 201,
+ '',
+ ],
+ 'test with empty sharing parameter empty string' => [
+ 5,
+ ['name' => 'test', 'sharing' => ''],
+ '/projects/5/versions.xml',
+ 'test',
+ 201,
+ '',
+ ],
+ ];
+ }
+
+ public function testCreateReturnsEmptyString()
+ {
+ $client = AssertingHttpClient::create(
+ $this,
+ [
+ 'POST',
+ '/projects/5/versions.xml',
+ 'application/xml',
+ 'test',
+ 500,
+ '',
+ ''
+ ]
+ );
+
+ // Create the object under test
+ $api = new Version($client);
+
+ // Perform the tests
+ $return = $api->create(5, ['name' => 'test']);
+
+ $this->assertSame('', $return);
+ }
+
+ public function testCreateThrowsExceptionWithEmptyParameters()
+ {
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Version($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
+
+ // Perform the tests
+ $api->create(5);
+ }
+
+ public function testCreateThrowsExceptionWithMissingNameInParameters()
+ {
+ // Test values
+ $parameters = [
+ 'description' => 'Test version description',
+ ];
+
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Version($client);
+
+ $this->expectException(MissingParameterException::class);
+ $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
+
+ // Perform the tests
+ $api->create(5, $parameters);
+ }
+
+ public function testCreateThrowsExceptionWithInvalidStatus()
+ {
+ // Test values
+ $parameters = [
+ 'name' => 'test',
+ 'description' => 'Test version description',
+ 'status' => 'invalid',
+ ];
+
+ // Create the used mock objects
+ $client = $this->createMock(HttpClient::class);
+
+ // Create the object under test
+ $api = new Version($client);
+
+ $this->expectException(InvalidParameterException::class);
+ $this->expectExceptionMessage('Possible values for status : open, locked, closed');
+
+ // Perform the tests
+ $api->create('test', $parameters);
+ }
+}
diff --git a/tests/Unit/Api/VersionTest.php b/tests/Unit/Api/VersionTest.php
index 39ce5fde..cc276b9f 100644
--- a/tests/Unit/Api/VersionTest.php
+++ b/tests/Unit/Api/VersionTest.php
@@ -6,7 +6,6 @@
use Redmine\Api\Version;
use Redmine\Client\Client;
use Redmine\Exception\InvalidParameterException;
-use Redmine\Exception\MissingParameterException;
use Redmine\Tests\Fixtures\MockClient;
/**
@@ -180,165 +179,6 @@ public function testRemoveWithStringCallsDelete()
$this->assertSame($response, $api->remove(5));
}
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionWithEmptyParameters()
- {
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Version($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
-
- // Perform the tests
- $api->create(5);
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- *
- * @test
- */
- public function testCreateThrowsExceptionWithMissingNameInParameters()
- {
- // Test values
- $parameters = [
- 'description' => 'Test version description',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Version($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
-
- // Perform the tests
- $api->create(5, $parameters);
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::validateStatus
- *
- * @test
- */
- public function testCreateThrowsExceptionWithInvalidStatus()
- {
- // Test values
- $parameters = [
- 'description' => 'Test version description',
- 'status' => 'invalid',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
-
- // Create the object under test
- $api = new Version($client);
-
- $this->expectException(MissingParameterException::class);
- $this->expectExceptionMessage('Theses parameters are mandatory: `name`');
-
- // Perform the tests
- $api->create('test', $parameters);
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @test
- */
- public function testCreateCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'name' => 'Test version',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects/5/versions.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('Test version')
- )
- )
- ->willReturn(true);
- $client->expects($this->once())
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Version($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create(5, $parameters));
- }
-
- /**
- * Test create().
- *
- * @covers ::create
- * @covers ::post
- * @covers ::validateStatus
- * @test
- */
- public function testCreateWithValidStatusCallsPost()
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'name' => 'Test version',
- 'status' => 'locked',
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects/5/versions.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('Test version'),
- $this->stringContains('locked')
- )
- )
- ->willReturn(true);
- $client->expects($this->once())
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Version($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create(5, $parameters));
- }
-
/**
* Test update().
*
@@ -625,97 +465,6 @@ public function testGetIdByNameMakesGetRequest()
$this->assertSame(5, $api->getIdByName(5, 'Version 5'));
}
- /**
- * Test validateSharing().
- *
- * @covers ::create
- * @covers ::validateSharing
- * @dataProvider validSharingProvider
- * @test
- *
- * @param string $sharingValue
- * @param string $sharingXmlElement
- */
- public function testCreateWithValidSharing($sharingValue, $sharingXmlElement)
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'name' => 'Test version',
- 'sharing' => $sharingValue,
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects/test/versions.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('Test version'),
- $this->stringContains($sharingXmlElement)
- )
- )
- ->willReturn(true);
- $client->expects($this->once())
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Version($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create('test', $parameters));
- }
-
- /**
- * Test validateSharing().
- *
- * @covers ::create
- * @covers ::validateSharing
- * @dataProvider validEmptySharingProvider
- * @test
- *
- * @param string $sharingValue
- */
- public function testCreateWithValidEmptySharing($sharingValue)
- {
- // Test values
- $response = 'API Response';
- $parameters = [
- 'name' => 'Test version',
- 'sharing' => $sharingValue,
- ];
-
- // Create the used mock objects
- $client = $this->createMock(Client::class);
- $client->expects($this->once())
- ->method('requestPost')
- ->with(
- '/projects/test/versions.xml',
- $this->logicalAnd(
- $this->stringStartsWith('' . "\n" . ''),
- $this->stringEndsWith('' . "\n"),
- $this->stringContains('Test version'),
- $this->logicalNot(
- $this->stringContains('willReturn(true);
- $client->expects($this->once())
- ->method('getLastResponseBody')
- ->willReturn($response);
-
- // Create the object under test
- $api = new Version($client);
-
- // Perform the tests
- $this->assertSame($response, $api->create('test', $parameters));
- }
-
/**
* Test validateSharing().
*
diff --git a/tests/Unit/Client/NativeCurlClient/RequestTest.php b/tests/Unit/Client/NativeCurlClient/RequestTest.php
index b1cf4fe5..ccdc05c4 100644
--- a/tests/Unit/Client/NativeCurlClient/RequestTest.php
+++ b/tests/Unit/Client/NativeCurlClient/RequestTest.php
@@ -12,6 +12,7 @@
/**
* @covers \Redmine\Client\NativeCurlClient::request
* @covers \Redmine\Client\NativeCurlClient::runRequest
+ * @covers \Redmine\Client\NativeCurlClient::createCurl
* @covers \Redmine\Client\NativeCurlClient::createHttpHeader
*/
class RequestTest extends TestCase
@@ -92,4 +93,63 @@ public static function getRequestReponseData(): array
['DELETE', '', 500, 'text/plain', 'Internal Server Error'],
];
}
+
+ public function testRequestWithUploadAndFilepathReturnsCorrectResponse()
+ {
+ $namespace = 'Redmine\Client';
+
+ $curl = $this->createMock(stdClass::class);
+
+ $curlInit = $this->getFunctionMock($namespace, 'curl_init');
+ $curlInit->expects($this->exactly(1))->willReturn($curl);
+
+ $curlExec = $this->getFunctionMock($namespace, 'curl_exec');
+ $curlExec->expects($this->exactly(1))->willReturn('{"upload":{}}');
+
+ $curlSetoptArray = $this->getFunctionMock($namespace, 'curl_setopt_array');
+
+ $curlGetinfo = $this->getFunctionMock($namespace, 'curl_getinfo');
+ $curlGetinfo->expects($this->exactly(2))->will($this->returnValueMap(([
+ [$curl, CURLINFO_HTTP_CODE, 201],
+ [$curl, CURLINFO_CONTENT_TYPE, 'application/json'],
+ ])));
+
+ $curlErrno = $this->getFunctionMock($namespace, 'curl_errno');
+ $curlErrno->expects($this->exactly(1))->willReturn(CURLE_OK);
+
+ $curlClose = $this->getFunctionMock($namespace, 'curl_close');
+
+ $client = new NativeCurlClient(
+ 'http://test.local',
+ 'access_token'
+ );
+
+ // PHPUnit 10 compatible way to test trigger_error().
+ set_error_handler(
+ function ($errno, $errstr): bool {
+ $this->assertSame(
+ 'Uploading an attachment by filepath is deprecated since v2.1.0, use file_get_contents() to upload the file content instead.',
+ $errstr
+ );
+
+ restore_error_handler();
+ return true;
+ },
+ E_USER_DEPRECATED
+ );
+
+ $request = $this->createConfiguredMock(Request::class, [
+ 'getMethod' => 'POST',
+ 'getPath' => '/uploads.json',
+ 'getContentType' => 'application/octet-stream',
+ 'getContent' => realpath(__DIR__ . '/../../../Fixtures/testfile_01.txt'),
+ ]);
+
+ $response = $client->request($request);
+
+ $this->assertInstanceOf(Response::class, $response);
+ $this->assertSame(201, $response->getStatusCode());
+ $this->assertSame('application/json', $response->getContentType());
+ $this->assertSame('{"upload":{}}', $response->getContent());
+ }
}
diff --git a/tests/Unit/Exception/ClientExceptionTest.php b/tests/Unit/Exception/ClientExceptionTest.php
index c0195534..200e0941 100644
--- a/tests/Unit/Exception/ClientExceptionTest.php
+++ b/tests/Unit/Exception/ClientExceptionTest.php
@@ -7,11 +7,11 @@
use Redmine\Exception as RedmineException;
use Redmine\Exception\ClientException;
+/**
+ * @coversDefaultClass \Redmine\Exception\ClientException
+ */
class ClientExceptionTest extends TestCase
{
- /**
- * @test
- */
public function testClientException()
{
$exception = new ClientException();
diff --git a/tests/Unit/Exception/InvalidApiNameExceptionTest.php b/tests/Unit/Exception/InvalidApiNameExceptionTest.php
index 838aade8..9078d8a3 100644
--- a/tests/Unit/Exception/InvalidApiNameExceptionTest.php
+++ b/tests/Unit/Exception/InvalidApiNameExceptionTest.php
@@ -7,11 +7,11 @@
use Redmine\Exception as RedmineException;
use Redmine\Exception\InvalidApiNameException;
+/**
+ * @coversDefaultClass \Redmine\Exception\InvalidApiNameException
+ */
class InvalidApiNameExceptionTest extends TestCase
{
- /**
- * @test
- */
public function testInvalidApiNameException()
{
$exception = new InvalidApiNameException();
diff --git a/tests/Unit/Http/HttpFactory/MakeXmlRequestTest.php b/tests/Unit/Http/HttpFactory/MakeXmlRequestTest.php
new file mode 100644
index 00000000..5a0bf923
--- /dev/null
+++ b/tests/Unit/Http/HttpFactory/MakeXmlRequestTest.php
@@ -0,0 +1,26 @@
+assertInstanceOf(Request::class, $response);
+ $this->assertSame('GET', $response->getMethod());
+ $this->assertSame('path.xml', $response->getPath());
+ $this->assertSame('application/xml', $response->getContentType());
+ $this->assertSame('content', $response->getContent());
+ }
+}
diff --git a/tests/Unit/Serializer/JsonSerializerTest.php b/tests/Unit/Serializer/JsonSerializerTest.php
index de9a2307..afed796d 100644
--- a/tests/Unit/Serializer/JsonSerializerTest.php
+++ b/tests/Unit/Serializer/JsonSerializerTest.php
@@ -8,6 +8,9 @@
use Redmine\Exception\SerializerException;
use Redmine\Serializer\JsonSerializer;
+/**
+ * @coversDefaultClass \Redmine\Serializer\JsonSerializer
+ */
class JsonSerializerTest extends TestCase
{
public static function getEncodedToNormalizedData(): array
@@ -180,8 +183,6 @@ public static function getNormalizedToEncodedData(): array
}
/**
- * @covers \Redmine\Serializer\JsonSerializer::getEncoded
- * @covers \Redmine\Serializer\JsonSerializer::__toString
* @test
*
* @dataProvider getNormalizedToEncodedData
diff --git a/tests/Unit/Serializer/PathSerializerTest.php b/tests/Unit/Serializer/PathSerializerTest.php
index 439a4e84..35a8499a 100644
--- a/tests/Unit/Serializer/PathSerializerTest.php
+++ b/tests/Unit/Serializer/PathSerializerTest.php
@@ -7,6 +7,9 @@
use PHPUnit\Framework\TestCase;
use Redmine\Serializer\PathSerializer;
+/**
+ * @coversDefaultClass \Redmine\Serializer\PathSerializer
+ */
class PathSerializerTest extends TestCase
{
public static function getPathData(): array
@@ -48,8 +51,6 @@ public static function getPathData(): array
}
/**
- * @covers \Redmine\Serializer\PathSerializer::getPath
- * @covers \Redmine\Serializer\PathSerializer::__toString
* @test
*
* @dataProvider getPathData
diff --git a/tests/Unit/Serializer/XmlSerializerTest.php b/tests/Unit/Serializer/XmlSerializerTest.php
index aefa4296..170e456c 100644
--- a/tests/Unit/Serializer/XmlSerializerTest.php
+++ b/tests/Unit/Serializer/XmlSerializerTest.php
@@ -8,28 +8,31 @@
use Redmine\Exception\SerializerException;
use Redmine\Serializer\XmlSerializer;
+/**
+ * @coversDefaultClass \Redmine\Serializer\XmlSerializer
+ */
class XmlSerializerTest extends TestCase
{
public static function getEncodedToNormalizedData(): array
{
return [
- [
+ 'test with single tag' => [
'',
[],
],
- [
+ 'test with closed tag' => [
'',
[],
],
- [
+ 'test with open and close tag' => [
'',
[],
],
- [
+ 'test with integer' => [
'1',
['1'],
],
- [
+ 'test with array' => [
<<< XML
@@ -107,13 +110,22 @@ public function createFromStringWithInvalidStringThrowsException(string $message
$this->expectException(SerializerException::class);
$this->expectExceptionMessage($message);
- $serializer = XmlSerializer::createFromString($data);
+ XmlSerializer::createFromString($data);
}
public static function getNormalizedToEncodedData(): array
{
return [
- [
+ 'test with simple string' => [
+ [
+ 'key' => 'value',
+ ],
+ <<< XML
+
+ value
+ XML,
+ ],
+ 'test with simple array' => [
[
'issue' => [
'project_id' => 1,
@@ -124,13 +136,13 @@ public static function getNormalizedToEncodedData(): array
<<< XML
- 1
- Example
- 4
+ 1
+ Example
+ 4
XML,
],
- [
+ 'test with ignored elements' => [
[
'issue' => [
'project_id' => 1,
@@ -144,13 +156,41 @@ public static function getNormalizedToEncodedData(): array
<<< XML
- 1
- Example
- 4
+ 1
+ Example
+ 4
XML,
],
- [
+ 'test with custom fields with single value' => [
+ [
+ 'project' => [
+ 'name' => 'some name',
+ 'identifier' => 'the_identifier',
+ 'custom_fields' => [
+ [
+ 'id' => 123,
+ 'name' => 'cf_name',
+ 'field_format' => 'string',
+ 'value' => 1,
+ ],
+ ],
+ ],
+ ],
+ <<< XML
+
+
+ some name
+ the_identifier
+
+
+ 1
+
+
+
+ XML,
+ ],
+ 'test with custom fields with array value' => [
[
'project' => [
'name' => 'some name',
@@ -168,26 +208,51 @@ public static function getNormalizedToEncodedData(): array
<<< XML
- some name
- the_identifier
-
-
-
- 1
- 2
- 3
-
-
-
+ some name
+ the_identifier
+
+
+
+ 1
+ 2
+ 3
+
+
+
XML,
],
+ 'test with uploads' => [
+ [
+ 'issue' => [
+ 'uploads' => [
+ [
+ 'token' => 'asdfasdfasdfasdf',
+ 'filename' => 'MyFile.pdf',
+ 'description' => 'MyFile is better then YourFile...',
+ 'content_type' => 'application/pdf',
+ ],
+ ],
+ ],
+ ],
+ <<< XML
+
+
+
+
+ asdfasdfasdfasdf
+ MyFile.pdf
+ MyFile is better then YourFile...
+ application/pdf
+
+
+
+ XML,
+ ],
];
}
/**
- * @covers \Redmine\Serializer\XmlSerializer::getEncoded
- * @covers \Redmine\Serializer\XmlSerializer::__toString
* @test
*
* @dataProvider getNormalizedToEncodedData
@@ -219,6 +284,6 @@ public function createFromArrayWithInvalidDataThrowsException(string $message, a
$this->expectException(SerializerException::class);
$this->expectExceptionMessage($message);
- $serializer = XmlSerializer::createFromArray($data);
+ XmlSerializer::createFromArray($data);
}
}