Add more API unit tests; fix bugs identified by new tests.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-06-12 22:57:10 -05:00
parent 4a529c9003
commit 5da0f4e3cb
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
14 changed files with 312 additions and 119 deletions

View File

@ -321,7 +321,7 @@ return function (App $app) {
$group->group(
'/podcast/{podcast_id}',
function (RouteCollectorProxy $group) {
$group->post('', Controller\Api\Stations\PodcastsController::class . ':editAction')
$group->put('', Controller\Api\Stations\PodcastsController::class . ':editAction')
->add(new Middleware\HandleMultipartJson());
$group->delete('', Controller\Api\Stations\PodcastsController::class . ':deleteAction');
@ -339,7 +339,7 @@ return function (App $app) {
$group->group(
'/episode/{episode_id}',
function (RouteCollectorProxy $group) {
$group->post(
$group->put(
'',
Controller\Api\Stations\PodcastEpisodesController::class . ':editAction'
)->add(new Middleware\HandleMultipartJson());

View File

@ -2,6 +2,7 @@
namespace App\Middleware;
use JsonException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
@ -36,9 +37,11 @@ class HandleMultipartJson implements MiddlewareInterface
if (1 === count($parsedBody)) {
$bodyField = current($parsedBody);
if (is_string($bodyField)) {
$parsedBody = json_decode($bodyField, true, 512, JSON_THROW_ON_ERROR);
$request = $request->withParsedBody($parsedBody);
try {
$parsedBody = json_decode($bodyField, true, 512, JSON_THROW_ON_ERROR);
$request = $request->withParsedBody($parsedBody);
} catch (JsonException) {
}
}
}

View File

@ -99,11 +99,15 @@ class Strings
/**
* Truncate URL in text-presentable format (i.e. "http://www.example.com" becomes "example.com")
*
* @param string $url
* @param string|null $url
* @param int $length
*/
public static function truncateUrl(string $url, $length = 40): string
public static function truncateUrl(?string $url, $length = 40): string
{
if (null === $url) {
return '';
}
/** @noinspection HttpUrlsUsage */
$url = str_replace(['http://', 'https://', 'www.'], '', $url);

View File

@ -10,41 +10,15 @@ class Api_Admin_CustomFieldsCest extends CestAbstract
{
$I->wantTo('Manage custom fields via API.');
// Create new record
$I->sendPOST('/api/admin/custom_fields', [
'name' => 'Test Field',
]);
$I->seeResponseCodeIs(200);
$newRecord = $I->grabDataFromResponseByJsonPath('id');
$newRecordId = $newRecord[0];
// Get single record.
$I->sendGET('/api/admin/custom_field/' . $newRecordId);
$I->seeResponseContainsJson([
'id' => $newRecordId,
'name' => 'Test Field',
]);
// Modify record.
$I->sendPUT('/api/admin/custom_field/' . $newRecordId, [
'name' => 'Test Field Renamed',
]);
// List all records.
$I->sendGET('/api/admin/custom_field/' . $newRecordId);
$I->seeResponseContainsJson([
'id' => $newRecordId,
'name' => 'Test Field Renamed',
]);
// Delete Record
$I->sendDELETE('/api/admin/custom_field/' . $newRecordId);
$I->sendGET('/api/admin/custom_field/' . $newRecordId);
$I->seeResponseCodeIs(404);
$this->testCrudApi(
$I,
'/api/admin/custom_fields',
[
'name' => 'Test Field',
],
[
'name' => 'Modified Field',
]
);
}
}

View File

@ -0,0 +1,29 @@
<?php
class Api_Admin_RolesCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function manageRoles(FunctionalTester $I): void
{
$I->wantTo('Manage roles via API.');
$this->testCrudApi(
$I,
'/api/admin/roles',
[
'name' => 'Super Administrator',
'permissions' => [
'global' => [
\App\Acl::GLOBAL_ALL,
],
],
],
[
'name' => 'Test Super Administrator',
]
);
}
}

View File

@ -10,43 +10,17 @@ class Api_Admin_StationsCest extends CestAbstract
{
$I->wantTo('Manage stations via API.');
// Create new record
$I->sendPOST('/api/admin/stations', [
'name' => 'Test Station',
]);
$I->seeResponseCodeIs(200);
$newRecord = $I->grabDataFromResponseByJsonPath('id');
$newRecordId = $newRecord[0];
// Get single record.
$I->sendGET('/api/admin/station/' . $newRecordId);
$I->seeResponseContainsJson([
'id' => $newRecordId,
'name' => 'Test Station',
'short_name' => 'test_station',
]);
// Modify record.
$I->sendPUT('/api/admin/station/' . $newRecordId, [
'name' => 'Test Station Renamed',
]);
// List all records.
$I->sendGET('/api/admin/station/' . $newRecordId);
$I->seeResponseContainsJson([
'id' => $newRecordId,
'name' => 'Test Station Renamed',
'short_name' => 'test_station',
]);
// Delete Record
$I->sendDELETE('/api/admin/station/' . $newRecordId);
$I->sendGET('/api/admin/station/' . $newRecordId);
$I->seeResponseCodeIs(404);
$this->testCrudApi(
$I,
'/api/admin/stations',
[
'name' => 'Test Station',
'short_name' => 'test_station',
],
[
'name' => 'Modified Station',
'frontend_type' => \App\Radio\Adapters::FRONTEND_SHOUTCAST,
]
);
}
}

View File

@ -10,43 +10,16 @@ class Api_Admin_UsersCest extends CestAbstract
{
$I->wantTo('Manage users via API.');
// Create new record
$I->sendPOST('/api/admin/users', [
'email' => 'test@example.com',
'name' => 'Test User',
]);
$I->seeResponseCodeIs(200);
$newRecord = $I->grabDataFromResponseByJsonPath('id');
$newRecordId = $newRecord[0];
// Get single record.
$I->sendGET('/api/admin/user/' . $newRecordId);
$I->seeResponseContainsJson([
'id' => $newRecordId,
'name' => 'Test User',
]);
// Modify record.
$I->sendPUT('/api/admin/user/' . $newRecordId, [
'name' => 'Test User Renamed',
]);
// List all records.
$I->sendGET('/api/admin/user/' . $newRecordId);
$I->seeResponseContainsJson([
'id' => $newRecordId,
'name' => 'Test User Renamed',
'email' => 'test@example.com',
]);
// Delete Record
$I->sendDELETE('/api/admin/user/' . $newRecordId);
$I->sendGET('/api/admin/user/' . $newRecordId);
$I->seeResponseCodeIs(404);
$this->testCrudApi(
$I,
'/api/admin/users',
[
'name' => 'Test User',
'email' => 'test@example.com',
],
[
'name' => 'Test User Renamed',
]
);
}
}

View File

@ -0,0 +1,30 @@
<?php
class Api_Stations_MountsCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function manageMounts(FunctionalTester $I): void
{
$I->wantTo('Manage station mount points via API.');
$station = $this->getTestStation();
$this->testCrudApi(
$I,
'/api/station/' . $station->getId() . '/mounts',
[
'name' => '/radio.mp3',
'enable_autodj' => true,
'autodj_format' => 'mp3',
'autodj_bitrate' => 128,
],
[
'name' => '/music.mp3',
'enable_autodj' => false,
]
);
}
}

View File

@ -0,0 +1,30 @@
<?php
class Api_Stations_PlaylistsCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function managePlaylists(FunctionalTester $I): void
{
$I->wantTo('Manage station playlists via API.');
$station = $this->getTestStation();
$this->testCrudApi(
$I,
'/api/station/' . $station->getId() . '/playlists',
[
'name' => 'General Rotation Playlist',
'source' => \App\Entity\StationPlaylist::SOURCE_SONGS,
'type' => \App\Entity\StationPlaylist::TYPE_DEFAULT,
'weight' => 5,
],
[
'name' => 'Modified Playlist',
'type' => \App\Entity\StationPlaylist::TYPE_ADVANCED,
]
);
}
}

View File

@ -0,0 +1,29 @@
<?php
class Api_Stations_PodcastsCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function managePodcasts(FunctionalTester $I): void
{
$I->wantTo('Manage station podcasts via API.');
$station = $this->getTestStation();
$this->testCrudApi(
$I,
'/api/station/' . $station->getId() . '/podcasts',
[
'title' => 'My Awesome Podcast',
'description' => 'A functional test podcast.',
'language' => 'en',
],
[
'title' => 'My Modified Podcast',
'language' => 'de',
]
);
}
}

View File

@ -0,0 +1,27 @@
<?php
class Api_Stations_RemotesCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function manageRemotes(FunctionalTester $I): void
{
$I->wantTo('Manage station remote relays via API.');
$station = $this->getTestStation();
$this->testCrudApi(
$I,
'/api/station/' . $station->getId() . '/remotes',
[
'type' => \App\Radio\Adapters::REMOTE_ICECAST,
'display_name' => 'Test Remote Relay',
],
[
'display_name' => 'Modified Remote Relay',
]
);
}
}

