diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d77b7520..b6e48a43 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -46,4 +46,4 @@ jobs:
run: composer run-script lint
- name: Execute the Composer test script
- run: composer run-script lint
+ run: composer run-script test
diff --git a/composer.json b/composer.json
index a7e4810a..7e04fc80 100644
--- a/composer.json
+++ b/composer.json
@@ -58,12 +58,14 @@
"vlucas/phpdotenv": "^5.2"
},
"require-dev": {
+ "brain/monkey": "^2.6",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"filp/whoops": "^2.9",
- "mikey179/vfsstream": "^1.6",
+ "mockery/mockery": "^1.4",
+ "pestphp/pest": "^1.0",
"phpcompatibility/php-compatibility": "^9.3",
- "phpunit/phpunit": "^8.5.8|^9.3.3",
"roave/security-advisories": "dev-master",
+ "spatie/temporary-directory": "^1.3",
"squizlabs/php_codesniffer": "^3.5"
},
"suggest": {
@@ -77,7 +79,7 @@
"scripts": {
"lint": "phpcs",
"lint:fix": "phpcbf",
- "test": "phpunit",
- "coverage": "phpunit --coverage-html coverage"
+ "test": "pest",
+ "coverage": "pest --coverage --coverage-html=coverage"
}
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 62960cd3..52fc223f 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -12,8 +12,8 @@
src/Illuminate/*
-
-
+
+
acorn.php
src
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 5a52bfae..e3be750b 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,5 +1,7 @@
-
- ./tests/Feature
- ./tests/Unit
+ ./tests
-
-
- ./
-
- ./
- ./config
- ./vendor
- ./tests
-
-
-
+
+
+ ./src
+
+
+ ./src/Illuminate/*
+
+
diff --git a/scripts/download-latest-laravel.sh b/scripts/download-latest-laravel.sh
new file mode 100755
index 00000000..4eef6797
--- /dev/null
+++ b/scripts/download-latest-laravel.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+set -e
+
+# pro tip: maybe don't run this script. i mostly just hacked my way through this. this should definitely not be automated in any way.
+
+# thx u https://explainshell.com/
+
+# YOINK! https://stackoverflow.com/a/4774063
+SCRIPTS_DIR="$(cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)"
+
+TEMP_DIR="${SCRIPTS_DIR}/.temp"
+
+LARAVEL_VERSION=$(curl --silent "https://api.github.com/repos/laravel/framework/tags" | jq -r '.[].name' | sort | tail -1)
+
+ARCHIVE_FILE="${LARAVEL_VERSION}.tar.gz"
+
+rm -rf "${TEMP_DIR}"
+mkdir -p "${TEMP_DIR}"
+
+wget -q "https://github.com/laravel/framework/archive/${ARCHIVE_FILE}" -O "${TEMP_DIR}/${ARCHIVE_FILE}"
+
+ROOT_FOLDER=$(tar ztf "${TEMP_DIR}/${ARCHIVE_FILE}" | sort | head -1)
+
+pushd "${TEMP_DIR}"
+
+# only extracts the Foundation folder
+tar xzf "${TEMP_DIR}/${ARCHIVE_FILE}" "${ROOT_FOLDER}src/Illuminate/Foundation" --strip-components=4 --one-top-level=Foundation
+
+popd
+
+# only syncs files that already exist in the destination
+rsync -a --existing "${TEMP_DIR}/Foundation/" "${SCRIPTS_DIR}/../src/Illuminate/Foundation/"
+
+rm -rf "${TEMP_DIR}"
diff --git a/src/Illuminate/Foundation/AliasLoader.php b/src/Illuminate/Foundation/AliasLoader.php
old mode 100644
new mode 100755
diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php
old mode 100644
new mode 100755
index ec1deae4..648cfc6b
--- a/src/Illuminate/Foundation/Application.php
+++ b/src/Illuminate/Foundation/Application.php
@@ -33,7 +33,7 @@ class Application extends Container implements ApplicationContract, CachesConfig
*
* @var string
*/
- const VERSION = '8.22.1';
+ const VERSION = '8.26.1';
/**
* The base path for the Laravel installation.
@@ -112,6 +112,13 @@ class Application extends Container implements ApplicationContract, CachesConfig
*/
protected $databasePath;
+ /**
+ * The custom language file path defined by the developer.
+ *
+ * @var string
+ */
+ protected $langPath;
+
/**
* The custom storage path defined by the developer.
*
@@ -407,7 +414,30 @@ public function useDatabasePath($path)
*/
public function langPath()
{
- return $this->resourcePath().DIRECTORY_SEPARATOR.'lang';
+ if ($this->langPath) {
+ return $this->langPath;
+ }
+
+ if (is_dir($path = $this->resourcePath().DIRECTORY_SEPARATOR.'lang')) {
+ return $path;
+ }
+
+ return $this->basePath().DIRECTORY_SEPARATOR.'lang';
+ }
+
+ /**
+ * Set the language file directory.
+ *
+ * @param string $path
+ * @return $this
+ */
+ public function useLangPath($path)
+ {
+ $this->langPath = $path;
+
+ $this->instance('path.lang', $path);
+
+ return $this;
}
/**
@@ -530,7 +560,7 @@ public function environment(...$environments)
}
/**
- * Determine if application is in local environment.
+ * Determine if the application is in the local environment.
*
* @return bool
*/
@@ -540,7 +570,7 @@ public function isLocal()
}
/**
- * Determine if application is in production environment.
+ * Determine if the application is in the production environment.
*
* @return bool
*/
@@ -1230,7 +1260,7 @@ public function setFallbackLocale($fallbackLocale)
}
/**
- * Determine if application locale is the given locale.
+ * Determine if the application locale is the given locale.
*
* @param string $locale
* @return bool
diff --git a/src/Illuminate/Foundation/Exceptions/Handler.php b/src/Illuminate/Foundation/Exceptions/Handler.php
index 761175d2..61a775a9 100644
--- a/src/Illuminate/Foundation/Exceptions/Handler.php
+++ b/src/Illuminate/Foundation/Exceptions/Handler.php
@@ -11,6 +11,8 @@
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract;
use Illuminate\Contracts\Support\Responsable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
+use Illuminate\Database\MultipleRecordsFoundException;
+use Illuminate\Database\RecordsNotFoundException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
@@ -19,7 +21,6 @@
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\View;
use Illuminate\Support\Reflector;
use Illuminate\Support\Traits\ReflectsClosures;
use Illuminate\Support\ViewErrorBag;
@@ -28,6 +29,13 @@
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Application as ConsoleApplication;
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
+use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
+use Symfony\Component\HttpFoundation\RedirectResponse as SymfonyRedirectResponse;
+use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
use Whoops\Handler\HandlerInterface;
use Whoops\Run as Whoops;
@@ -82,6 +90,8 @@ class Handler implements ExceptionHandlerContract
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
+ MultipleRecordsFoundException::class,
+ RecordsNotFoundException::class,
SuspiciousOperationException::class,
TokenMismatchException::class,
ValidationException::class,
@@ -362,6 +372,8 @@ protected function prepareException(Throwable $e)
$e = new HttpException(419, $e->getMessage(), $e);
} elseif ($e instanceof SuspiciousOperationException) {
$e = new NotFoundHttpException('Bad hostname provided.', $e);
+ } elseif ($e instanceof RecordsNotFoundException) {
+ $e = new NotFoundHttpException('Not found.', $e);
}
return $e;
diff --git a/src/Illuminate/Foundation/Exceptions/ReportableHandler.php b/src/Illuminate/Foundation/Exceptions/ReportableHandler.php
old mode 100755
new mode 100644
diff --git a/src/Illuminate/Foundation/ProviderRepository.php b/src/Illuminate/Foundation/ProviderRepository.php
old mode 100644
new mode 100755
diff --git a/src/Roots/Acorn/Application.php b/src/Roots/Acorn/Application.php
index 78f9d20e..037402e7 100644
--- a/src/Roots/Acorn/Application.php
+++ b/src/Roots/Acorn/Application.php
@@ -190,31 +190,6 @@ public function useConfigPath($path)
return $this;
}
- /**
- * Get the path to the language files.
- *
- * @return string
- */
- public function langPath()
- {
- return $this->langPath ?: $this->resourcePath('lang');
- }
-
- /**
- * Set the path to the language files.
- *
- * @param string $path
- * @return $this
- */
- public function useLangPath($path)
- {
- $this->langPath = $path;
-
- $this->instance('path.lang', $path);
-
- return $this;
- }
-
/**
* Get the path to the public / web directory.
*
@@ -286,7 +261,7 @@ protected function registerBaseServiceProviders()
*/
public function isDownForMaintenance()
{
- return is_file($this->storagePath() . '/framework/down') || is_file(ABSPATH . '/.maintenance');
+ return is_file($this->storagePath() . '/framework/down') || (defined('ABSPATH') && is_file(constant('ABSPATH') . '/.maintenance'));
}
/**
diff --git a/src/Roots/Acorn/Filesystem/Filesystem.php b/src/Roots/Acorn/Filesystem/Filesystem.php
index 5bb7d014..c00a42e2 100644
--- a/src/Roots/Acorn/Filesystem/Filesystem.php
+++ b/src/Roots/Acorn/Filesystem/Filesystem.php
@@ -83,7 +83,7 @@ public function getRelativePath($basePath, $targetPath)
$path = str_repeat('../', count($sourceDirs)) . implode('/', $targetDirs);
return $path === '' || $path[0] === '/'
- || ($colonPos = strpos($path, ':')) !== false && (($slashPos = strpos($path, '/') >= $colonPos)
+ || ($colonPos = strpos($path, ':')) !== false && ($colonPos < ($slashPos = strpos($path, '/'))
|| $slashPos === false)
? "./$path" : $path;
}
diff --git a/tests/Application/AliasLoaderTest.php b/tests/Application/AliasLoaderTest.php
new file mode 100644
index 00000000..cf60f884
--- /dev/null
+++ b/tests/Application/AliasLoaderTest.php
@@ -0,0 +1,19 @@
+toBeFalse();
+ expect(function_exists('asset'))->toBeFalse();
+ expect(function_exists('config'))->toBeFalse();
+ expect(function_exists('view'))->toBeFalse();
+
+ $loader->register();
+
+ expect(function_exists('app'))->toBeTrue();
+ expect(function_exists('asset'))->toBeTrue();
+ expect(function_exists('config'))->toBeTrue();
+ expect(function_exists('view'))->toBeTrue();
+});
diff --git a/tests/Application/ApplicationTest.php b/tests/Application/ApplicationTest.php
new file mode 100644
index 00000000..202d169f
--- /dev/null
+++ b/tests/Application/ApplicationTest.php
@@ -0,0 +1,142 @@
+toBeInstanceOf(LazyLoader::class);
+});
+
+it('instantiates with custom paths', function () {
+ $app = new Application(null, [
+ 'app' => $this->fixture('use_paths/app'),
+ 'config' => $this->fixture('use_paths/config'),
+ ]);
+
+ expect($app['path'])->toBe($this->fixture('use_paths/app'));
+ expect($app['path.config'])->toBe($this->fixture('use_paths/config'));
+});
+
+it('rejects invalid custom path types', function () {
+ $app = new Application();
+
+ $app->usePaths([
+ 'app' => $this->fixture('use_paths/app'),
+ 'not_a_valid_path_type' => $this->fixture('use_paths/resources/lang'),
+ ]);
+})->throws(Exception::class);
+
+it('rejects invalid custom paths', function () {
+ $app = new Application();
+
+ $app->usePaths([
+ 'app' => $this->fixture('use_paths/app'),
+ 'lang' => __DIR__ . '/this/does/not/exist',
+ ]);
+})->throws(Exception::class);
+
+it('accepts an array of custom paths', function () {
+ $app = new Application(temp('base_path'));
+
+ expect($app['path'])->not->toBe($this->fixture('use_paths/app'));
+ expect($app['path.lang'])->not->toBe($this->fixture('use_paths/resources/lang'));
+ expect($app['path.config'])->not->toBe($this->fixture('use_paths/config'));
+ expect($app['path.public'])->not->toBe($this->fixture('use_paths/public'));
+ expect($app['path.storage'])->not->toBe($this->fixture('use_paths/storage'));
+ expect($app['path.database'])->not->toBe($this->fixture('use_paths/database'));
+ expect($app['path.resources'])->not->toBe($this->fixture('use_paths/resources'));
+ expect($app['path.bootstrap'])->not->toBe($this->fixture('use_paths/bootstrap'));
+
+ $app->usePaths([
+ 'app' => $this->fixture('use_paths/app'),
+ 'lang' => $this->fixture('use_paths/resources/lang'),
+ 'config' => $this->fixture('use_paths/config'),
+ 'public' => $this->fixture('use_paths/public'),
+ 'storage' => $this->fixture('use_paths/storage'),
+ 'database' => $this->fixture('use_paths/database'),
+ 'resources' => $this->fixture('use_paths/resources'),
+ 'bootstrap' => $this->fixture('use_paths/bootstrap'),
+ ]);
+
+ expect($app['path'])->toBe($this->fixture('use_paths/app'));
+ expect($app['path.lang'])->toBe($this->fixture('use_paths/resources/lang'));
+ expect($app['path.config'])->toBe($this->fixture('use_paths/config'));
+ expect($app['path.public'])->toBe($this->fixture('use_paths/public'));
+ expect($app['path.storage'])->toBe($this->fixture('use_paths/storage'));
+ expect($app['path.database'])->toBe($this->fixture('use_paths/database'));
+ expect($app['path.resources'])->toBe($this->fixture('use_paths/resources'));
+ expect($app['path.bootstrap'])->toBe($this->fixture('use_paths/bootstrap'));
+});
+
+it('allows specific paths to be changed', function () {
+ $app = new Application(temp('not_a_path'));
+
+ expect($app['path.bootstrap'])->not->toBe($this->fixture('use_paths/bootstrap'));
+ $app->useBootstrapPath($this->fixture('use_paths/bootstrap'));
+ expect($app['path.bootstrap'])->toBe($this->fixture('use_paths/bootstrap'));
+
+ expect($app['path.config'])->not->toBe($this->fixture('use_paths/config'));
+ $app->useConfigPath($this->fixture('use_paths/config'));
+ expect($app['path.config'])->toBe($this->fixture('use_paths/config'));
+
+ expect($app['path.public'])->not->toBe($this->fixture('use_paths/public'));
+ $app->usePublicPath($this->fixture('use_paths/public'));
+ expect($app['path.public'])->toBe($this->fixture('use_paths/public'));
+
+ expect($app['path.resources'])->not->toBe($this->fixture('use_paths/resource'));
+ $app->useResourcePath($this->fixture('use_paths/resource'));
+ expect($app['path.resources'])->toBe($this->fixture('use_paths/resource'));
+});
+
+it('goes down for maintenance when acorn maintenance file exists', function () {
+ $app = new Application();
+
+ expect($app->isDownForMaintenance())->toBeFalse();
+
+ $app->useStoragePath($this->fixture('is_down_for_maintenance/storage'));
+
+ expect($app->isDownForMaintenance())->toBeTrue();
+});
+
+it('goes down for maintenance when wordpress maintenance file exists', function () {
+ $app = new Application();
+
+ expect($app->isDownForMaintenance())->toBeFalse();
+
+ touch(temp(('wp/.maintenance')));
+
+ expect($app->isDownForMaintenance())->toBeTrue();
+});
+
+it('throws an exception if app namespace cannot be determined', function () {
+ (new Application($this->fixture('get_namespace/a_bedrock_site/a_random_library')))->getNamespace();
+})->throws(RuntimeException::class);
+
+it('determines namespace based on app composer.json', function () {
+ $app = new Application($this->fixture('get_namespace/a_sage_theme'));
+
+ expect($app->getNamespace())->toBe('Sage\\');
+});
+
+it('determines namespace based on app ancestor composer.json', function () {
+ $app = new Application($this->fixture('get_namespace/a_bedrock_site/a_sage_theme'));
+
+ expect($app->getNamespace())->toBe('Bedrock\\Sage\\');
+});
+
+it('allows the app namespace to changed arbitrarily', function () {
+ $app = new Application($this->fixture('get_namespace/a_sage_theme'));
+
+ expect($app->getNamespace())->not->toBe('App\\');
+
+ $app->useNamespace('App');
+
+ expect($app->getNamespace())->toBe('App\\');
+});
diff --git a/tests/Application/__fixtures__/get_namespace/a_bedrock_site/a_random_library/composer.json b/tests/Application/__fixtures__/get_namespace/a_bedrock_site/a_random_library/composer.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/tests/Application/__fixtures__/get_namespace/a_bedrock_site/a_random_library/composer.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/tests/Application/__fixtures__/get_namespace/a_bedrock_site/a_sage_theme/app/.gitignore b/tests/Application/__fixtures__/get_namespace/a_bedrock_site/a_sage_theme/app/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/get_namespace/a_bedrock_site/a_sage_theme/app/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/get_namespace/a_bedrock_site/composer.json b/tests/Application/__fixtures__/get_namespace/a_bedrock_site/composer.json
new file mode 100644
index 00000000..7400d224
--- /dev/null
+++ b/tests/Application/__fixtures__/get_namespace/a_bedrock_site/composer.json
@@ -0,0 +1,7 @@
+{
+ "autoload": {
+ "psr-4": {
+ "Bedrock\\Sage\\": "a_sage_theme/app/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Application/__fixtures__/get_namespace/a_sage_theme/app/.gitignore b/tests/Application/__fixtures__/get_namespace/a_sage_theme/app/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/get_namespace/a_sage_theme/app/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/get_namespace/a_sage_theme/composer.json b/tests/Application/__fixtures__/get_namespace/a_sage_theme/composer.json
new file mode 100644
index 00000000..44970e72
--- /dev/null
+++ b/tests/Application/__fixtures__/get_namespace/a_sage_theme/composer.json
@@ -0,0 +1,7 @@
+{
+ "autoload": {
+ "psr-4": {
+ "Sage\\": "app/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Application/__fixtures__/is_down_for_maintenance/storage/framework/down b/tests/Application/__fixtures__/is_down_for_maintenance/storage/framework/down
new file mode 100644
index 00000000..8337712e
--- /dev/null
+++ b/tests/Application/__fixtures__/is_down_for_maintenance/storage/framework/down
@@ -0,0 +1 @@
+//
diff --git a/tests/Application/__fixtures__/is_down_for_maintenance/wp/.maintenance b/tests/Application/__fixtures__/is_down_for_maintenance/wp/.maintenance
new file mode 100644
index 00000000..8337712e
--- /dev/null
+++ b/tests/Application/__fixtures__/is_down_for_maintenance/wp/.maintenance
@@ -0,0 +1 @@
+//
diff --git a/tests/Application/__fixtures__/use_paths/app/.gitignore b/tests/Application/__fixtures__/use_paths/app/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/app/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/use_paths/bootstrap/cache/.gitignore b/tests/Application/__fixtures__/use_paths/bootstrap/cache/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/bootstrap/cache/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/use_paths/config/.gitignore b/tests/Application/__fixtures__/use_paths/config/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/config/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/use_paths/database/.gitignore b/tests/Application/__fixtures__/use_paths/database/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/database/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/use_paths/public/.gitignore b/tests/Application/__fixtures__/use_paths/public/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/public/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/use_paths/resources/lang/.gitignore b/tests/Application/__fixtures__/use_paths/resources/lang/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/resources/lang/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Application/__fixtures__/use_paths/storage/.gitignore b/tests/Application/__fixtures__/use_paths/storage/.gitignore
new file mode 100644
index 00000000..d6b7ef32
--- /dev/null
+++ b/tests/Application/__fixtures__/use_paths/storage/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php
new file mode 100644
index 00000000..687be72e
--- /dev/null
+++ b/tests/Assets/AssetTest.php
@@ -0,0 +1,3 @@
+normalizePath('/a//b///c/d//e'))
+ ->toEqual('/a/b/c/d/e');
+});
+
+it('should normalize paths separated by backslashes', function () {
+ expect((new Filesystem())->normalizePath('/a\\\\b\\\\c/d//e'))
+ ->toEqual('/a/b/c/d/e');
+});
+
+it('should normalize paths to arbitrary separator', function () {
+ expect((new Filesystem())->normalizePath('/a\\\\b\\\\c/d//e', '|'))
+ ->toEqual('|a|b|c|d|e');
+});
+
+it('should find the closest path within the filesystem', function () {
+ expect((new Filesystem())->closest($this->fixture('closest/a/b'), 'kjo.txt'))
+ ->toEqual($this->fixture('closest/kjo.txt'));
+
+ expect((new Filesystem())->closest($this->fixture('closest/a/b'), 'bdubs.txt'))
+ ->toEqual($this->fixture('closest/a/b/bdubs.txt'));
+
+ expect((new Filesystem())->closest($this->fixture('closest/a/b'), 'apray.txt'))
+ ->toBeNull();
+});
+
+it('should determine the relative path between two absolute paths', function () {
+ expect((new Filesystem())->getRelativePath('/dir_a/dir_b/', '/dir_a/dir_b/dir_c/file_d'))
+ ->toEqual('dir_c/file_d');
+
+ expect((new Filesystem())->getRelativePath('/dir_a/dir_b/dir_c/dir_d/', '/dir_a/dir_b/'))
+ ->toEqual('../../');
+
+ expect((new Filesystem())->getRelativePath('/dir_a/dir_b/', '/dir_a/file_kjo'))
+ ->toEqual('../file_kjo');
+
+ expect((new Filesystem())->getRelativePath('/dir_a/dir_b/', '/dir_a/dir_b/'))
+ ->toEqual('');
+});
diff --git a/tests/Unit/__fixtures__/view.php b/tests/Filesystem/__fixtures__/closest/a/b/bdubs.txt
similarity index 100%
rename from tests/Unit/__fixtures__/view.php
rename to tests/Filesystem/__fixtures__/closest/a/b/bdubs.txt
diff --git a/tests/Filesystem/__fixtures__/closest/kjo.txt b/tests/Filesystem/__fixtures__/closest/kjo.txt
new file mode 100644
index 00000000..ab0c0141
--- /dev/null
+++ b/tests/Filesystem/__fixtures__/closest/kjo.txt
@@ -0,0 +1 @@
+//
\ No newline at end of file
diff --git a/tests/Sage/SageTest.php b/tests/Sage/SageTest.php
new file mode 100644
index 00000000..13b65ece
--- /dev/null
+++ b/tests/Sage/SageTest.php
@@ -0,0 +1,3 @@
+booted($booted);
- $app->booting($booting);
-
- /** initial boot sets counts to 1 */
- $app->boot();
- $this->assertEquals(1, $bootedCount);
- $this->assertEquals(1, $bootingCount);
-
- /** subsequent boot attempt skips firing callbacks */
- $app->boot();
- $this->assertEquals(1, $bootedCount);
- $this->assertEquals(1, $bootingCount);
- }
-}
diff --git a/tests/Unit/AssetDirectiveTest.php b/tests/Unit/AssetDirectiveTest.php
deleted file mode 100644
index 17f56209..00000000
--- a/tests/Unit/AssetDirectiveTest.php
+++ /dev/null
@@ -1,17 +0,0 @@
-assertEquals("= \Roots\asset('scripts/app.js'); ?>", $directive("'scripts/app.js'"));
- $this->assertEquals('= \Roots\asset($file); ?>', $directive('$file'));
- }
-}
diff --git a/tests/Unit/Assets/AssetTest.php b/tests/Unit/Assets/AssetTest.php
deleted file mode 100644
index 3cd46f28..00000000
--- a/tests/Unit/Assets/AssetTest.php
+++ /dev/null
@@ -1,40 +0,0 @@
-contents());
- }
-
- public function testGetReturnsFalseIfNotExists(): void
- {
- $asset = new Asset('foo', 'bar');
-
- self::assertFalse($asset->get());
- }
-
- public function testIncludedFileContentIsReturned(): void
- {
- $temp = stream_get_meta_data(tmpfile())['uri'];
- file_put_contents($temp, " 'bar'];\n");
- $asset = new Asset($temp, 'bar');
-
- self::assertSame(['foo' => 'bar'], $asset->get());
- }
-
- public function testCastsToUri(): void
- {
- $asset = new Asset('foo', 'bar');
-
- self::assertSame('bar', (string)$asset);
- }
-
-}
diff --git a/tests/Unit/Assets/AssetsManagerTest.php b/tests/Unit/Assets/AssetsManagerTest.php
deleted file mode 100644
index e5ca1e5b..00000000
--- a/tests/Unit/Assets/AssetsManagerTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-manager->register('foo', $expected);
-
- self::assertSame($expected, $this->manager->manifest('foo'));
- }
-
- public function testCustomCreatorIsCalledWhenStrategyIsRegistered(): void
- {
- $expected = new RelativePathManifest('', '');
- $this->manager->extend('foo', function () use ($expected): Manifest {
- return $expected;
- });
-
- self::assertSame($expected, $this->manager->manifest('bar', ['strategy' => 'foo']));
- }
-
- public function testConfig(): void
- {
- $expected = new RelativePathManifest('', '');
- $manager = new AssetsManager(
- new ContainerStub(['config' => ['assets.manifests.foo' => ['strategy' => 'bar']]])
- );
- $manager->extend('bar', function () use ($expected): Manifest {
- return $expected;
- });
-
- self::assertSame($expected, $manager->manifest('foo', null));
- }
-
- public function testGetDefaultManifest(): void
- {
- $manager = new AssetsManager(new ContainerStub(['config' => ['assets.default' => 'foo']]));
-
- self::assertSame('foo', $manager->getDefaultManifest());
- }
-
- public function testMissingStrategyThrowsException(): void
- {
- $this->expectException(InvalidArgumentException::class);
-
- $this->manager->manifest('foo', ['strategy' => 'bar']);
- }
-
- public function testManifestGetsCalled(): void
- {
- $spy = new ManifestSpy();
- $manager = new AssetsManager(new ContainerStub(['config' => ['assets.default' => 'default']]));
- $manager->register('default', $spy);
-
- $manager->foobar();
-
- $calls = $spy->getCallLog();
- self::assertArrayHasKey('foobar', $calls);
- self::assertSame(1, $calls['foobar']);
- }
-
- protected function setUp(): void
- {
- parent::setUp();
- $app = new Application();
- $this->manager = new AssetsManager($app);
- }
-}
diff --git a/tests/Unit/Assets/AssetsServiceProviderTest.php b/tests/Unit/Assets/AssetsServiceProviderTest.php
deleted file mode 100644
index 15699d29..00000000
--- a/tests/Unit/Assets/AssetsServiceProviderTest.php
+++ /dev/null
@@ -1,61 +0,0 @@
- '/* javascript */',
- '/app/themes/sage/dist/styles/app.css' => '/* css */',
- ];
-
- public function testRegister(): void
- {
- $app = new Application();
- $app->bind(
- 'config',
- function (): array {
- return [
- 'assets.default' => 'test',
- 'assets.manifests.test' => ['manifest' => '', 'path' => 'test', 'uri' => 'test'],
- ];
- }
- );
- $app->bind(
- 'files',
- function (): Filesystem {
- return new Filesystem();
- }
- );
- $service = new AssetsServiceProvider($app);
-
- $service->register();
-
- self::assertInstanceOf(AssetsManager::class, $app->get('assets'));
- self::assertInstanceOf(Manifest::class, $app->get('assets.manifest'));
- }
-
- public function setUp(): void
- {
- $this->fsSetUp();
- $jsonManifest = json_encode(
- [
- 'scripts/app.js' => 'scripts/app-123456.js',
- 'styles/app.css' => 'styles/app.css?id=123456',
- ]
- );
- $this->write('/app/themes/sage/dist/assets.json', $jsonManifest);
- }
-}
diff --git a/tests/Unit/Assets/RelativePathManifestTest.php b/tests/Unit/Assets/RelativePathManifestTest.php
deleted file mode 100644
index 366278bb..00000000
--- a/tests/Unit/Assets/RelativePathManifestTest.php
+++ /dev/null
@@ -1,105 +0,0 @@
-manifest->offsetGet('foo');
-
- self::assertSame('/foo', $asset->path());
- self::assertSame('/foo', $asset->uri());
- }
-
- public function testOffsetSet(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
- $asset = $this->manifest->offsetGet('foo');
-
- self::assertSame('/bar', $asset->path());
- self::assertSame('/bar', $asset->uri());
- }
-
- public function testOffsetUnset(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
- $this->manifest->offsetUnset('foo');
- $asset = $this->manifest->offsetGet('foo');
-
- self::assertSame('/foo', $asset->path());
- self::assertSame('/foo', $asset->uri());
- }
-
- public function testOffsetExistsTrue(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
-
- self::assertTrue($this->manifest->offsetExists('foo'));
- }
-
- public function testOffsetExistsFalse(): void
- {
- self::assertFalse($this->manifest->offsetExists('foo'));
- }
-
- public function testCountIsZeroWhenNothingAdded(): void
- {
- self::assertSame(0, $this->manifest->count());
- }
-
- public function testCountIsAsExpected(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
-
- self::assertSame(1, $this->manifest->count());
- }
-
- public function testGetIterator(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
-
- $iterator = $this->manifest->getIterator();
- self::assertTrue($iterator->offsetExists('foo'));
- self::assertSame('bar', $iterator->offsetGet('foo'));
- }
-
- public function testToArray(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
-
- $array = $this->manifest->toArray();
- self::assertArrayHasKey('foo', $array);
- self::assertSame('bar', $array['foo']);
- }
-
- public function testToJson(): void
- {
- $this->manifest->offsetSet('foo', 'bar');
-
- $json = $this->manifest->toJson();
- $decoded = json_decode($json, true);
- self::assertArrayHasKey('foo', $decoded);
- self::assertSame('bar', $decoded['foo']);
- }
-
- public function testJsonSerializeReturnsSameDataAsToJson(): void
- {
- self::assertSame(json_encode($this->manifest, true), $this->manifest->toJson());
- }
-
- protected function setUp(): void
- {
- parent::setUp();
- $this->manifest = new RelativePathManifest($this->path, $this->uri);
- }
-
-}
diff --git a/tests/Unit/AssetsTest.php b/tests/Unit/AssetsTest.php
deleted file mode 100644
index 59b816eb..00000000
--- a/tests/Unit/AssetsTest.php
+++ /dev/null
@@ -1,107 +0,0 @@
- '/* javascript */',
- '/app/themes/sage/dist/styles/app.css' => '/* css */',
- ];
-
- public function setUp() : void
- {
- $this->fsSetUp();
- $jsonManifest = json_encode([
- 'scripts/app.js' => 'scripts/app-123456.js',
- 'styles/app.css' => 'styles/app.css?id=123456',
- ]);
- $this->write('/app/themes/sage/dist/assets.json', $jsonManifest);
- }
-
- /** @test */
- public function an_asset_should_strip_query_string_from_its_path()
- {
- $asset = $this->asset('scripts/app.js?id=123456');
-
- $this->assertEquals(get_theme_file_path('/scripts/app.js'), $asset->path());
- }
-
- /** @test */
- public function an_asset_should_return_its_contents()
- {
- $path = 'dist/scripts/app.js';
- $contents = '/** my app */';
- file_put_contents(get_theme_file_path($path), $contents);
-
- $this->assertEquals($contents, $this->asset($path)->contents());
- }
-
- /** @test */
- public function an_asset_should_determine_whether_it_exists()
- {
- $asset = $this->asset('dist/scripts/app-123456.js');
- $asset2 = $this->asset('dist/scripts/notafile.js');
-
- $this->assertTrue($asset->exists());
- $this->assertFalse($asset2->exists());
- }
-
- /** @test */
- public function an_asset_should_return_its_path_and_uri()
- {
- $asset = $this->asset('scripts/app.js', 'scripts/app.js?id=123456');
-
- $this->assertEquals(get_theme_file_path('scripts/app.js'), $asset->path());
- $this->assertEquals(get_theme_file_uri('scripts/app.js?id=123456'), $asset->uri());
- }
-
- /** @test */
- public function a_relative_path_manifest_should_prepend_a_base_path_and_uri()
- {
- $path = get_theme_file_path('dist');
- $uri = get_theme_file_uri('dist');
- $manifest = new \Roots\Acorn\Assets\RelativePathManifest($path, $uri, [
- 'scripts/app.js' => 'scripts/app-123456.js'
- ]);
-
- $this->assertEquals($manifest->uri(), $uri);
- $this->assertEquals($manifest->path(), $path);
- $this->assertEquals($manifest->get('scripts/app.js')->uri(), "{$uri}/scripts/app-123456.js");
- $this->assertEquals($manifest->get('scripts/app.js')->path(), "{$path}/scripts/app-123456.js");
- }
-
- /** @test */
- public function asset_manager_should_resolve_manifest()
- {
- $app = new \Roots\Acorn\Application();
- $app->singleton('files', \Roots\Acorn\Filesystem\Filesystem::class);
-
- $assets = new \Roots\Acorn\Assets\AssetsManager($app);
-
- $manifest = $assets->manifest('my-manifest', [
- 'strategy' => 'relative',
- 'manifest' => get_theme_file_path('dist/assets.json'),
- 'path' => get_theme_file_path('dist'),
- 'uri' => get_theme_file_uri('dist'),
- ]);
-
- $this->assertInstanceOf(\Roots\Acorn\Assets\RelativePathManifest::class, $manifest);
- }
-
- /**
- * @param string $path
- * @return \Roots\Acorn\Assets\Asset
- */
- protected function asset($path, $uri = null)
- {
- return new \Roots\Acorn\Assets\Asset(get_theme_file_path($path), get_theme_file_uri($uri ?? $path));
- }
-}
diff --git a/tests/Unit/BootloaderTest.php b/tests/Unit/BootloaderTest.php
deleted file mode 100644
index 8808129a..00000000
--- a/tests/Unit/BootloaderTest.php
+++ /dev/null
@@ -1,74 +0,0 @@
-getBootloader();
-
- $this->assertFalse($bootloader->ready());
-
- $this->boot();
-
- $this->assertTrue($bootloader->ready());
- }
-
- /** @test */
- public function it_should_defer_callbacks_until_ready()
- {
- $bootloader = $this->getBootloader();
-
- $expected = 'foo';
-
- $bootloader->call(function () use (&$expected) {
- $expected = 'foobar';
- });
-
- $this->assertEquals('foo', $expected);
-
- $this->boot();
-
- $this->assertEquals('foobar', $expected);
- }
-
- /** @test */
- public function it_should_immediately_call_callback_if_ready()
- {
- $bootloader = $this->getBootloader();
-
- $expected = 'foo';
-
- $this->boot();
-
- $bootloader->call(function () use (&$expected) {
- $expected = 'foobar';
- });
-
- $this->assertEquals('foobar', $expected);
- }
-
- protected function getBootloader($hook = 'boot')
- {
- return new \Roots\Acorn\Bootloader($hook, Application::class);
- }
-
- protected function boot($hook = 'boot')
- {
- \do_action($hook);
- }
-}
-
-class Application extends \Roots\Acorn\Application
-{
- public function bootstrapWith(array $bootstrappers)
- {
- }
-}
diff --git a/tests/Unit/Clover/MetaTest.php b/tests/Unit/Clover/MetaTest.php
deleted file mode 100644
index 64ff006c..00000000
--- a/tests/Unit/Clover/MetaTest.php
+++ /dev/null
@@ -1,34 +0,0 @@
-expectError();
- $this->expectErrorMessage('Meta is immutable and cannot be modified after instantiation.');
-
- $meta->set('foo');
- }
-
- public function testOverloadingGetReturnsMetaInstanceForAssocArrayValue(): void
- {
- $meta = new Meta(['foo' => ['bar' => 'Lorem Ipsum']]);
-
- self::assertInstanceOf(Meta::class, $meta->foo);
- self::assertSame('Lorem Ipsum', $meta->foo->bar);
- }
-
- public function testOverloadingGetReturnsValue(): void
- {
- $meta = new Meta(['foo' => ['bar']]);
-
- self::assertSame(['bar'], $meta->foo);
- }
-}
diff --git a/tests/Unit/Clover/ServiceProviderTest.php b/tests/Unit/Clover/ServiceProviderTest.php
deleted file mode 100644
index 5672d845..00000000
--- a/tests/Unit/Clover/ServiceProviderTest.php
+++ /dev/null
@@ -1,104 +0,0 @@
-service->boot();
-
- self::assertTrue($this->plugin->runWasCalled());
- self::assertTrue($this->plugin->lifecycleWasCalled());
- }
-
- public function testRegisterLoadsPluginConfigFileAndAddsViewPathsToFactory(): void
- {
- $this->service->register();
-
- self::assertContains('dummy-plugin', $this->getViewFactoryFromApp()->getRegisteredNamespaces());
- $paths = $this->getViewFactoryFromApp()->getPathsForNamespace('dummy-plugin');
- self::assertStringContainsString('tests/Unit/__fixtures__/plugin/config/../resources/views', $paths[0]);
- }
-
- public function testRegisterProvidersFromPluginConfig(): void
- {
- $this->service->register();
-
- self::assertTrue($this->getServiceProviderSpy()->isRegisterCalled());
- }
-
- public function testRegisterBailsEarlyIfNoConfigFound(): void
- {
- $meta = new Meta(
- [
- 'key' => 'my-plugin',
- 'plugin' => __DIR__ . '/../fixtures/not-existing/my-plugin.php',
- ]
- );
- $this->plugin = new PluginStub($meta);
- $this->app->bind('my-plugin', function () {
- return $this->plugin;
- });
-
- (new CloverServiceProviderStub($this->app, $meta))->register();
-
- $viewFactory = $this->getViewFactoryFromApp();
- self::assertNotContains('my-plugin', $viewFactory->getRegisteredNamespaces());
- }
-
- protected function setUp(): void
- {
- parent::setUp();
- $this->app = new Application();
- $meta = new Meta(
- [
- 'key' => 'dummy-plugin',
- 'plugin' => __DIR__ . '/../__fixtures__/plugin/dummy-plugin.php',
- ]
- );
- $this->plugin = new PluginStub($meta);
- $this->app->bind('dummy-plugin', function () {
- return $this->plugin;
- });
- $this->viewFactory = new ViewFactoryStub();
- $this->app->bind('view', function (): Factory {
- return $this->viewFactory;
- });
- $this->service = new CloverServiceProviderStub($this->app, $meta);
- }
-
- private function getViewFactoryFromApp(): Factory
- {
- $viewFactory = $this->app->get('view');
- assert($viewFactory instanceof ViewFactoryStub);
- return $viewFactory;
- }
-
- private function getServiceProviderSpy(): ServiceProviderSpy
- {
- $viewFactory = $this->app->get(ServiceProviderSpy::class);
- assert($viewFactory instanceof ServiceProviderSpy);
- return $viewFactory;
- }
-}
diff --git a/tests/Unit/Exceptions/HandlerTest.php b/tests/Unit/Exceptions/HandlerTest.php
deleted file mode 100644
index 873612a4..00000000
--- a/tests/Unit/Exceptions/HandlerTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-container = new Application();
- $this->env = 'development';
- $this->container->bind('env', function () {
- return $this->env;
- });
- $this->handler = new Handler($this->container);
- }
-
- public function testRenderSymfonyErrorPageWithoutErrorMessageForProduction(): void
- {
- $this->env = 'production';
-
- $content = $this->handler->render(Request::create('/'), new RuntimeException('Foo Bar'));
-
- self::assertStringContainsString('500 Internal Server Error', $content);
- self::assertStringNotContainsString('Foo bar', $content);
- }
-
- public function testRenderForConsoleRendersErrorMessage(): void
- {
- $output = new OutputStub();
-
- $this->handler->renderForConsole($output, new RuntimeException('Foo bar'));
-
- self::assertStringContainsString('Foo bar', implode(' ', $output->getWrittenMessages()));
- }
-}
diff --git a/tests/Unit/Exceptions/PrettyPageHandlerTest.php b/tests/Unit/Exceptions/PrettyPageHandlerTest.php
deleted file mode 100644
index 07746b85..00000000
--- a/tests/Unit/Exceptions/PrettyPageHandlerTest.php
+++ /dev/null
@@ -1,27 +0,0 @@
-handler = new PrettyPageHandler();
- }
-
- public function testPrettyPageHandlerHasExpectedDataTables(): void
- {
- $tables = $this->handler->getDataTables();
-
- self::assertArrayHasKey('WordPress Data', $tables);
- self::assertArrayHasKey('WP_Query Data', $tables);
- self::assertArrayHasKey('WP_Post Data', $tables);
- }
-}
diff --git a/tests/Unit/FileViewFinderTest.php b/tests/Unit/FileViewFinderTest.php
deleted file mode 100644
index 0f14d992..00000000
--- a/tests/Unit/FileViewFinderTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
- '{{-- foo --}}',
- '/views/foo-bar.blade.php' => '{{-- foobar --}}',
- '/sage/resources/views/page.blade.php' => '{{-- page --}}',
- '/sage/resources/views/page-about.blade.php' => '{{-- about page --}}',
- ];
-
- /** @test */
- public function it_should_find_other_files_based_on_delimeter_breakpoints_in_specified_name()
- {
- $this->markTestSkipped("Feature has been removed, but might be added back");
- $finder = $this->getFinder();
-
- $this->assertEquals("{$this->filesystem}/views/foo.blade.php", $finder->find('foo'));
- $this->assertEquals("{$this->filesystem}/views/foo-bar.blade.php", $finder->find('foo-bar'));
- $this->assertEquals("{$this->filesystem}/views/foo-bar.blade.php", $finder->find('foo-bar-biz-baz'));
- }
-
- /** @test */
- public function it_should_find_possible_view_files_based_on_possible_file_name()
- {
- /** @var \Roots\Acorn\View\FileViewFinder $finder */
- $finder = $this->getFinder();
-
- $views = $finder->getPossibleViewFilesFromPath("{$this->filesystem}/sage/resources/views/page.php");
-
- $expected = [
- "page.blade.php",
- "page.php",
- "page.css",
- 'page.html',
- ];
-
- $this->assertEquals($expected, $views);
- }
-
- protected function getFinder()
- {
- return new \Roots\Acorn\View\FileViewFinder(
- new \Illuminate\Filesystem\Filesystem(),
- ["{$this->filesystem}/views", "{$this->filesystem}/sage/resources/views"]
- );
- }
-}
diff --git a/tests/Unit/Filesystem/FilesystemServiceProviderTest.php b/tests/Unit/Filesystem/FilesystemServiceProviderTest.php
deleted file mode 100644
index 70f3eb9b..00000000
--- a/tests/Unit/Filesystem/FilesystemServiceProviderTest.php
+++ /dev/null
@@ -1,22 +0,0 @@
-register();
-
- $fs = $app->get('files');
- self::assertInstanceOf(Filesystem::class, $fs);
- }
-}
diff --git a/tests/Unit/FilesystemTest.php b/tests/Unit/FilesystemTest.php
deleted file mode 100644
index caccf718..00000000
--- a/tests/Unit/FilesystemTest.php
+++ /dev/null
@@ -1,43 +0,0 @@
-assertEquals('/some/path/to/a/file', $filesystem->normalizePath($path));
- }
-
- /** @test */
- public function it_should_determine_a_relative_path()
- {
- $filesystem = new \Roots\Acorn\Filesystem\Filesystem();
-
- $relative = $filesystem->getRelativePath(
- '/app/themes/sage/',
- '/app/plugins/my-plugin/'
- );
-
- $this->assertEquals('../../plugins/my-plugin/', $relative);
- }
-
- /** @test */
- public function it_should_return_empty_string_when_base_and_target_path_are_equal()
- {
- $filesystem = new \Roots\Acorn\Filesystem\Filesystem();
-
- $relative = $filesystem->getRelativePath(
- '/app/themes/sage/',
- '/app/themes/sage/'
- );
-
- $this->assertEquals('', $relative);
- }
-}
diff --git a/tests/Unit/SageTest.php b/tests/Unit/SageTest.php
deleted file mode 100644
index d4b9bd25..00000000
--- a/tests/Unit/SageTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-fileViewFinder->setPaths([__DIR__ . '/__fixtures__/theme']);
-
- $result = $this->sage->filterThemeTemplates([], ['sage'], 123, 'page');
-
- self::assertSame(['page-template.php' => 'Page Template'], $result);
- }
-
- /** @test */
- public function it_should_compile_list_of_theme_post_type_templates()
- {
- $this->fileViewFinder->setPaths([__DIR__ . '/__fixtures__/theme']);
-
- $result = $this->sage->filterThemeTemplates([], ['sage'], 123, 'post');
-
- self::assertSame(['post-type-template.php' => 'Post Type Template'], $result);
- }
-
- /** @test */
- public function it_should_include_given_templates_in_compiled_list()
- {
- $this->fileViewFinder->setPaths([__DIR__ . '/__fixtures__/theme']);
-
- $result = $this->sage->filterThemeTemplates(['foo' => 'bar'], ['sage'], 123, 'page');
-
- self::assertSame(['foo' => 'bar', 'page-template.php' => 'Page Template'], $result);
- }
-
- /** @test */
- public function it_should_share_the_loop_post_with_view()
- {
- $post = new \WP_Post();
-
- $this->sage->filterThePost($post);
-
- self::assertSame(['post' => $post], $this->viewFactory->getShared());
- }
-
- /** @test */
- public function it_should_load_data_based_on_body_class()
- {
- $GLOBALS['body-class'] = ['foo', 'bar'];
- $this->fileViewFinder->setPaths([__DIR__ . '/__fixtures__/theme']);
- $log = [];
- $cb = function ($data, $view, $file) use (&$log): array {
- $log[] = [
- 'data' => $data,
- 'view' => $view,
- 'file' => $file,
- ];
- return $data;
- };
- add_filter('sage/template/foo/data', $cb);
- add_filter('sage/template/bar/data', $cb);
-
- $this->sage->filterTemplateInclude(__DIR__ . '/__fixtures__/view.php');
-
- self::assertSame([], $log[0]['data']);
- self::assertSame(ltrim(__DIR__, '/') . '/__fixtures__/view', $log[0]['view']);
- self::assertSame(__DIR__ . '/__fixtures__/view.php', $log[0]['file']);
- self::assertSame([], $log[1]['data']);
- }
-
- protected function setUp(): void
- {
- parent::setUp();
- $filesystem = new Filesystem();
- $this->fileViewFinder = new FileViewFinder($filesystem, []);
- $this->viewFactory = new ViewFactoryStub();
- $this->sage = new Sage(
- $filesystem,
- new ViewFinder($this->fileViewFinder, $filesystem),
- $this->fileViewFinder,
- $this->viewFactory,
- new Application()
- );
- }
-}
diff --git a/tests/Unit/SageViewFinderTest.php b/tests/Unit/SageViewFinderTest.php
deleted file mode 100644
index 49dd9618..00000000
--- a/tests/Unit/SageViewFinderTest.php
+++ /dev/null
@@ -1,83 +0,0 @@
- '{{-- page --}}',
- '/app/themes/sage-child/resources/views/page.blade.php' => '{{-- child-page --}}',
- '/app/themes/sage/resources/views/another-page.blade.php' => '{{-- page --}}',
- '/app/themes/sage-child/resources/views/another-page.blade.php' => '{{-- child-page --}}',
- ];
- /** @var \Roots\Acorn\View\FileViewFinder */
- private $viewFinder;
- /** @var \Roots\Acorn\Filesystem\Filesystem */
- private $fs;
-
- /** @test */
- public function it_should_compile_list_of_views_for_template_hierarchy()
- {
- $finder = $this->getFinder();
-
- $this->assertEquals(
- [
- "resources/views/page.blade.php",
- "resources/views/page.php",
- "resources/views/page.css",
- "resources/views/page.html",
- "../sage/resources/views/page.blade.php",
- "../sage/resources/views/page.php",
- "../sage/resources/views/page.css",
- "../sage/resources/views/page.html",
- ],
- array_values($finder->locate('page.php'))
- );
- }
-
- /** @test */
- public function it_should_support_multiple_files()
- {
- $finder = $this->getFinder();
-
- $templates = array_values($finder->locate(['page.php', 'another-page.php']));
-
- self::assertContains("resources/views/page.blade.php", $templates);
- self::assertContains("resources/views/another-page.blade.php", $templates);
- }
-
- /** @test */
- public function it_should_return_instance_of_view_finder()
- {
- $this->assertEquals($this->viewFinder, $this->getFinder()->getFinder());
- }
-
- /** @test */
- public function it_should_return_instance_of_filesystem()
- {
- $this->assertEquals($this->fs, $this->getFinder()->getFilesystem());
- }
-
- protected function getFinder()
- {
- return new \Roots\Acorn\Sage\ViewFinder($this->viewFinder, $this->fs, "{$this->filesystem}/sage-child");
- }
-
- protected function setUp(): void
- {
- parent::setUp();
- $this->fs = new \Roots\Acorn\Filesystem\Filesystem();
- $this->viewFinder = new \Roots\Acorn\View\FileViewFinder(
- new \Roots\Acorn\Filesystem\Filesystem(),
- [
- "{$this->filesystem}/sage-child/resources/views",
- "{$this->filesystem}/sage/resources/views"
- ]
- );
- }
-}
diff --git a/tests/Unit/TestDouble/CloverServiceProviderStub.php b/tests/Unit/TestDouble/CloverServiceProviderStub.php
deleted file mode 100644
index f77a4882..00000000
--- a/tests/Unit/TestDouble/CloverServiceProviderStub.php
+++ /dev/null
@@ -1,15 +0,0 @@
-meta = $meta;
- }
-}
diff --git a/tests/Unit/TestDouble/ContainerStub.php b/tests/Unit/TestDouble/ContainerStub.php
deleted file mode 100644
index 13effb76..00000000
--- a/tests/Unit/TestDouble/ContainerStub.php
+++ /dev/null
@@ -1,46 +0,0 @@
- */
- private $map;
-
- public function __construct(?array $map = null)
- {
- $this->map = $map ?? [];
- }
-
- /**
- * @param string $id
- * @return mixed
- */
- public function get($id)
- {
- return $this->map[$id] ?? null;
- }
-
- /**
- * @param string $id
- * @return bool
- */
- public function has($id): bool
- {
- return array_key_exists($id, $this->map);
- }
-
- /**
- * @param string $id
- * @param mixed $value
- * @return void
- */
- public function set($id, $value): void
- {
- $this->map[$id] = $value;
- }
-}
diff --git a/tests/Unit/TestDouble/ManifestSpy.php b/tests/Unit/TestDouble/ManifestSpy.php
deleted file mode 100644
index 367f0106..00000000
--- a/tests/Unit/TestDouble/ManifestSpy.php
+++ /dev/null
@@ -1,47 +0,0 @@
- */
- private $map;
- /** @var array */
- private $callLog;
-
- public function __construct(?array $map = null)
- {
- $this->map = $map ?? [];
- }
-
- public function get($key): Asset
- {
- $asset = $this->map[$key] ?? null;
- if ($asset === null) {
- throw new RuntimeException(sprintf('Manifest for key "%s" not found', $key));
- }
- return $asset;
- }
-
- public function set(string $key, Asset $value): void
- {
- $this->map[$key] = $value;
- }
-
- public function __call($name, $arguments): void
- {
- $this->callLog[$name] = ($this->callLog[$name] ?? 0) + 1;
- }
-
- /**
- * @return array
- */
- public function getCallLog(): array
- {
- return $this->callLog;
- }
-}
diff --git a/tests/Unit/TestDouble/OutputStub.php b/tests/Unit/TestDouble/OutputStub.php
deleted file mode 100644
index dc2abd42..00000000
--- a/tests/Unit/TestDouble/OutputStub.php
+++ /dev/null
@@ -1,21 +0,0 @@
-written[] = $message;
- }
-
- public function getWrittenMessages(): array
- {
- return $this->written;
- }
-}
diff --git a/tests/Unit/TestDouble/PluginStub.php b/tests/Unit/TestDouble/PluginStub.php
deleted file mode 100644
index bc4facaa..00000000
--- a/tests/Unit/TestDouble/PluginStub.php
+++ /dev/null
@@ -1,42 +0,0 @@
-meta = $meta;
- }
-
- public function run()
- {
- $this->runWasCalled = true;
- }
-
- public function runWasCalled(): bool
- {
- return $this->runWasCalled;
- }
-
- public function lifecycle(Meta $meta): void
- {
- $this->lifecycleWasCalled = true;
- }
-
- public function lifecycleWasCalled(): bool
- {
- return $this->lifecycleWasCalled;
- }
-}
diff --git a/tests/Unit/TestDouble/ServiceProviderSpy.php b/tests/Unit/TestDouble/ServiceProviderSpy.php
deleted file mode 100644
index 195529c7..00000000
--- a/tests/Unit/TestDouble/ServiceProviderSpy.php
+++ /dev/null
@@ -1,23 +0,0 @@
-app->bind(self::class, function (): self {
- return $this;
- });
- $this->registerCalled = true;
- }
-
- public function isRegisterCalled(): bool
- {
- return $this->registerCalled;
- }
-}
diff --git a/tests/Unit/TestDouble/ViewFactoryStub.php b/tests/Unit/TestDouble/ViewFactoryStub.php
deleted file mode 100644
index 6f700d60..00000000
--- a/tests/Unit/TestDouble/ViewFactoryStub.php
+++ /dev/null
@@ -1,95 +0,0 @@
->
- */
- private $map = [];
- /**
- * @var array
- */
- private $shared = [];
-
- public function exists($view): bool
- {
- return false;
- }
-
- public function file($path, $data = [], $mergeData = []): View
- {
- return new ViewStub();
- }
-
- public function make($view, $data = [], $mergeData = []): View
- {
- return new ViewStub();
- }
-
- public function share($key, $value = null)
- {
- $keys = is_array($key) ? $key : [$key => $value];
-
- foreach ($keys as $key => $value) {
- $this->shared[$key] = $value;
- }
-
- return $value;
- }
-
- public function composer($views, $callback): array
- {
- return [];
- }
-
- public function creator($views, $callback): array
- {
- return [];
- }
-
- public function addNamespace($namespace, $hints): self
- {
- $existingHints = $this->map[$namespace] ?? [];
- $this->map[$namespace] = array_merge($hints, $existingHints);
- return $this;
- }
-
- public function replaceNamespace($namespace, $hints): self
- {
- $this->map[$namespace] = $hints;
- return $this;
- }
-
- /**
- * @return string[]
- */
- public function getRegisteredNamespaces(): array
- {
- return array_keys($this->map);
- }
-
- /**
- * @return string[]
- */
- public function getPathsForNamespace(string $namespace): array
- {
- return array_values($this->map[$namespace] ?? []);
- }
-
- /**
- * @return array
- */
- public function getShared(): array
- {
- return $this->shared;
- }
-}
diff --git a/tests/Unit/TestDouble/ViewStub.php b/tests/Unit/TestDouble/ViewStub.php
deleted file mode 100644
index d203c9ab..00000000
--- a/tests/Unit/TestDouble/ViewStub.php
+++ /dev/null
@@ -1,42 +0,0 @@
- */
- private $map = [];
- /** @var string */
- private $content;
- /** @var string */
- private $name;
-
- public function __construct(string $name = '', string $content = '')
- {
- $this->name = $name;
- $this->content = $content;
- }
-
- public function render()
- {
- return $this->content;
- }
-
- public function name()
- {
- return $this->name;
- }
-
- public function with($key, $value = null)
- {
- $this->map[$key] = $value;
- return $this;
- }
-
- public function getData(): array
- {
- return $this->map;
- }
-}
diff --git a/tests/Unit/__fixtures__/plugin/config/dummy-plugin.php b/tests/Unit/__fixtures__/plugin/config/dummy-plugin.php
deleted file mode 100644
index 56e002d1..00000000
--- a/tests/Unit/__fixtures__/plugin/config/dummy-plugin.php
+++ /dev/null
@@ -1,8 +0,0 @@
- [
- \Roots\Acorn\Tests\Unit\TestDouble\ServiceProviderSpy::class
- ],
- 'views' => [__DIR__ . '/../resources/views'],
-];
diff --git a/tests/Unit/__fixtures__/plugin/resources/views/test.php b/tests/Unit/__fixtures__/plugin/resources/views/test.php
deleted file mode 100644
index f3e333e8..00000000
--- a/tests/Unit/__fixtures__/plugin/resources/views/test.php
+++ /dev/null
@@ -1 +0,0 @@
-Hello World
diff --git a/tests/Unit/__fixtures__/theme/page-template.php b/tests/Unit/__fixtures__/theme/page-template.php
deleted file mode 100644
index bdd240ec..00000000
--- a/tests/Unit/__fixtures__/theme/page-template.php
+++ /dev/null
@@ -1,10 +0,0 @@
-
-Hello World Page
diff --git a/tests/Unit/__fixtures__/theme/post-type-template.php b/tests/Unit/__fixtures__/theme/post-type-template.php
deleted file mode 100644
index f9f1671c..00000000
--- a/tests/Unit/__fixtures__/theme/post-type-template.php
+++ /dev/null
@@ -1,7 +0,0 @@
-
-Hello World Post Type
diff --git a/tests/View/ViewTest.php b/tests/View/ViewTest.php
new file mode 100644
index 00000000..3cb61046
--- /dev/null
+++ b/tests/View/ViewTest.php
@@ -0,0 +1,3 @@
+filesystem = new class ($this->fixtures()) {
- /** @var \org\bovigo\vfs\vfsStreamDirectory */
- protected $stream;
-
- public function __construct($fixtures = [])
- {
- $this->stream = vfsStream::setup('__fixtures__', null, $fixtures);
- }
-
- public function __call($name, $arguments)
- {
- return $this->stream->{$name}(...$arguments);
- }
-
- public function __get($name)
- {
- return $this->stream->{$name};
- }
-
- public function __toString()
- {
- return $this->stream->url();
- }
- };
- }
-
- protected function write($file, $contents)
- {
- $file = str_replace('\\', '/', $file);
- $file = ltrim($file, '/');
-
- $file = "{$this->filesystem}/{$file}";
-
- file_put_contents($file, $contents);
-
- return $file;
- }
-
- protected function writeDump($file, $data)
- {
- $contents = var_export($data, true);
- return $this->write($file, $contents);
- }
-
- protected function fixtures()
- {
- $filesystem = [];
-
- foreach ($this->fixtures ?? [] as $file => $content) {
- $limbs = array_reverse(array_filter(explode('/', $file)));
- $filesystem = array_merge_recursive(array_reduce($limbs, function ($leaf, $limb) {
- return [$limb => $leaf];
- }, $content), $filesystem);
- }
-
- return $filesystem;
- }
-}
diff --git a/tests/Unit/__fixtures__/plugin/dummy-plugin.php b/tests/api.php
similarity index 85%
rename from tests/Unit/__fixtures__/plugin/dummy-plugin.php
rename to tests/api.php
index a4abe2da..b3d9bbc7 100644
--- a/tests/Unit/__fixtures__/plugin/dummy-plugin.php
+++ b/tests/api.php
@@ -1,2 +1 @@
create();
+
+ define('ABSPATH', $temp->path('wp'));
+
+ register_shutdown_function(function () use ($temp) {
+ $temp->delete();
+ });
+ }
+
+ if ($path) {
+ return $temp->path($path);
+ }
+
+ return $temp;
+}
+
+function mock(string $class): MockInterface
+{
+ return Mockery::mock($class);
+}
diff --git a/tests/mock-api.php b/tests/mock-api.php
deleted file mode 100644
index c7a2eaf4..00000000
--- a/tests/mock-api.php
+++ /dev/null
@@ -1,223 +0,0 @@
- WP_CONTENT_DIR . '/uploads/test',
- 'url' => content_url() . '/uploads/test',
- 'subdir' => '/test',
- 'basedir' => WP_CONTENT_DIR . '/uploads',
- 'baseurl' => content_url() . '/uploads'
- ];
- }
-}
-
-if (! function_exists('add_filter')) {
- function add_filter($key, callable $callback)
- {
- $GLOBALS['mock-hooks'][$key] = $callback;
-
- return null;
- }
-}
-
-if (! function_exists('apply_filters')) {
- function apply_filters($key, $value = null)
- {
- if (array_key_exists($key, $GLOBALS['mock-hooks'])) {
- $callback = $GLOBALS['mock-hooks'][$key];
- unset($GLOBALS['mock-hooks'][$key]);
- $args = func_get_args();
- unset($args[0]);
- $value = call_user_func($callback, ...$args);
- }
-
- return $value;
- }
-}
-
-if (! function_exists('doing_filter')) {
- function doing_filter($key)
- {
- return ! array_key_exists($key, $GLOBALS['mock-hooks']);
- }
-}
-
-if (! function_exists('add_action')) {
- function add_action($key, $callback)
- {
- return add_filter($key, $callback);
- }
-}
-
-if (! function_exists('do_action')) {
- function do_action($key, $value = null)
- {
- return apply_filters($key, $value);
- }
-}
-
-if (! function_exists('did_action')) {
- function did_action($key)
- {
- return doing_filter($key);
- }
-}
-
-if (! function_exists('doing_action')) {
- function doing_action($key)
- {
- return doing_filter($key);
- }
-}
-
-if (! function_exists('__')) {
- function __(): string
- {
- return mock_translation(...func_get_args());
- }
-}
-
-if (! function_exists('_x')) {
- function _x(): string
- {
- return mock_translation(...func_get_args());
- }
-}
-
-if (! function_exists('_e')) {
- function _e(): void
- {
- echo mock_translation(...func_get_args());
- }
-}
-
-if (! function_exists('_cleanup_header_comment')) {
- /**
- * Strip close comment and close php tags from file headers used by WP.
- * @link https://github.com/WordPress/WordPress/blob/5.2.1/wp-includes/functions.php#L5480-L5492
- *
- * @param string $str Header comment to clean up.
- * @return string
- */
- function _cleanup_header_comment($str)
- {
- return trim(preg_replace('/\s*(?:\*\/|\?>).*/', '', $str));
- }
-}
-
-if (! function_exists('sanitize_key')) {
- /**
- * Sanitizes a string key.
- * @link https://github.com/WordPress/WordPress/blob/5.2.1/wp-includes/formatting.php#L2114-L2138
- *
- * @param string $key String key
- * @return string Sanitized key
- */
- function sanitize_key($key)
- {
- $key = strtolower($key);
- $key = preg_replace('/[^a-z0-9_\-]/', '', $key);
- return $key;
- }
-}
-
-if (! function_exists('get_body_class')) {
- function get_body_class()
- {
- return $GLOBALS['body-class'];
- }
-}
-
-if (! function_exists('get_template_directory')) {
- function get_template_directory()
- {
- return TEMPLATEPATH;
- }
-}
-
-if (! function_exists('get_current_user_id')) {
- function get_current_user_id()
- {
- return 1;
- }
-}
-
-if (! class_exists('WP_Post')) {
- final class WP_Post
- {
-
- }
-}
-
-function mock_translation()
-{
- return 'translated.' . func_get_arg(0);
-}