diff --git a/build/phpunit.xml b/build/phpunit.xml
index 5de965e..372bff1 100644
--- a/build/phpunit.xml
+++ b/build/phpunit.xml
@@ -32,7 +32,7 @@
- src/
+ ../src/
diff --git a/src/Api.php b/src/Api.php
index 2919ddf..6924720 100644
--- a/src/Api.php
+++ b/src/Api.php
@@ -2,9 +2,9 @@
namespace Potherca\Flysystem\Github;
+use Github\Api\ApiInterface;
use Github\Api\GitData;
use Github\Api\Repo;
-use Github\Api\Repository\Contents;
use Github\Client;
use Github\Exception\RuntimeException;
use League\Flysystem\AdapterInterface;
@@ -13,14 +13,16 @@
/**
* Facade class for the Github Api Library
*/
-class Api implements ApiInterface
+class Api implements \Potherca\Flysystem\Github\ApiInterface
{
////////////////////////////// CLASS PROPERTIES \\\\\\\\\\\\\\\\\\\\\\\\\\\\
const ERROR_NO_NAME = 'Could not set name for entry';
const ERROR_NOT_FOUND = 'Not Found';
- const API_GIT_DATA = 'git';
- const API_REPO = 'repo';
+ const API_GIT_DATA = 'gitData';
+ const API_REPOSITORY = 'repo';
+ const API_REPOSITORY_COMMITS = 'commits';
+ const API_REPOSITORY_CONTENTS = 'contents';
const KEY_BLOB = 'blob';
const KEY_DIRECTORY = 'dir';
@@ -36,20 +38,27 @@ class Api implements ApiInterface
const KEY_TREE = 'tree';
const KEY_TYPE = 'type';
const KEY_VISIBILITY = 'visibility';
-
+
const GITHUB_API_URL = 'https://api.github.com';
const GITHUB_URL = 'https://github.com';
- const MIME_TYPE_DIRECTORY = 'directory';
+ const MIME_TYPE_DIRECTORY = 'directory'; // or application/x-directory
+
+ const NOT_RECURSIVE = false;
+ const RECURSIVE = true;
+ /** @var ApiInterface[] */
+ private $apiCollection = [];
/** @var Client */
private $client;
- /** @var Contents */
- private $contents;
- /** @var SettingsInterface */
- private $settings;
+ /** @var array */
+ private $commits = [];
/** @var bool */
private $isAuthenticationAttempted = false;
+ /** @var array */
+ private $metadata = [];
+ /** @var SettingsInterface */
+ private $settings;
//////////////////////////// SETTERS AND GETTERS \\\\\\\\\\\\\\\\\\\\\\\\\\\
/**
@@ -61,41 +70,66 @@ class Api implements ApiInterface
*/
private function getApi($name)
{
- $this->authenticate();
- return $this->client->api($name);
+ $this->assureAuthenticated();
+
+ if ($this->hasKey($this->apiCollection, $name) === false) {
+ $this->apiCollection[$name] = $this->client->api($name);
+ }
+
+ return $this->apiCollection[$name];
}
/**
- * @return GitData
+ * @param $name
+ * @param $api
+ * @return ApiInterface
+ */
+ private function getApiFrom($name, $api)
+ {
+ if ($this->hasKey($this->apiCollection, $name) === false) {
+ $this->apiCollection[$name] = $api->{$name}();
+ }
+ return $this->apiCollection[$name];
+ }
+
+ /**
+ * @return \Github\Api\Repository\Commits
*
* @throws \Github\Exception\InvalidArgumentException
*/
- private function getGitDataApi()
+ private function getCommitsApi()
{
- return $this->getApi(self::API_GIT_DATA);
+ return $this->getApiFrom(self::API_REPOSITORY_COMMITS, $this->getRepositoryApi());
}
/**
- * @return Repo
+ * @return \Github\Api\Repository\Contents
*
* @throws \Github\Exception\InvalidArgumentException
*/
- private function getRepositoryApi()
+ private function getContentApi()
{
- return $this->getApi(self::API_REPO);
+ return $this->getApiFrom(self::API_REPOSITORY_CONTENTS, $this->getRepositoryApi());
}
/**
- * @return \Github\Api\Repository\Contents
+ * @return GitData
*
* @throws \Github\Exception\InvalidArgumentException
*/
- private function getRepositoryContent()
+ private function getGitDataApi()
{
- if ($this->contents === null) {
- $this->contents = $this->getRepositoryApi()->contents();
- }
- return $this->contents;
+ return $this->getApi(self::API_GIT_DATA);
+ }
+
+ /**
+ * @return Repo
+ *
+ * @throws \Github\Exception\InvalidArgumentException
+ */
+ private function getRepositoryApi()
+ {
+ return $this->getApi(self::API_REPOSITORY);
}
//////////////////////////////// PUBLIC API \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
@@ -118,7 +152,9 @@ final public function __construct(Client $client, SettingsInterface $settings)
*/
final public function exists($path)
{
- return $this->getRepositoryContent()->exists(
+ $path = $this->normalizePathName($path);
+
+ return $this->getContentApi()->exists(
$this->settings->getVendor(),
$this->settings->getPackage(),
$path,
@@ -136,7 +172,9 @@ final public function exists($path)
*/
final public function getFileContents($path)
{
- return $this->getRepositoryContent()->download(
+ $path = $this->normalizePathName($path);
+
+ return $this->getContentApi()->download(
$this->settings->getVendor(),
$this->settings->getPackage(),
$path,
@@ -153,13 +191,7 @@ final public function getFileContents($path)
*/
final public function getLastUpdatedTimestamp($path)
{
- $commits = $this->commitsForFile($path);
-
- $updated = array_shift($commits);
-
- $time = new \DateTime($updated['commit']['committer']['date']);
-
- return ['timestamp' => $time->getTimestamp()];
+ return $this->filterCommits($path, 'reset');
}
/**
@@ -171,13 +203,7 @@ final public function getLastUpdatedTimestamp($path)
*/
final public function getCreatedTimestamp($path)
{
- $commits = $this->commitsForFile($path);
-
- $created = array_pop($commits);
-
- $time = new \DateTime($created['commit']['committer']['date']);
-
- return ['timestamp' => $time->getTimestamp()];
+ return $this->filterCommits($path, 'end');
}
/**
@@ -187,56 +213,36 @@ final public function getCreatedTimestamp($path)
*
* @throws \Github\Exception\InvalidArgumentException
* @throws \Github\Exception\RuntimeException
+ * @throws \League\Flysystem\NotSupportedException
*/
final public function getMetaData($path)
{
- try {
- $metadata = $this->getRepositoryContent()->show(
- $this->settings->getVendor(),
- $this->settings->getPackage(),
- $path,
- $this->settings->getReference()
- );
- } catch (RuntimeException $exception) {
- if ($exception->getMessage() === self::ERROR_NOT_FOUND) {
- $metadata = false;
- } else {
- throw $exception;
+ $path = $this->normalizePathName($path);
+
+ if ($this->hasKey($this->metadata, $path) === false) {
+ try {
+ $metadata = $this->getContentApi()->show(
+ $this->settings->getVendor(),
+ $this->settings->getPackage(),
+ $path,
+ $this->settings->getReference()
+ );
+ } catch (RuntimeException $exception) {
+ if ($exception->getMessage() === self::ERROR_NOT_FOUND) {
+ $metadata = false;
+ } else {
+ throw $exception;
+ }
+ }
+
+ if ($this->isMetadataForDirectory($metadata) === true) {
+ $metadata = $this->metadataForDirectory($path);
}
- }
-
- if (is_array($metadata) === true && $this->isMetadataForDirectory($metadata) === true) {
- /** @var $metadata array */
- $project = sprintf('%s/%s', $this->settings->getVendor(), $this->settings->getPackage());
- $reference = $this->settings->getReference();
-
- $url = sprintf(
- '%s/repos/%s/contents/%s?ref=%s',
- self::GITHUB_API_URL,
- $project,
- trim($path, '/'),
- $reference
- );
- $htmlUrl = sprintf(
- '%s/%s/blob/%s/%s',
- self::GITHUB_URL,
- $project,
- $reference,
- trim($path, '/')
- );
- $metadata = [
- self::KEY_TYPE => self::KEY_DIRECTORY,
- 'url' => $url,
- 'html_url' => $htmlUrl,
- '_links' => [
- 'self' => $url,
- 'html' => $htmlUrl
- ]
- ];
+ $this->metadata[$path] = $metadata;
}
- return $metadata;
+ return $this->metadata[$path];
}
/**
@@ -244,10 +250,13 @@ final public function getMetaData($path)
* @param bool $recursive
*
* @return array
+ *
* @throws \Github\Exception\InvalidArgumentException
*/
- final public function getTreeMetadata($path, $recursive)
+ final public function getDirectoryContents($path, $recursive)
{
+ $path = $this->normalizePathName($path);
+
// If $info['truncated'] is `true`, the number of items in the tree array
// exceeded the github maximum limit. If we need to fetch more items,
// multiple calls will be needed
@@ -256,36 +265,14 @@ final public function getTreeMetadata($path, $recursive)
$this->settings->getVendor(),
$this->settings->getPackage(),
$this->settings->getReference(),
- true //@NOTE: To retrieve all needed date the 'recursive' flag should always be 'true'
+ self::RECURSIVE //@NOTE: To retrieve all needed date the 'recursive' flag should always be 'true'
);
- $path = rtrim($path, '/') . '/';
+ $treeData = $this->addTimestamps($info[self::KEY_TREE]);
- $treeMetadata = $this->extractMetaDataFromTreeInfo($info[self::KEY_TREE], $path, $recursive);
-
- $normalizeTreeMetadata = $this->normalizeTreeMetadata($treeMetadata);
-
- $directoryTimestamp = 0000000000;
+ $filteredTreeData = $this->filterTreeData($treeData, $path, $recursive);
- array_walk($normalizeTreeMetadata, function (&$entry) use (&$directoryTimestamp) {
- if ($this->hasKey($entry, self::KEY_TIMESTAMP) === false
- || $entry[self::KEY_TIMESTAMP] === false
- ) {
- $timestamp = $this->getCreatedTimestamp($entry[self::KEY_PATH])['timestamp'];
-
- $entry[self::KEY_TIMESTAMP] = $timestamp;
-
- if ($timestamp > $directoryTimestamp) {
- $directoryTimestamp = $timestamp;
- }
- }
- });
-
- /* @FIXME: It might be wise to use a filter to find the right entry instead of always using the first entry in the array. */
-
- $normalizeTreeMetadata[0]['timestamp'] = $directoryTimestamp;
-
- return $normalizeTreeMetadata;
+ return $this->normalizeTreeData($filteredTreeData);
}
/**
@@ -299,11 +286,14 @@ final public function getTreeMetadata($path, $recursive)
*/
final public function guessMimeType($path)
{
+ $path = $this->normalizePathName($path);
+
//@NOTE: The github API does not return a MIME type, so we have to guess :-(
$meta = $this->getMetaData($path);
+ /** @noinspection OffsetOperationsInspection *//* @NOTE: The existence of $meta[self::KEY_TYPE] has been validated by `hasKey`. */
if ($this->hasKey($meta, self::KEY_TYPE) && $meta[self::KEY_TYPE] === self::KEY_DIRECTORY) {
- $mimeType = self::MIME_TYPE_DIRECTORY; // or application/x-directory
+ $mimeType = self::MIME_TYPE_DIRECTORY;
} else {
$content = $this->getFileContents($path);
$mimeType = MimeType::detectByContent($content);
@@ -317,12 +307,12 @@ final public function guessMimeType($path)
*
* @throws \Github\Exception\InvalidArgumentException If no authentication method was given
*/
- private function authenticate()
+ private function assureAuthenticated()
{
if ($this->isAuthenticationAttempted === false) {
$credentials = $this->settings->getCredentials();
- if (empty($credentials) === false) {
+ if (count($credentials) !== 0) {
$credentials = array_replace(
[null, null, null],
$credentials
@@ -345,21 +335,18 @@ private function authenticate()
*
* @return array
*/
- private function extractMetaDataFromTreeInfo(array $tree, $path, $recursive)
+ private function filterTreeData(array $tree, $path, $recursive)
{
- $matchPath = substr($path, 0, -1);
- $length = abs(strlen($matchPath) - 1);
+ $length = strlen($path);
- $metadata = array_filter($tree, function ($entry) use ($matchPath, $recursive, $length) {
+ $metadata = array_filter($tree, function ($entry) use ($path, $recursive, $length) {
$match = false;
- $entryPath = $entry[self::KEY_PATH];
-
- if ($matchPath === '' || strpos($entryPath, $matchPath) === 0) {
- if ($recursive === true) {
+ if ($path === '' || strpos($entry[self::KEY_PATH], $path) === 0) {
+ if ($recursive === self::RECURSIVE) {
$match = true;
} else {
- $match = ($matchPath !== '' || strpos($entryPath, '/', $length) === false);
+ $match = ($path !== '' || strpos($entry[self::KEY_PATH], '/', $length) === false);
}
}
@@ -385,32 +372,30 @@ private function guessVisibility($permissions)
}
/**
- * @param array $metadata
+ * @param array $treeData
*
* @return array
+ *
+ * @throws \Github\Exception\InvalidArgumentException
*/
- private function normalizeTreeMetadata($metadata)
+ private function normalizeTreeData($treeData)
{
- $result = [];
-
- if (is_array(current($metadata)) === false) {
- $metadata = [$metadata];
+ if (is_array(current($treeData)) === false) {
+ $treeData = [$treeData];
}
- foreach ($metadata as $entry) {
+ $normalizedTreeData = array_map(function ($entry) {
$this->setEntryName($entry);
$this->setEntryType($entry);
$this->setEntryVisibility($entry);
$this->setDefaultValue($entry, self::KEY_CONTENTS);
$this->setDefaultValue($entry, self::KEY_STREAM);
- $this->setDefaultValue($entry, self::KEY_TIMESTAMP);
-
- $result[] = $entry;
- }
+ return $entry;
+ }, $treeData);
- return $result;
+ return $normalizedTreeData;
}
/**
@@ -422,14 +407,18 @@ private function normalizeTreeMetadata($metadata)
*/
private function commitsForFile($path)
{
- return $this->getRepositoryApi()->commits()->all(
- $this->settings->getVendor(),
- $this->settings->getPackage(),
- array(
- 'sha' => $this->settings->getBranch(),
- 'path' => $path
- )
- );
+ if ($this->hasKey($this->commits, $path) === false) {
+ $this->commits[$path] = $this->getCommitsApi()->all(
+ $this->settings->getVendor(),
+ $this->settings->getPackage(),
+ array(
+ 'sha' => $this->settings->getBranch(),
+ 'path' => $path
+ )
+ );
+ }
+
+ return $this->commits[$path];
}
/**
@@ -460,7 +449,10 @@ private function setEntryType(&$entry)
case self::KEY_TREE:
$entry[self::KEY_TYPE] = self::KEY_DIRECTORY;
break;
+ //@CHECKME: what should the 'default' be? Throw exception for unknown?
}
+ } else {
+ $entry[self::KEY_TYPE] = false;
}
}
@@ -501,10 +493,12 @@ private function isMetadataForDirectory($metadata)
{
$isDirectory = false;
- $keys = array_keys($metadata);
+ if (is_array($metadata) === true) {
+ $keys = array_keys($metadata);
- if ($keys[0] === 0) {
- $isDirectory = true;
+ if ($keys[0] === 0) {
+ $isDirectory = true;
+ }
}
return $isDirectory;
@@ -526,4 +520,129 @@ private function hasKey(&$subject, $key)
return $keyExists;
}
+
+ /**
+ * @param array $treeMetadata
+ * @param $path
+ *
+ * @return int
+ *
+ * @throws \Github\Exception\InvalidArgumentException
+ */
+ private function getDirectoryTimestamp(array $treeMetadata, $path)
+ {
+ $directoryTimestamp = 0000000000;
+
+ $filteredTreeData = $this->filterTreeData($treeMetadata, $path, self::RECURSIVE);
+
+ array_walk($filteredTreeData, function ($entry) use (&$directoryTimestamp, $path) {
+ if ($entry[self::KEY_TYPE] === self::KEY_FILE
+ && strpos($entry[self::KEY_PATH], $path) === 0
+ ) {
+ // @CHECKME: Should the directory Timestamp reflect the `getCreatedTimestamp` or `getLastUpdatedTimestamp`?
+ $timestamp = $this->getCreatedTimestamp($entry[self::KEY_PATH])[self::KEY_TIMESTAMP];
+
+ if ($timestamp > $directoryTimestamp) {
+ $directoryTimestamp = $timestamp;
+ }
+ }
+ });
+
+ return $directoryTimestamp;
+ }
+
+ private function normalizePathName($path)
+ {
+ return trim($path, '/');
+ }
+
+ /**
+ * @param $path
+ * @return array
+ * @throws \League\Flysystem\NotSupportedException
+ * @throws \Github\Exception\RuntimeException
+ *
+ * @throws \Github\Exception\InvalidArgumentException
+ */
+ private function metadataForDirectory($path)
+ {
+ $reference = $this->settings->getReference();
+ $project = sprintf('%s/%s', $this->settings->getVendor(), $this->settings->getPackage());
+
+ $url = sprintf(
+ '%s/repos/%s/contents/%s?ref=%s',
+ self::GITHUB_API_URL,
+ $project,
+ $path,
+ $reference
+ );
+ $htmlUrl = sprintf(
+ '%s/%s/blob/%s/%s',
+ self::GITHUB_URL,
+ $project,
+ $reference,
+ $path
+ );
+
+ $directoryContents = $this->getDirectoryContents($path, self::RECURSIVE);
+
+ $directoryMetadata = array_filter($directoryContents, function ($entry) use ($path) {
+ return $entry[self::KEY_PATH] === $path;
+ });
+
+ $metadata = array_merge(
+ $directoryMetadata[0],
+ [
+ self::KEY_TYPE => self::KEY_DIRECTORY,
+ 'url' => $url,
+ 'html_url' => $htmlUrl,
+ '_links' => [
+ 'self' => $url,
+ 'html' => $htmlUrl
+ ]
+ ]
+ );
+
+ return $metadata;
+ }
+
+ /**
+ * @param array $treeData
+ *
+ * @return array
+ *
+ * @throws \Github\Exception\InvalidArgumentException
+ */
+ private function addTimestamps(array $treeData)
+ {
+ return array_map(function ($entry) use ($treeData) {
+ if ($entry[self::KEY_TYPE] === self::KEY_DIRECTORY) {
+ $timestamp = $this->getDirectoryTimestamp($treeData, $entry[self::KEY_PATH]);
+ } else {
+ // @CHECKME: Should the Timestamp reflect the `getCreatedTimestamp` or `getLastUpdatedTimestamp`?
+ $timestamp = $this->getCreatedTimestamp($entry[self::KEY_PATH])[self::KEY_TIMESTAMP];
+ }
+ $entry[self::KEY_TIMESTAMP] = $timestamp;
+
+ return $entry;
+ }, $treeData);
+ }
+
+ /**
+ * @param $path
+ * @param $function
+ * @return array
+ */
+ private function filterCommits($path, callable $function)
+ {
+ $path = $this->normalizePathName($path);
+
+ $commits = $this->commitsForFile($path);
+
+ $subject = $function($commits);
+
+ $time = new \DateTime($subject['commit']['committer']['date']);
+
+ return [self::KEY_TIMESTAMP => $time->getTimestamp()];
+ }
}
diff --git a/src/ApiInterface.php b/src/ApiInterface.php
index d5168de..19ade72 100644
--- a/src/ApiInterface.php
+++ b/src/ApiInterface.php
@@ -42,7 +42,7 @@ public function getMetaData($path);
*
* @return array
*/
- public function getTreeMetadata($path, $recursive);
+ public function getDirectoryContents($path, $recursive);
/**
* @param string $path
diff --git a/src/GithubAdapter.php b/src/GithubAdapter.php
index 1379ecc..d63cc48 100644
--- a/src/GithubAdapter.php
+++ b/src/GithubAdapter.php
@@ -187,7 +187,7 @@ public function read($path)
*/
public function listContents($path = '/', $recursive = false)
{
- $contents = $this->getApi()->getTreeMetadata($path, $recursive);
+ $contents = $this->getApi()->getDirectoryContents($path, $recursive);
if ($this->isDirectoryContents($contents) === false) {
$contents = [];
@@ -254,7 +254,7 @@ public function getTimestamp($path)
public function getVisibility($path)
{
$recursive = false;
- $metadata = $this->getApi()->getTreeMetadata($path, $recursive);
+ $metadata = $this->getApi()->getDirectoryContents($path, $recursive);
return $metadata[0];
}
diff --git a/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fcommits.json b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fcommits.json
new file mode 100644
index 0000000..36e888c
--- /dev/null
+++ b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fcommits.json
@@ -0,0 +1,278 @@
+[
+ {
+ "sha": "676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
+ "commit": {
+ "author": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2016-04-03T15:54:55Z"
+ },
+ "committer": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2016-04-03T15:55:17Z"
+ },
+ "message": "Adds a directory.",
+ "tree": {
+ "sha": "f6deabf5e5e195c06d4e7820f4e24be11cb9ae40",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/f6deabf5e5e195c06d4e7820f4e24be11cb9ae40"
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/commits/676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
+ "comment_count": 0
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
+ "comments_url": "https://api.github.com/repos/potherca-bot/test-repository/commits/676a09fd1c7df28938e8c12dc5d9f3c3271f0249/comments",
+ "author": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "committer": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "parents": [
+ {
+ "sha": "19278cb740438ddeb2013af182e410270d98bb1a",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/19278cb740438ddeb2013af182e410270d98bb1a",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/19278cb740438ddeb2013af182e410270d98bb1a"
+ }
+ ]
+ },
+ {
+ "sha": "19278cb740438ddeb2013af182e410270d98bb1a",
+ "commit": {
+ "author": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2016-04-03T15:54:39Z"
+ },
+ "committer": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2016-04-03T15:55:12Z"
+ },
+ "message": "Adds a file.",
+ "tree": {
+ "sha": "54625561b164dd772eb072422904f2c56476dd50",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/54625561b164dd772eb072422904f2c56476dd50"
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/commits/19278cb740438ddeb2013af182e410270d98bb1a",
+ "comment_count": 0
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/19278cb740438ddeb2013af182e410270d98bb1a",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/19278cb740438ddeb2013af182e410270d98bb1a",
+ "comments_url": "https://api.github.com/repos/potherca-bot/test-repository/commits/19278cb740438ddeb2013af182e410270d98bb1a/comments",
+ "author": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "committer": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "parents": [
+ {
+ "sha": "2937e62cd3aa5d5ddce78fe47dffd819366807b5",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/2937e62cd3aa5d5ddce78fe47dffd819366807b5",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/2937e62cd3aa5d5ddce78fe47dffd819366807b5"
+ }
+ ]
+ },
+ {
+ "sha": "2937e62cd3aa5d5ddce78fe47dffd819366807b5",
+ "commit": {
+ "author": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2016-04-03T15:51:19Z"
+ },
+ "committer": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2016-04-03T15:51:19Z"
+ },
+ "message": "Adds README file.",
+ "tree": {
+ "sha": "84051791094ac74fed2dd68d4f7ab7754bcc7744",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/84051791094ac74fed2dd68d4f7ab7754bcc7744"
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/commits/2937e62cd3aa5d5ddce78fe47dffd819366807b5",
+ "comment_count": 0
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/2937e62cd3aa5d5ddce78fe47dffd819366807b5",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/2937e62cd3aa5d5ddce78fe47dffd819366807b5",
+ "comments_url": "https://api.github.com/repos/potherca-bot/test-repository/commits/2937e62cd3aa5d5ddce78fe47dffd819366807b5/comments",
+ "author": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "committer": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "parents": [
+ {
+ "sha": "f0520a2efe8cb04b343f564f957f393c6bda70fc",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/f0520a2efe8cb04b343f564f957f393c6bda70fc",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/f0520a2efe8cb04b343f564f957f393c6bda70fc"
+ }
+ ]
+ },
+ {
+ "sha": "f0520a2efe8cb04b343f564f957f393c6bda70fc",
+ "commit": {
+ "author": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2015-12-16T07:59:30Z"
+ },
+ "committer": {
+ "name": "Ben Peachey",
+ "email": "potherca@gmail.com",
+ "date": "2015-12-16T07:59:30Z"
+ },
+ "message": "Initial Commit.",
+ "tree": {
+ "sha": "4b825dc642cb6eb9a060e54bf8d69288fbee4904",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/4b825dc642cb6eb9a060e54bf8d69288fbee4904"
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/commits/f0520a2efe8cb04b343f564f957f393c6bda70fc",
+ "comment_count": 0
+ },
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/commits/f0520a2efe8cb04b343f564f957f393c6bda70fc",
+ "html_url": "https://github.com/potherca-bot/test-repository/commit/f0520a2efe8cb04b343f564f957f393c6bda70fc",
+ "comments_url": "https://api.github.com/repos/potherca-bot/test-repository/commits/f0520a2efe8cb04b343f564f957f393c6bda70fc/comments",
+ "author": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "committer": {
+ "login": "Potherca",
+ "id": 195757,
+ "avatar_url": "https://avatars.githubusercontent.com/u/195757?v=3",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/Potherca",
+ "html_url": "https://github.com/Potherca",
+ "followers_url": "https://api.github.com/users/Potherca/followers",
+ "following_url": "https://api.github.com/users/Potherca/following{/other_user}",
+ "gists_url": "https://api.github.com/users/Potherca/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/Potherca/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/Potherca/subscriptions",
+ "organizations_url": "https://api.github.com/users/Potherca/orgs",
+ "repos_url": "https://api.github.com/users/Potherca/repos",
+ "events_url": "https://api.github.com/users/Potherca/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/Potherca/received_events",
+ "type": "User",
+ "site_admin": false
+ },
+ "parents": [
+
+ ]
+ }
+]
\ No newline at end of file
diff --git a/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fcontents%2Fa-directory.json b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fcontents%2Fa-directory.json
new file mode 100644
index 0000000..d7fda39
--- /dev/null
+++ b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fcontents%2Fa-directory.json
@@ -0,0 +1,34 @@
+[
+ {
+ "name": "another-file.js",
+ "path": "a-directory/another-file.js",
+ "sha": "f542363e1b45aa7a33e5e731678dee18f7a1e729",
+ "size": 52,
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/contents/a-directory/another-file.js?ref=master",
+ "html_url": "https://github.com/potherca-bot/test-repository/blob/master/a-directory/another-file.js",
+ "git_url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/f542363e1b45aa7a33e5e731678dee18f7a1e729",
+ "download_url": "https://raw.githubusercontent.com/potherca-bot/test-repository/master/a-directory/another-file.js",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/potherca-bot/test-repository/contents/a-directory/another-file.js?ref=master",
+ "git": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/f542363e1b45aa7a33e5e731678dee18f7a1e729",
+ "html": "https://github.com/potherca-bot/test-repository/blob/master/a-directory/another-file.js"
+ }
+ },
+ {
+ "name": "readme.txt",
+ "path": "a-directory/readme.txt",
+ "sha": "27f8ec8435cb07992ecf18f9d5494ffc14948368",
+ "size": 31,
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/contents/a-directory/readme.txt?ref=master",
+ "html_url": "https://github.com/potherca-bot/test-repository/blob/master/a-directory/readme.txt",
+ "git_url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/27f8ec8435cb07992ecf18f9d5494ffc14948368",
+ "download_url": "https://raw.githubusercontent.com/potherca-bot/test-repository/master/a-directory/readme.txt",
+ "type": "file",
+ "_links": {
+ "self": "https://api.github.com/repos/potherca-bot/test-repository/contents/a-directory/readme.txt?ref=master",
+ "git": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/27f8ec8435cb07992ecf18f9d5494ffc14948368",
+ "html": "https://github.com/potherca-bot/test-repository/blob/master/a-directory/readme.txt"
+ }
+ }
+]
\ No newline at end of file
diff --git a/tests/fixtures/listContents-folder-recursive.json b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD%3Frecursive%3D1.json
similarity index 94%
rename from tests/fixtures/listContents-folder-recursive.json
rename to tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD%3Frecursive%3D1.json
index 785a69b..f350ce4 100644
--- a/tests/fixtures/listContents-folder-recursive.json
+++ b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD%3Frecursive%3D1.json
@@ -1,4 +1,5 @@
{
+ "original-source" : "https://api.github.com/repos/potherca-bot/test-repository/git/trees/HEAD?recursive=1",
"sha": "676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
"url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
"tree": [
@@ -17,6 +18,14 @@
"sha": "30b7e362894eecb159ce0ba2921a8363cd297213",
"url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/30b7e362894eecb159ce0ba2921a8363cd297213"
},
+ {
+ "path": "a-file.php",
+ "mode": "100755",
+ "type": "blob",
+ "sha": "c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1",
+ "size": 117,
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1"
+ },
{
"path": "a-directory/another-file.js",
"mode": "100755",
@@ -32,15 +41,7 @@
"sha": "27f8ec8435cb07992ecf18f9d5494ffc14948368",
"size": 31,
"url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/27f8ec8435cb07992ecf18f9d5494ffc14948368"
- },
- {
- "path": "a-file.php",
- "mode": "100755",
- "type": "blob",
- "sha": "c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1",
- "size": 117,
- "url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1"
}
],
"truncated": false
-}
\ No newline at end of file
+}
diff --git a/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD.json b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD.json
new file mode 100644
index 0000000..04252cf
--- /dev/null
+++ b/tests/fixtures/repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD.json
@@ -0,0 +1,30 @@
+{
+ "sha": "676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/676a09fd1c7df28938e8c12dc5d9f3c3271f0249",
+ "tree": [
+ {
+ "path": "README",
+ "mode": "100755",
+ "type": "blob",
+ "sha": "1ff3a296caf2d27828dd8c40673c88dbf99d4b3a",
+ "size": 58,
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/1ff3a296caf2d27828dd8c40673c88dbf99d4b3a"
+ },
+ {
+ "path": "a-directory",
+ "mode": "040000",
+ "type": "tree",
+ "sha": "30b7e362894eecb159ce0ba2921a8363cd297213",
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/trees/30b7e362894eecb159ce0ba2921a8363cd297213"
+ },
+ {
+ "path": "a-file.php",
+ "mode": "100755",
+ "type": "blob",
+ "sha": "c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1",
+ "size": 117,
+ "url": "https://api.github.com/repos/potherca-bot/test-repository/git/blobs/c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1"
+ }
+ ],
+ "truncated": false
+}
\ No newline at end of file
diff --git a/tests/integration-tests/compareToLocalCalls.php b/tests/integration-tests/compareToLocalCalls.php
index 720825f..98a5641 100644
--- a/tests/integration-tests/compareToLocalCalls.php
+++ b/tests/integration-tests/compareToLocalCalls.php
@@ -75,7 +75,7 @@ final public function provideFiles()
$localContents = $localResult->getContents();
/** @var array $contents */
$contents = $result->getContents();
- $this->compare($localContents, $contents);
+ $this->validateLocalAdapterValuesArePresentInGithubAdapterValues($localContents, $contents);
} elseif ($localResult instanceof \League\Flysystem\File) {
/** @var $localResult \League\Flysystem\File */
/** @var $result \League\Flysystem\File */
@@ -84,13 +84,14 @@ final public function provideFiles()
self::assertEquals($localResult, $result);
}
}],
+ 'getMetadata' => ['callback' => [$this, 'validateLocalAdapterValuesArePresentInGithubAdapterValues']],
'getMimetype' => [],
'getSize' => [],
//@FIXME: Synchronize local timestamp with remote git repo timestamp so "getTimestamp" can be tested
// 'getTimestamp' => [],
'getVisibility' => [],
'has' => [],
- 'listContents' => ['type' => 'dir', 'callback' => [$this, 'compare']],
+ 'listContents' => ['type' => 'dir', 'callback' => [$this, 'validateLocalAdapterValuesArePresentInGithubAdapterValues']],
'read' => ['type' => 'file'],
'readStream' => ['type' => 'file', 'callback' => function ($localStream, $githubStream){
self::assertEquals(stream_get_contents($localStream), stream_get_contents($githubStream));
@@ -112,6 +113,7 @@ final public function provideFiles()
}
}
}
+
ksort($files);
return $files;
@@ -147,21 +149,31 @@ private function createFixture()
* @param array $localContents
* @param array $contents
*/
- private function compare(array $localContents, array $contents)
+ private function validateLocalAdapterValuesArePresentInGithubAdapterValues(array $localContents, array $contents)
{
- array_walk($contents, 'ksort');
- array_walk($localContents, 'ksort');
-
- $localContents = array_map(function ($value) {
- unset($value['timestamp']);
- return $value;
- }, $localContents);
+ if (is_array(reset($localContents))) {
+ array_walk($contents, 'ksort');
+ array_walk($localContents, 'ksort');
+
+ $localContents = array_map(function ($value) {
+ unset($value['timestamp']);
+ return $value;
+ }, $localContents);
+ foreach ($localContents as $index => $localContent) {
+ foreach ($localContent as $key => $value) {
+ self::assertEquals([$key => $value], [$key => $contents[$index][$key]]);
+ }
+ }
+ } else {
+ ksort($contents);
+ ksort($localContents);
- foreach ($localContents as $index => $localContent) {
- foreach ($localContent as $key => $value) {
- self::assertEquals($value, $contents[$index][$key]);
+ unset($localContents['timestamp']);
+ foreach ($localContents as $index => $localContent) {
+ self::assertEquals([$index => $localContent], [$index => $contents[$index]]);
}
}
+
}
private function getLocalFileSystem()
diff --git a/tests/unit-tests/ApiTest.php b/tests/unit-tests/ApiTest.php
index c1c3a19..9e0635f 100644
--- a/tests/unit-tests/ApiTest.php
+++ b/tests/unit-tests/ApiTest.php
@@ -3,7 +3,9 @@
namespace Potherca\Flysystem\Github;
use Github\Api\ApiInterface;
+use Github\Api\GitData;
use Github\Api\GitData\Trees;
+use Github\Api\Repo;
use Github\Api\Repository\Commits;
use Github\Api\Repository\Contents;
use Github\Client;
@@ -14,15 +16,22 @@
* Tests for the Api class
*
* @coversDefaultClass \Potherca\Flysystem\Github\Api
+ *
* @covers ::
* @covers ::__construct
+ *
+ * @uses \Potherca\Flysystem\Github\Api::
*/
class ApiTest extends \PHPUnit_Framework_TestCase
{
////////////////////////////////// FIXTURES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- const MOCK_FILE_PATH = '/path/to/mock/file';
const MOCK_FILE_CONTENTS = 'Mock file contents';
- const MOCK_FOLDER_PATH = 'a-directory';
+ const MOCK_FILE_PATH = '/a-directory/another-file.js';
+ const MOCK_FOLDER_PATH = 'a-directory/';
+ const MOCK_PACKAGE = 'mockPackage';
+ const MOCK_REFERENCE = 'mockReference';
+ const MOCK_VENDOR = 'mockVendor';
+ const MOCK_BRANCH = 'mockBranch';
/** @var Api */
private $api;
@@ -44,7 +53,7 @@ protected function setUp()
/////////////////////////////////// TESTS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/**
- * @uses Potherca\Flysystem\Github\Api::exists
+ *
*/
final public function testApiShouldComplainWhenInstantiatedWithoutClient()
{
@@ -88,20 +97,16 @@ final public function testApiShouldUseValuesFromSettingsWhenAskingClientForFileC
$expected = self::MOCK_FILE_CONTENTS;
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
$this->prepareMockApi(
'download',
- $api::API_REPO,
- [$mockVendor, $mockPackage, self::MOCK_FILE_PATH, $mockReference],
+ $api::API_REPOSITORY,
+ [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FILE_PATH, '/'), self::MOCK_REFERENCE],
$expected
);
@@ -119,20 +124,16 @@ final public function testApiShouldUseValuesFromSettingsWhenAskingClientIfFileEx
$expected = self::MOCK_FILE_CONTENTS;
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
$this->prepareMockApi(
'exists',
- $api::API_REPO,
- [$mockVendor, $mockPackage, self::MOCK_FILE_PATH, $mockReference],
+ $api::API_REPOSITORY,
+ [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FILE_PATH, '/'), self::MOCK_REFERENCE],
$expected
);
@@ -182,20 +183,16 @@ final public function testApiShouldUseValuesFromSettingsWhenAskingClientForFileI
$expected = self::MOCK_FILE_CONTENTS;
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
$this->prepareMockApi(
'show',
- $api::API_REPO,
- [$mockVendor, $mockPackage, self::MOCK_FILE_PATH, $mockReference],
+ $api::API_REPOSITORY,
+ [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FILE_PATH, '/'), self::MOCK_REFERENCE],
$expected
);
@@ -229,30 +226,29 @@ final public function testApiShouldReturnMetadataForDirectoryWhenGivenPathIsDire
{
$api = $this->api;
- $mockPackage = 'mockPackage';
- $mockPath = self::MOCK_FOLDER_PATH;
- $mockReference = 'mockReference';
- $mockVendor = 'mockVendor';
+ $mockPath = trim(self::MOCK_FOLDER_PATH, '/');
$expectedUrl = sprintf(
'%s/repos/%s/%s/contents/%s?ref=%s',
$api::GITHUB_API_URL,
- $mockVendor,
- $mockPackage,
+ self::MOCK_VENDOR,
+ self::MOCK_PACKAGE,
$mockPath,
- $mockReference
+ self::MOCK_REFERENCE
);
$expectedHtmlUrl = sprintf(
'%s/%s/%s/blob/%s/%s',
$api::GITHUB_URL,
- $mockVendor,
- $mockPackage,
- $mockReference,
+ self::MOCK_VENDOR,
+ self::MOCK_PACKAGE,
+ self::MOCK_REFERENCE,
$mockPath
);
$expected = [
+ 'path' => $mockPath,
+ 'timestamp' => 1450252770,
'type' => $api::KEY_DIRECTORY,
'url' => $expectedUrl,
'html_url' => $expectedHtmlUrl,
@@ -260,21 +256,52 @@ final public function testApiShouldReturnMetadataForDirectoryWhenGivenPathIsDire
'self' => $expectedUrl,
'html' => $expectedHtmlUrl,
),
+ 'mode' => '040000',
+ 'sha' => '30b7e362894eecb159ce0ba2921a8363cd297213',
+ 'name' => 'a-directory',
+ 'visibility' => 'public',
+ 'contents' => false,
+ 'stream' => false,
];
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
- $this->prepareMockApi(
- 'show',
- $api::API_REPO,
- [$mockVendor, $mockPackage, $mockPath, $mockReference],
- [0 => null]
- );
+ $recursiveTreesFixture = $this->loadFixture('repos/potherca-bot/test-repository/git/trees/HEAD?recursive=1');
+
+ $files = array_column($recursiveTreesFixture['tree'], $api::KEY_PATH);
+
+ $this->addMocksToClient($this->mockClient, [
+ Repo::class => [
+ Commits::class => [
+ 'method' => 'all',
+ 'exactly' => count($files),
+ 'with' => self::callback(function($vendor, $package, $context) use ($files) {
+ return $vendor === self::MOCK_VENDOR && $package === self::MOCK_PACKAGE && $context['sha'] === null
+ && preg_match(sprintf('#%s#', implode('|', $files)), $context['path']) === 1;
+ }),
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/commits'),
+ ],
+ Contents::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FOLDER_PATH, '/'), self::MOCK_REFERENCE],
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/contents/a-directory'),
+ ],
+ ],
+ GitData::class => [
+ Trees::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => [self::MOCK_VENDOR, self::MOCK_PACKAGE, self::MOCK_REFERENCE, $api::RECURSIVE],
+
+ 'willReturn' => $recursiveTreesFixture,
+ ],
+ ],
+ ]);
$actual = $api->getMetaData($mockPath);
@@ -322,41 +349,120 @@ final public function testApiShouldPassOnExceptionsWhenAskingInfoForFileCausesAn
}
/**
- * @covers ::getTreeMetadata
+ * @covers ::getDirectoryContents
*
- * @uses Potherca\Flysystem\Github\Api::getCreatedTimestamp
+ * @dataProvider provideDirectoryContents
+ *
+ * @param array $data
+ */
+ final public function testApiShouldRetrieveExpectedDirectoryContentsWhenAskedToGetDirectoryContents(array $data)
+ {
+ $api = $this->api;
+
+ $this->prepareMockSettings([
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
+ ]);
+
+ $recursiveTreesFixture = $this->loadFixture('repos/potherca-bot/test-repository/git/trees/HEAD?recursive=1');
+
+ $files = array_column($recursiveTreesFixture['tree'], $api::KEY_PATH);
+
+ $this->addMocksToClient($this->mockClient, [
+ Repo::class => [
+ Commits::class => [
+ 'method' => 'all',
+ 'exactly' => count($files),
+ 'with' => self::callback(function($vendor, $package, $context) use ($files) {
+ return $vendor === self::MOCK_VENDOR && $package === self::MOCK_PACKAGE && $context['sha'] === null
+ && preg_match(sprintf('#%s#', implode('|', $files)), $context['path']) === 1;
+ }),
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/commits'),
+ ],
+ ],
+ GitData::class => [
+ Trees::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => [self::MOCK_VENDOR, self::MOCK_PACKAGE, self::MOCK_REFERENCE, $api::RECURSIVE],
+ 'willReturn' => $recursiveTreesFixture,
+ ],
+ ],
+ ]);
+
+ $actual = $api->getDirectoryContents($data['path'], $data['recursive']);
+
+ self::assertEquals($data['expected'], $actual);
+ }
+
+ /**
+ * @covers ::getDirectoryContents
*
* @dataProvider provideExpectedMetadata
*
* @param array $data
*/
- final public function testApiShouldRetrieveExpectedMetadataWhenAskedToGetTreeMetadata($data) {
+ final public function testApiShouldRetrieveExpectedMetadataWhenAskedToGetMetadata(array $data)
+ {
$api = $this->api;
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
- $this->prepareMockApi(
- 'show',
- $api::API_GIT_DATA,
- [$mockVendor, $mockPackage, $mockReference, true],
- $this->getMockApiTreeResponse($data['truncated'], $api),
- Trees::class
- );
+ $treesFixture = $this->loadFixture('repos/potherca-bot/test-repository/git/trees/HEAD?recursive=1');
+
+ $files = array_column($treesFixture['tree'], $api::KEY_PATH);
+
+ $mockApis = [
+ Repo::class => [
+ Commits::class => [
+ 'method' => 'all',
+ 'exactly' => count($files),
+ 'with' => self::callback(function($vendor, $package, $context) use ($files) {
+ return $vendor === self::MOCK_VENDOR && $package === self::MOCK_PACKAGE && $context['sha'] === null
+ && preg_match(sprintf('#%s#', implode('|', $files)), $context['path']) === 1;
+ }),
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/commits'),
+ ],
+ Contents::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => self::callback(function ($vendor, $package, $path, $reference) use ($files) {
+ return $vendor === self::MOCK_VENDOR && $package === self::MOCK_PACKAGE && $reference === self::MOCK_REFERENCE
+ && preg_match(sprintf('#%s#', implode('|', $files)), $path) === 1;
+ }),
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/contents/a-directory'),
+ ],
+ ],
+ GitData::class => [
+ Trees::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => [self::MOCK_VENDOR, self::MOCK_PACKAGE, self::MOCK_REFERENCE, $api::RECURSIVE],
+ 'willReturn' => $treesFixture,
+ ],
+ ],
+ ];
+
+// if ($data['count'] !== 0) {
+// $mockApis[Repo::class][Commits::class] = [
+// 'method' => 'all',
+// 'exactly' => $data['count'],
+// 'with' => self::callback(function ($vendor, $package, $context) use ($files) {
+// return $vendor === self::MOCK_VENDOR && $package === self::MOCK_PACKAGE && $context['sha'] === null
+// && preg_match(sprintf('#%s#', implode('|', $files)), $context['path']) === 1;
+// }),
+// 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/commits'),
+// ];
+// }
- $actual = $api->getTreeMetadata($data['path'], $data['recursive']);
+ $this->addMocksToClient($this->mockClient, $mockApis);
- $actual = array_map(function ($value) {
- $value['timestamp'] = null;
- return $value;
- }, $actual);
+ $actual = $api->getMetaData($data['path']);
self::assertEquals($data['expected'], $actual);
}
@@ -365,8 +471,6 @@ final public function testApiShouldRetrieveExpectedMetadataWhenAskedToGetTreeMet
* @covers ::guessMimeType
*
* @uses League\Flysystem\Util\MimeType
- * @uses Potherca\Flysystem\Github\Api::getFileContents
- * @uses Potherca\Flysystem\Github\Api::getMetaData
*/
final public function testApiShouldUseFileContentsToGuessMimeTypeWhenExtensionUnavailable()
{
@@ -374,14 +478,10 @@ final public function testApiShouldUseFileContentsToGuessMimeTypeWhenExtensionUn
$expected = 'image/png';
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
$image = imagecreatetruecolor(1,1);
@@ -393,8 +493,8 @@ final public function testApiShouldUseFileContentsToGuessMimeTypeWhenExtensionUn
$this->prepareMockApi(
'download',
- $api::API_REPO,
- [$mockVendor, $mockPackage, self::MOCK_FILE_PATH, $mockReference],
+ $api::API_REPOSITORY,
+ [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FILE_PATH, '/'), self::MOCK_REFERENCE],
$contents
);
@@ -407,8 +507,6 @@ final public function testApiShouldUseFileContentsToGuessMimeTypeWhenExtensionUn
* @covers ::guessMimeType
*
* @uses League\Flysystem\Util\MimeType
- * @uses Potherca\Flysystem\Github\Api::getFileContents
- * @uses Potherca\Flysystem\Github\Api::getMetaData
*/
final public function testApiShouldGuessMimeTypeCorrectlyWhenGivenPathIsDirectory()
{
@@ -416,22 +514,42 @@ final public function testApiShouldGuessMimeTypeCorrectlyWhenGivenPathIsDirector
$expected = $api::MIME_TYPE_DIRECTORY;
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
]);
- $this->prepareMockApi(
- 'show',
- $api::API_REPO,
- [$mockVendor, $mockPackage, self::MOCK_FOLDER_PATH, $mockReference],
- [0 => [$api::KEY_TYPE => $api::MIME_TYPE_DIRECTORY]]
- );
+ $treesFixture = $this->loadFixture('repos/potherca-bot/test-repository/git/trees/HEAD');
+ $files = array_column($treesFixture['tree'], $api::KEY_PATH);
+
+ $this->addMocksToClient($this->mockClient, [
+ Repo::class => [
+ Commits::class => [
+ 'method' => 'all',
+ 'exactly' => count($files),
+ 'with' => self::callback(function($vendor, $package, $context) use ($files) {
+ return $vendor === self::MOCK_VENDOR && $package === self::MOCK_PACKAGE && $context['sha'] === null
+ && preg_match(sprintf('#%s#', implode('|', $files)), $context['path']) === 1;
+ }),
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/commits'),
+ ],
+ Contents::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FOLDER_PATH, '/'), self::MOCK_REFERENCE],
+ 'willReturn' => $this->loadFixture('repos/potherca-bot/test-repository/contents/a-directory'),
+ ],
+ ],
+ GitData::class => [
+ Trees::class => [
+ 'method' => 'show',
+ 'exactly' => 1,
+ 'with' => [self::MOCK_VENDOR, self::MOCK_PACKAGE, self::MOCK_REFERENCE, $api::RECURSIVE],
+ 'willReturn' => $treesFixture,
+ ],
+ ],
+ ]);
$actual = $api->guessMimeType(self::MOCK_FOLDER_PATH);
@@ -439,27 +557,23 @@ final public function testApiShouldGuessMimeTypeCorrectlyWhenGivenPathIsDirector
}
/**
- * @uses Potherca\Flysystem\Github\Api::exists
+ *
*/
final public function testApiShouldUseCredentialsWhenTheyHaveBeenGiven()
{
$api = $this->api;
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockReference = 'reference';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getReference' => $mockReference,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getReference' => self::MOCK_REFERENCE,
'getCredentials' => ['foo']
]);
$this->prepareMockApi(
'exists',
- $api::API_REPO,
- [$mockVendor, $mockPackage, self::MOCK_FILE_PATH, $mockReference],
+ $api::API_REPOSITORY,
+ [self::MOCK_VENDOR, self::MOCK_PACKAGE, trim(self::MOCK_FILE_PATH, '/'), self::MOCK_REFERENCE],
''
);
@@ -490,25 +604,83 @@ private function getMockSettings()
->getMock();
}
+ private function addMocksToClient(MockObject $mockClient, array $apiCollection)
+ {
+ $parentApiCollection = [];
+
+ foreach ($apiCollection as $parentApiClass => $children) {
+
+ $mockParentApi = $this->getMockBuilder($parentApiClass)
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ foreach ($children as $childApiClass => $properties) {
+ $parts = explode('\\', $childApiClass);
+ $childApiName = strtolower(array_pop($parts));
+
+ $mockChildApi = $this->getMockBuilder($childApiClass)
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ $returnMethod = 'willReturn';
+ if (is_callable($properties['willReturn'])) {
+ $returnMethod = 'willReturnCallback';
+ }
+
+ $mockChildApi->expects(self::exactly($properties['exactly']))
+ ->method($properties['method'])
+ ->withConsecutive($properties['with'])
+ ->{$returnMethod}($properties['willReturn'])
+ ;
+
+ $mockParentApi->expects(self::exactly(1))
+ ->method($childApiName)
+ ->with()
+ ->willReturn($mockChildApi)
+ ;
+ }
+
+ $parts = explode('\\', $parentApiClass);
+ $parentApiName = strtolower(array_pop($parts));
+ $parentApiCollection[$parentApiName] = $mockParentApi;
+ }
+
+ $parentApiCount = count($parentApiCollection);
+ $parentApiNames = array_keys($parentApiCollection);
+ $parentApiNamesPattern = implode('|', $parentApiNames);
+
+ $mockClient->expects(self::exactly($parentApiCount))
+ ->method('api')
+ ->with(self::matchesRegularExpression(sprintf('/%s/i', $parentApiNamesPattern)))
+ ->willReturnCallback(function ($apiName) use ($parentApiCollection) {
+ return $parentApiCollection[strtolower($apiName)];
+ })
+ ;
+ }
+
/**
+ * @deprecated Use `addMocksToClient` instead.
+ *
* @param string $method
* @param string $apiName
* @param array $apiParameters
* @param mixed $apiOutput
- * @param string $repositoryClass
+ * @param string $childApiClass
*/
private function prepareMockApi(
$method,
$apiName,
$apiParameters,
$apiOutput,
- $repositoryClass = Contents::class
+ $childApiClass = Contents::class
) {
- $parts = explode('\\', $repositoryClass);
- $repositoryName = strtolower(array_pop($parts));
+ $parts = explode('\\', $childApiClass);
+ $childApiName = strtolower(array_pop($parts));
- $methods = [$repositoryName, 'getPerPage', 'setPerPage'];
+ $methods = [$childApiName, 'getPerPage', 'setPerPage'];
$shouldMockCommitsRepository = false;
if (in_array('commits', $methods, true) === false) {
@@ -516,17 +688,17 @@ private function prepareMockApi(
$methods[] = 'commits';
}
- $mockApi = $this->getMockBuilder(ApiInterface::class)
+ $mockParentApi = $this->getMockBuilder(ApiInterface::class)
->setMethods($methods)
->getMock()
;
- $mockRepository = $this->getMockBuilder($repositoryClass)
+ $mockChildApi = $this->getMockBuilder($childApiClass)
->disableOriginalConstructor()
->getMock()
;
- $mockRepository->expects(self::exactly(1))
+ $mockChildApi->expects(self::exactly(1))
->method($method)
->withAnyParameters()
->willReturnCallback(function () use ($apiParameters, $apiOutput) {
@@ -535,13 +707,13 @@ private function prepareMockApi(
})
;
- $mockApi->expects(self::exactly(1))
- ->method($repositoryName)
- ->willReturn($mockRepository)
+ $mockParentApi->expects(self::exactly(1))
+ ->method($childApiName)
+ ->willReturn($mockChildApi)
;
if ($shouldMockCommitsRepository === true) {
- $mockCommitsRepository = $this->getMockBuilder(Commits::class)
+ $mockCommitsApi = $this->getMockBuilder(Commits::class)
->disableOriginalConstructor()
->getMock()
;
@@ -551,21 +723,21 @@ private function prepareMockApi(
['commit' => ['committer' => ['date' => '20140202']]]
];
- $mockCommitsRepository->expects(self::any())
+ $mockCommitsApi->expects(self::any())
->method('all')
->withAnyParameters()
->willReturn($apiOutput)
;
- $mockApi->expects(self::any())
+ $mockParentApi->expects(self::any())
->method('commits')
- ->willReturn($mockCommitsRepository)
+ ->willReturn($mockCommitsApi)
;
}
$this->mockClient->expects(self::any())
->method('api')
->with(self::matchesRegularExpression(sprintf('/%s|repo/', $apiName)))
- ->willReturn($mockApi)
+ ->willReturn($mockParentApi)
;
}
@@ -582,66 +754,22 @@ private function prepareMockSettings(array $expectations)
}
}
- /**
- * @param bool $truncated
- * @param Api $api
- * @return array
- */
- private function getMockApiTreeResponse($truncated, Api $api)
- {
- return [
- $api::KEY_TREE => [
- [
- 'path' => self::MOCK_FILE_PATH,
- 'mode' => '100644',
- 'type' => 'tree',
- 'size' => 57,
- ],
- [
- 'path' => self::MOCK_FILE_PATH . 'Foo',
- 'basename' => self::MOCK_FILE_PATH . 'Foo',
- 'mode' => '100644',
- 'type' => 'blob',
- 'size' => 57,
- ],
- [
- 'path' => self::MOCK_FILE_PATH . '/Bar',
- 'name' => self::MOCK_FILE_PATH . '/Bar',
- 'mode' => '100644',
- 'type' => 'blob',
- 'size' => 57,
- ],
- [
- 'path' => 'some/other/file',
- 'mode' => '100644',
- 'type' => 'blob',
- 'size' => 747,
- ],
- ],
- 'truncated' => $truncated,
- ];
- }
-
private function prepareFixturesForTimeStamp()
{
date_default_timezone_set('UTC');
- $mockVendor = 'vendor';
- $mockPackage = 'package';
- $mockBranch = 'branch';
-
$this->prepareMockSettings([
- 'getVendor' => $mockVendor,
- 'getPackage' => $mockPackage,
- 'getBranch' => $mockBranch,
+ 'getVendor' => self::MOCK_VENDOR,
+ 'getPackage' => self::MOCK_PACKAGE,
+ 'getBranch' => self::MOCK_BRANCH,
]);
$apiParameters = [
- $mockVendor,
- $mockPackage,
+ self::MOCK_VENDOR,
+ self::MOCK_PACKAGE,
[
- 'sha' => $mockBranch,
- 'path' => self::MOCK_FILE_PATH
+ 'sha' => self::MOCK_BRANCH,
+ 'path' => trim(self::MOCK_FILE_PATH, '/')
]
];
@@ -654,7 +782,7 @@ private function prepareFixturesForTimeStamp()
$this->prepareMockApi(
'all',
- Api::API_REPO,
+ Api::API_REPOSITORY,
$apiParameters,
$apiOutput,
Commits::class
@@ -668,274 +796,195 @@ private function prepareFixturesForTimeStamp()
final public function provideExpectedMetadata()
{
return [
- 'Filepath, not recursive, not truncated' => [[
+ 'FilePath' => [[
+ 'count' => 0,
'path' => self::MOCK_FILE_PATH,
'expected' => [
- [
- 'path' => '/path/to/mock/file',
- 'mode' => '100644',
+ 'path' => 'a-directory/another-file.js',
+ 'mode' => '100755',
'type' => 'dir',
- 'size' => 57,
- 'name' => '/path/to/mock/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/fileFoo',
- 'basename' => '/path/to/mock/fileFoo',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/fileFoo',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/file/Bar',
- 'name' => '/path/to/mock/file/Bar',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
+ 'sha' => 'f542363e1b45aa7a33e5e731678dee18f7a1e729',
+ 'size' => 52,
+ 'url' => 'https://api.github.com/repos/mockVendor/mockPackage/contents/a-directory/another-file.js?ref=mockReference',
+ 'name' => 'a-directory/another-file.js',
'visibility' => 'public',
'contents' => false,
'stream' => false,
- 'timestamp' => null
+ 'timestamp' => 1450252770,
+ 'html_url' => 'https://github.com/mockVendor/mockPackage/blob/mockReference/a-directory/another-file.js',
+ '_links' => [
+ 'self' => 'https://api.github.com/repos/mockVendor/mockPackage/contents/a-directory/another-file.js?ref=mockReference',
+ 'html' => 'https://github.com/mockVendor/mockPackage/blob/mockReference/a-directory/another-file.js',
],
],
- 'recursive' => false,
- 'truncated' => false,
]],
- 'Filepath, recursive, not truncated' => [[
- 'path' => self::MOCK_FILE_PATH,
+ 'DirectoryPath' => [[
+ 'count' => 2,
+ 'path' => self::MOCK_FOLDER_PATH,
'expected' => [
- [
- 'path' => '/path/to/mock/file',
- 'mode' => '100644',
+ 'path' => 'a-directory',
+ 'mode' => '040000',
'type' => 'dir',
- 'size' => 57,
- 'name' => '/path/to/mock/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/fileFoo',
- 'basename' => '/path/to/mock/fileFoo',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/fileFoo',
+ 'sha' => '30b7e362894eecb159ce0ba2921a8363cd297213',
+ 'url' => 'https://api.github.com/repos/mockVendor/mockPackage/contents/a-directory?ref=mockReference',
+ 'name' => 'a-directory',
+ 'visibility' => 'public',
'contents' => false,
'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
+ 'timestamp' => 1450252770,
+ 'html_url' => 'https://github.com/mockVendor/mockPackage/blob/mockReference/a-directory',
+ '_links' => [
+ 'self' => 'https://api.github.com/repos/mockVendor/mockPackage/contents/a-directory?ref=mockReference',
+ 'html' => 'https://github.com/mockVendor/mockPackage/blob/mockReference/a-directory',
],
- [
- 'path' => '/path/to/mock/file/Bar',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/file/Bar',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ]
],
+ ]],
+ ];
+ }
+
+ final public function provideDirectoryContents()
+ {
+ $subDirectoryContent = [
+ [
+ 'path' => 'a-directory/another-file.js',
+ 'mode' => '100755',
+ 'type' => 'file',
+ 'size' => 52,
+ 'name' => 'a-directory/another-file.js',
+ 'contents' => false,
+ 'stream' => false,
+ 'timestamp' => 1450252770,
+ 'visibility' => 'public',
+ 'sha' => 'f542363e1b45aa7a33e5e731678dee18f7a1e729',
+ 'url' => 'https://api.github.com/repos/potherca-bot/test-repository/git/blobs/f542363e1b45aa7a33e5e731678dee18f7a1e729',
+ ],
+ [
+ 'path' => 'a-directory/readme.txt',
+ 'mode' => '100755',
+ 'type' => 'file',
+ 'size' => 31,
+ 'name' => 'a-directory/readme.txt',
+ 'contents' => false,
+ 'stream' => false,
+ 'timestamp' => 1450252770,
+ 'visibility' => 'public',
+ 'sha' => '27f8ec8435cb07992ecf18f9d5494ffc14948368',
+ 'url' => 'https://api.github.com/repos/potherca-bot/test-repository/git/blobs/27f8ec8435cb07992ecf18f9d5494ffc14948368',
+ ],
+ ];
+
+ $subDirectory = [
+ 'path' => 'a-directory',
+ 'mode' => '040000',
+ 'type' => 'dir',
+ 'name' => 'a-directory',
+ 'contents' => false,
+ 'stream' => false,
+ 'timestamp' => 1450252770,
+ 'visibility' => 'public',
+ 'sha' => '30b7e362894eecb159ce0ba2921a8363cd297213',
+ 'url' => 'https://api.github.com/repos/potherca-bot/test-repository/git/trees/30b7e362894eecb159ce0ba2921a8363cd297213',
+ ];
+
+ $nonRecursiveRepositoryContent = [
+ [
+ 'path' => 'README',
+ 'mode' => '100755',
+ 'type' => 'file',
+ 'size' => 58,
+ 'name' => 'README',
+ 'contents' => false,
+ 'stream' => false,
+ 'timestamp' => 1450252770,
+ 'visibility' => 'public',
+ 'sha' => '1ff3a296caf2d27828dd8c40673c88dbf99d4b3a',
+ 'url' => 'https://api.github.com/repos/potherca-bot/test-repository/git/blobs/1ff3a296caf2d27828dd8c40673c88dbf99d4b3a',
+ ],
+ $subDirectory,
+ [
+ 'path' => 'a-file.php',
+ 'mode' => '100755',
+ 'type' => 'file',
+ 'sha' => 'c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1',
+ 'size' => 117,
+ 'url' => 'https://api.github.com/repos/potherca-bot/test-repository/git/blobs/c6e6cd91e3ae40ab74883720a0d6cfb2af89e4b1',
+ 'name' => 'a-file.php',
+ 'visibility' => 'public',
+ 'contents' => false,
+ 'stream' => false,
+ 'timestamp' => 1450252770,
+ ],
+ ];
+
+ $recursiveRepositoryContent = array_merge($nonRecursiveRepositoryContent, $subDirectoryContent);
+
+ return [
+ // @TODO: Add Directory path?
+ 'Directorypath, not recursive, not truncated' => [[
+ //@TODO: Add sub-sub-directory so non-recursive directory contents can be properly tested
+ 'path' => self::MOCK_FOLDER_PATH,
+ 'expected' => array_merge([$subDirectory], $subDirectoryContent),
+ 'recursive' => false,
+ 'truncated' => false,
+ ]],
+ 'Directorypath, recursive, not truncated' => [[
+ 'path' => self::MOCK_FOLDER_PATH,
+ 'expected' => array_merge([$subDirectory], $subDirectoryContent),
'recursive' => true,
'truncated' => false,
]],
- 'Filepath, not recursive, truncated' => [[
- 'path' => self::MOCK_FILE_PATH,
- 'expected' => [
- [
- 'path' => '/path/to/mock/file',
- 'mode' => '100644',
- 'type' => 'dir',
- 'size' => 57,
- 'name' => '/path/to/mock/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/fileFoo',
- 'basename' => '/path/to/mock/fileFoo',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/fileFoo',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/file/Bar',
- 'name' => '/path/to/mock/file/Bar',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'visibility' => 'public',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null
- ],
- ],
+ 'No FilePath, not recursive, not truncated' => [[
+ 'path' => '',
+ 'expected' => $nonRecursiveRepositoryContent,
'recursive' => false,
- 'truncated' => true,
+ 'truncated' => false,
]],
- 'Filepath, recursive, truncated' => [[
- 'path' => self::MOCK_FILE_PATH,
- 'expected' => [
- [
- 'path' => '/path/to/mock/file',
- 'mode' => '100644',
- 'type' => 'dir',
- 'size' => 57,
- 'name' => '/path/to/mock/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/fileFoo',
- 'basename' => '/path/to/mock/fileFoo',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/fileFoo',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/file/Bar',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/file/Bar',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ]
- ],
- 'recursive' => true,
+ 'No FilePath, not recursive, truncated' => [[
+ 'path' => '',
+ 'expected' => $nonRecursiveRepositoryContent,
+ 'recursive' => false,
'truncated' => true,
]],
- 'No Filepath, recursive, not truncated' => [[
+ 'No FilePath, recursive, not truncated' => [[
'path' => '',
- 'expected' => [
- [
- 'path' => '/path/to/mock/file',
- 'mode' => '100644',
- 'type' => 'dir',
- 'size' => 57,
- 'name' => '/path/to/mock/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/fileFoo',
- 'basename' => '/path/to/mock/fileFoo',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/fileFoo',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/file/Bar',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/file/Bar',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => 'some/other/file',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 747,
- 'name' => 'some/other/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ]
- ],
+ 'expected' => $recursiveRepositoryContent,
'recursive' => true,
'truncated' => false,
]],
- 'No Filepath, recursive, truncated' => [[
+ 'No FilePath, recursive, truncated' => [[
'path' => '',
- 'expected' => [
- [
- 'path' => '/path/to/mock/file',
- 'mode' => '100644',
- 'type' => 'dir',
- 'size' => 57,
- 'name' => '/path/to/mock/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/fileFoo',
- 'basename' => '/path/to/mock/fileFoo',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/fileFoo',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => '/path/to/mock/file/Bar',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 57,
- 'name' => '/path/to/mock/file/Bar',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ],
- [
- 'path' => 'some/other/file',
- 'mode' => '100644',
- 'type' => 'file',
- 'size' => 747,
- 'name' => 'some/other/file',
- 'contents' => false,
- 'stream' => false,
- 'timestamp' => null,
- 'visibility' => 'public'
- ]
- ],
+ 'expected' => $recursiveRepositoryContent,
'recursive' => true,
'truncated' => true,
]],
];
}
+
+ /**
+ * @param $fixtureName
+ * @return mixed
+ */
+ private function loadFixture($fixtureName)
+ {
+ $fixtureName = urlencode($fixtureName);
+
+ $fixtureDirectory = sprintf('%s/fixtures', dirname(__DIR__));
+ $fixturePath = sprintf('%s/%s.json', $fixtureDirectory, $fixtureName);
+
+ if (is_file($fixturePath) === false) {
+ self::fail(
+ sprintf('Could not find file for fixture "%s"', $fixtureName)
+ );
+ } else {
+ $fixture = json_decode(file_get_contents($fixturePath), true);
+ $lastJsonError = json_last_error();
+ if ($lastJsonError !== JSON_ERROR_NONE) {
+ self::fail(
+ sprintf('Error Reading Fixture "%s": %s', $fixturePath, json_last_error_msg())
+ );
+ }
+ }
+
+ return $fixture;
+ }
}
diff --git a/tests/unit-tests/GithubAdapterTest.php b/tests/unit-tests/GithubAdapterTest.php
index afd1d72..3a2bfa2 100644
--- a/tests/unit-tests/GithubAdapterTest.php
+++ b/tests/unit-tests/GithubAdapterTest.php
@@ -35,6 +35,11 @@ protected function setup()
/////////////////////////////////// TESTS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
/**
+ * @param $method
+ * @param $apiMethod
+ * @param $parameters
+ * @param mixed $returnValue
+ *
* @covers ::has
* @covers ::read
* @covers ::listContents
@@ -45,21 +50,19 @@ protected function setup()
* @covers ::getVisibility
*
* @dataProvider provideReadMethods
- *
- * @param $method
- * @param $apiMethod
- * @param $parameters
- * @param mixed $returnValue
*/
- final public function testAdapterShouldPassParameterToClient($method, $apiMethod, $parameters, $returnValue = null)
- {
+ final public function testAdapterShouldPassParameterToClientWhenReadMethodsAreCalled(
+ $method,
+ $apiMethod,
+ $parameters,
+ $returnValue = null
+ ) {
if (is_string($returnValue) && is_file(sprintf('%s/../fixtures/%s.json', __DIR__, $returnValue))) {
$fixturePath = sprintf('%s/../fixtures/%s.json', __DIR__, $returnValue);
$fixture = json_decode(file_get_contents($fixturePath), true);
$returnValue = $fixture['tree'];
}
-
$mocker = $this->mockClient->expects(self::exactly(1))
->method($apiMethod)
->willReturn($returnValue)
@@ -78,15 +81,16 @@ final public function provideReadMethods()
return [
'has' => ['has', 'exists', [self::MOCK_FILE_PATH]],
'read' => ['read', 'getFileContents', [self::MOCK_FILE_PATH]],
- 'listContents - File' => ['listContents', 'getTreeMetadata', [self::MOCK_FILE_PATH, false]],
- 'listContents - File - recursive' => ['listContents', 'getTreeMetadata', [self::MOCK_FILE_PATH, true]],
- 'listContents - Folder' => ['listContents', 'getTreeMetadata', [self::MOCK_FOLDER_PATH, false], ''],
- 'listContents - Folder - recursive' => ['listContents', 'getTreeMetadata', [self::MOCK_FOLDER_PATH, true], 'listContents-folder-recursive'],
- 'getMetadata' => ['getMetadata', 'getMetadata', [self::MOCK_FILE_PATH]],
+ 'listContents - File' => ['listContents', 'getDirectoryContents', [self::MOCK_FILE_PATH, false]],
+ 'listContents - File - recursive' => ['listContents', 'getDirectoryContents', [self::MOCK_FILE_PATH, true]],
+ 'listContents - Folder' => ['listContents', 'getDirectoryContents', [self::MOCK_FOLDER_PATH, false], ''],
+ 'listContents - Folder - recursive' => ['listContents', 'getDirectoryContents', [self::MOCK_FOLDER_PATH, true], 'repos%2Fpotherca-bot%2Ftest-repository%2Fgit%2Ftrees%2FHEAD'],
+ 'getMetadata - File' => ['getMetadata', 'getMetadata', [self::MOCK_FILE_PATH]],
+ 'getMetadata - Folder' => ['getMetadata', 'getMetadata', [self::MOCK_FOLDER_PATH]],
'getSize' => ['getSize', 'getMetadata', [self::MOCK_FILE_PATH]],
'getMimetype' => ['getMimetype', 'guessMimeType', [self::MOCK_FILE_PATH]],
'getTimestamp' => ['getTimestamp', 'getLastUpdatedTimestamp', [self::MOCK_FILE_PATH]],
- 'getVisibility' => ['getVisibility', 'getTreeMetadata', [self::MOCK_FILE_PATH]],
+ 'getVisibility' => ['getVisibility', 'getDirectoryContents', [self::MOCK_FILE_PATH]],
];
}
}