View File

@ -0,0 +1,59 @@
<?php
class Api_Stations_StreamersCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function manageStreamers(FunctionalTester $I): void
{
$I->wantTo('Manage station streamers via API.');
// Create new record
$station = $this->getTestStation();
$listUrl = '/api/station/' . $station->getId() . '/streamers';
$I->sendPOST(
$listUrl,
[
'streamer_username' => 'test',
'streamer_password' => 'test',
'display_name' => 'Test Streamer',
]
);
$I->seeResponseCodeIs(200);
$newRecord = $I->grabDataFromResponseByJsonPath('links.self');
$newRecordSelfLink = $newRecord[0];
// Get single record.
$I->sendGET($newRecordSelfLink);
$I->seeResponseContainsJson(
[
'streamer_username' => 'test',
'display_name' => 'Test Streamer',
]
);
// Modify record.
$editJson = [
'display_name' => 'Different Test Streamer',
];
$I->sendPUT($newRecordSelfLink, $editJson);
// List all records.
$I->sendGET($newRecordSelfLink);
$I->seeResponseContainsJson($editJson);
// Delete Record
$I->sendDELETE($newRecordSelfLink);
$I->sendGET($newRecordSelfLink);
$I->seeResponseCodeIs(404);
}
}

View File

@ -0,0 +1,27 @@
<?php
class Api_Stations_WebhooksCest extends CestAbstract
{
/**
* @before setupComplete
* @before login
*/
public function manageWebhooks(FunctionalTester $I): void
{
$I->wantTo('Manage station webhooks via API.');
$station = $this->getTestStation();
$this->testCrudApi(
$I,
'/api/station/' . $station->getId() . '/webhooks',
[
'type' => \App\Webhook\Connector\Generic::NAME,
'name' => 'Test Webhook',
],
[
'name' => 'Modified Webhook',
]
);
}
}

View File

@ -163,4 +163,38 @@ abstract class CestAbstract
$I->seeInSource('Logged In');
}
protected function testCrudApi(
FunctionalTester $I,
string $listUrl,
array $createJson = [],
array $editJson = []
): void {
// Create new record
$I->sendPOST($listUrl, $createJson);
$I->seeResponseCodeIs(200);
$newRecord = $I->grabDataFromResponseByJsonPath('links.self');
$newRecordSelfLink = $newRecord[0];
// Get single record.
$I->sendGET($newRecordSelfLink);
$I->seeResponseContainsJson($createJson);
// Modify record.
$I->sendPUT($newRecordSelfLink, $editJson);
// List all records.
$I->sendGET($newRecordSelfLink);
$I->seeResponseContainsJson($editJson);
// Delete Record
$I->sendDELETE($newRecordSelfLink);
$I->sendGET($newRecordSelfLink);
$I->seeResponseCodeIs(404);
}
}