diff options
-rw-r--r-- | app/Model/Link.php | 4 | ||||
-rw-r--r-- | app/Model/TaskLink.php | 2 | ||||
-rw-r--r-- | docs/api-json-rpc.markdown | 477 | ||||
-rw-r--r-- | tests/functionals.mysql.xml | 2 | ||||
-rw-r--r-- | tests/functionals.postgres.xml | 2 | ||||
-rw-r--r-- | tests/functionals/ApiTest.php | 113 |
6 files changed, 585 insertions, 15 deletions
diff --git a/app/Model/Link.php b/app/Model/Link.php index b26a01e4..e0e5184e 100644 --- a/app/Model/Link.php +++ b/app/Model/Link.php @@ -125,7 +125,7 @@ class Link extends Base $label_id = $this->db->getConnection()->getLastId(); - if ($opposite_label !== '') { + if (! empty($opposite_label)) { $this->db ->table(self::TABLE) @@ -144,7 +144,7 @@ class Link extends Base $this->db->closeTransaction(); - return $label_id; + return (int) $label_id; } /** diff --git a/app/Model/TaskLink.php b/app/Model/TaskLink.php index 7b696afc..251460c9 100644 --- a/app/Model/TaskLink.php +++ b/app/Model/TaskLink.php @@ -144,7 +144,7 @@ class TaskLink extends Base $this->db->closeTransaction(); - return $task_link_id; + return (int) $task_link_id; } /** diff --git a/docs/api-json-rpc.markdown b/docs/api-json-rpc.markdown index d8fe896d..89010cef 100644 --- a/docs/api-json-rpc.markdown +++ b/docs/api-json-rpc.markdown @@ -2830,7 +2830,6 @@ Response example: } ``` - ### createSubtask - Purpose: **Create a new subtask** @@ -2876,6 +2875,8 @@ Response example: - Result on success: **subtask properties** - Result on failure: **null** +Request example: + ```json { "jsonrpc": "2.0", @@ -2913,6 +2914,8 @@ Response example: - Result on success: **List of subtasks** - Result on failure: **false** +Request example: + ```json { "jsonrpc": "2.0", @@ -2961,7 +2964,7 @@ Response example: - Result on success: **true** - Result on failure: **false** -Request examples: +Request example: ```json { @@ -2996,6 +2999,8 @@ Response example: - Result on success: **true** - Result on failure: **false** +Request example: + ```json { "jsonrpc": "2.0", @@ -3016,3 +3021,471 @@ Response example: "result": true } ``` + +### getAllLinks + +- Purpose: **Get the list of possible relations between tasks** +- Parameters: none +- Result on success: **List of links** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getAllLinks", + "id": 113057196 +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 113057196, + "result": [ + { + "id": "1", + "label": "relates to", + "opposite_id": "0" + }, + { + "id": "2", + "label": "blocks", + "opposite_id": "3" + }, + { + "id": "3", + "label": "is blocked by", + "opposite_id": "2" + }, + { + "id": "4", + "label": "duplicates", + "opposite_id": "5" + }, + { + "id": "5", + "label": "is duplicated by", + "opposite_id": "4" + }, + { + "id": "6", + "label": "is a child of", + "opposite_id": "7" + }, + { + "id": "7", + "label": "is a parent of", + "opposite_id": "6" + }, + { + "id": "8", + "label": "targets milestone", + "opposite_id": "9" + }, + { + "id": "9", + "label": "is a milestone of", + "opposite_id": "8" + }, + { + "id": "10", + "label": "fixes", + "opposite_id": "11" + }, + { + "id": "11", + "label": "is fixed by", + "opposite_id": "10" + } + ] +} +``` + +### getOppositeLinkId + +- Purpose: **Get the opposite link id of a task link** +- Parameters: + - **link_id** (integer, required) +- Result on success: **link_id** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getOppositeLinkId", + "id": 407062448, + "params": [ + 2 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 407062448, + "result": "3" +} +``` + +### getLinkByLabel + +- Purpose: **Get a link by label** +- Parameters: + - **label** (integer, required) +- Result on success: **link properties** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getLinkByLabel", + "id": 1796123316, + "params": [ + "blocks" + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 1796123316, + "result": { + "id": "2", + "label": "blocks", + "opposite_id": "3" + } +} +``` + +### getLinkById + +- Purpose: **Get a link by id** +- Parameters: + - **link_id** (integer, required) +- Result on success: **link properties** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getLinkById", + "id": 1190238402, + "params": [ + 4 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 1190238402, + "result": { + "id": "4", + "label": "duplicates", + "opposite_id": "5" + } +} +``` + +### createLink + +- Purpose: **Create a new task relation** +- Parameters: + - **label** (integer, required) + - **opposite_label** (integer, optional) +- Result on success: **link_id** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "createLink", + "id": 1040237496, + "params": [ + "foo", + "bar" + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 1040237496, + "result": 13 +} +``` + +### updateLink + +- Purpose: **Update a link** +- Parameters: + - **link_id** (integer, required) + - **opposite_link_id** (integer, required) + - **label** (string, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "updateLink", + "id": 2110446926, + "params": [ + "14", + "12", + "boo" + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2110446926, + "result": true +} +``` + +### removeLink + +- Purpose: **Remove a link** +- Parameters: + - **link_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "removeLink", + "id": 2136522739, + "params": [ + "14" + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 2136522739, + "result": true +} +``` + +### createTaskLink + +- Purpose: **Create a link between two tasks** +- Parameters: + - **task_id** (integer, required) + - **opposite_task_id** (integer, required) + - **link_id** (integer, required) +- Result on success: **task_link_id** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "createTaskLink", + "id": 509742912, + "params": [ + 2, + 3, + 1 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 509742912, + "result": 1 +} +``` + +### updateTaskLink + +- Purpose: **Update task link** +- Parameters: + - **task_link_id** (integer, required) + - **task_id** (integer, required) + - **opposite_task_id** (integer, required) + - **link_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "updateTaskLink", + "id": 669037109, + "params": [ + 1, + 2, + 4, + 2 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 669037109, + "result": true +} +``` + +### getTaskLinkById + +- Purpose: **Get a task link** +- Parameters: + - **task_link_id** (integer, required) +- Result on success: **task link properties** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getTaskLinkById", + "id": 809885202, + "params": [ + 1 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 809885202, + "result": { + "id": "1", + "link_id": "1", + "task_id": "2", + "opposite_task_id": "3" + } +} +``` + +### getAllTaskLinks + +- Purpose: **Get all links related to a task** +- Parameters: + - **task_id** (integer, required) +- Result on success: **list of task link** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "getAllTaskLinks", + "id": 810848359, + "params": [ + 2 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 810848359, + "result": [ + { + "id": "1", + "task_id": "3", + "label": "relates to", + "title": "B", + "is_active": "1", + "project_id": "1", + "task_time_spent": "0", + "task_time_estimated": "0", + "task_assignee_id": "0", + "task_assignee_username": null, + "task_assignee_name": null, + "column_title": "Backlog" + } + ] +} +``` + +### removeTaskLink + +- Purpose: **Remove a link between two tasks** +- Parameters: + - **task_link_id** (integer, required) +- Result on success: **true** +- Result on failure: **false** + +Request example: + +```json +{ + "jsonrpc": "2.0", + "method": "removeTaskLink", + "id": 473028226, + "params": [ + 1 + ] +} +``` + +Response example: + +```json +{ + "jsonrpc": "2.0", + "id": 473028226, + "result": true +} +``` diff --git a/tests/functionals.mysql.xml b/tests/functionals.mysql.xml index f5c3e16a..61cb05df 100644 --- a/tests/functionals.mysql.xml +++ b/tests/functionals.mysql.xml @@ -12,6 +12,6 @@ <const name="DB_HOSTNAME" value="localhost" /> <const name="DB_USERNAME" value="root" /> <const name="DB_PASSWORD" value="" /> - <const name="DB_PORT" value="3306" /> + <const name="DB_PORT" value="" /> </php> </phpunit>
\ No newline at end of file diff --git a/tests/functionals.postgres.xml b/tests/functionals.postgres.xml index 40fcef00..eb83d157 100644 --- a/tests/functionals.postgres.xml +++ b/tests/functionals.postgres.xml @@ -12,6 +12,6 @@ <const name="DB_HOSTNAME" value="localhost" /> <const name="DB_USERNAME" value="postgres" /> <const name="DB_PASSWORD" value="postgres" /> - <const name="DB_PORT" value="5432" /> + <const name="DB_PORT" value="" /> </php> </phpunit>
\ No newline at end of file diff --git a/tests/functionals/ApiTest.php b/tests/functionals/ApiTest.php index 7b7a2bed..4ab2db99 100644 --- a/tests/functionals/ApiTest.php +++ b/tests/functionals/ApiTest.php @@ -4,25 +4,24 @@ require_once __DIR__.'/../../vendor/autoload.php'; class Api extends PHPUnit_Framework_TestCase { - private $client; + private $client = null; public static function setUpBeforeClass() { if (DB_DRIVER === 'sqlite') { @unlink(DB_FILENAME); - $pdo = new PDO('sqlite:'.DB_FILENAME); } else if (DB_DRIVER === 'mysql') { $pdo = new PDO('mysql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD); $pdo->exec('DROP DATABASE '.DB_NAME); $pdo->exec('CREATE DATABASE '.DB_NAME); - $pdo = new PDO('mysql:host='.DB_HOSTNAME.';dbname='.DB_NAME, DB_USERNAME, DB_PASSWORD); + $pdo = null; } else if (DB_DRIVER === 'postgres') { $pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD); $pdo->exec('DROP DATABASE '.DB_NAME); $pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME); - $pdo = new PDO('pgsql:host='.DB_HOSTNAME.';dbname='.DB_NAME, DB_USERNAME, DB_PASSWORD); + $pdo = null; } $service = new ServiceProvider\DatabaseProvider; @@ -31,15 +30,13 @@ class Api extends PHPUnit_Framework_TestCase $db->table('settings')->eq('option', 'api_token')->update(array('value' => API_KEY)); $db->table('settings')->eq('option', 'application_timezone')->update(array('value' => 'Europe/Paris')); $db->closeConnection(); - - $pdo = null; } public function setUp() { $this->client = new JsonRPC\Client(API_URL); $this->client->authentication('jsonrpc', API_KEY); - // $this->client->debug = true; + $this->client->debug = true; } private function getTaskId() @@ -837,4 +834,104 @@ class Api extends PHPUnit_Framework_TestCase $this->assertEmpty($actions); $this->assertCount(0, $actions); } -} + + public function testGetAllLinks() + { + $links = $this->client->getAllLinks(); + $this->assertNotEmpty($links); + $this->assertArrayHasKey('id', $links[0]); + $this->assertArrayHasKey('label', $links[0]); + $this->assertArrayHasKey('opposite_id', $links[0]); + } + + public function testGetOppositeLink() + { + $link = $this->client->getOppositeLinkId(1); + $this->assertEquals(1, $link); + + $link = $this->client->getOppositeLinkId(2); + $this->assertEquals(3, $link); + } + + public function testGetLinkByLabel() + { + $link = $this->client->getLinkByLabel('blocks'); + $this->assertNotEmpty($link); + $this->assertEquals(2, $link['id']); + $this->assertEquals(3, $link['opposite_id']); + } + + public function testGetLinkById() + { + $link = $this->client->getLinkById(4); + $this->assertNotEmpty($link); + $this->assertEquals(4, $link['id']); + $this->assertEquals(5, $link['opposite_id']); + $this->assertEquals('duplicates', $link['label']); + } + + public function testCreateLink() + { + $link_id = $this->client->createLink(array('label' => 'test')); + $this->assertNotFalse($link_id); + $this->assertInternalType('int', $link_id); + + $link_id = $this->client->createLink(array('label' => 'foo', 'opposite_label' => 'bar')); + $this->assertNotFalse($link_id); + $this->assertInternalType('int', $link_id); + } + + public function testUpdateLink() + { + $link1 = $this->client->getLinkByLabel('bar'); + $this->assertNotEmpty($link1); + + $link2 = $this->client->getLinkByLabel('test'); + $this->assertNotEmpty($link2); + + $this->assertNotFalse($this->client->updateLink($link1['id'], $link2['id'], 'boo')); + + $link = $this->client->getLinkById($link1['id']); + $this->assertNotEmpty($link); + $this->assertEquals($link2['id'], $link['opposite_id']); + $this->assertEquals('boo', $link['label']); + + $this->assertTrue($this->client->removeLink($link1['id'])); + } + + public function testCreateTaskLink() + { + $task_id1 = $this->client->createTask(array('project_id' => 1, 'title' => 'A')); + $this->assertNotFalse($task_id1); + + $task_id2 = $this->client->createTask(array('project_id' => 1, 'title' => 'B')); + $this->assertNotFalse($task_id2); + + $task_id3 = $this->client->createTask(array('project_id' => 1, 'title' => 'C')); + $this->assertNotFalse($task_id3); + + $task_link_id = $this->client->createTaskLink($task_id1, $task_id2, 1); + $this->assertNotFalse($task_link_id); + + $task_link = $this->client->getTaskLinkById($task_link_id); + $this->assertNotEmpty($task_link); + $this->assertEquals($task_id1, $task_link['task_id']); + $this->assertEquals($task_id2, $task_link['opposite_task_id']); + $this->assertEquals(1, $task_link['link_id']); + + $task_links = $this->client->getAllTaskLinks($task_id1); + $this->assertNotEmpty($task_links); + $this->assertCount(1, $task_links); + + $this->assertTrue($this->client->updateTaskLink($task_link_id, $task_id1, $task_id3, 2)); + + $task_link = $this->client->getTaskLinkById($task_link_id); + $this->assertNotEmpty($task_link); + $this->assertEquals($task_id1, $task_link['task_id']); + $this->assertEquals($task_id3, $task_link['opposite_task_id']); + $this->assertEquals(2, $task_link['link_id']); + + $this->assertTrue($this->client->removeTaskLink($task_link_id)); + $this->assertEmpty($this->client->getAllTaskLinks($task_id1)); + } +}
\ No newline at end of file |