- Introduced SitemapStorage class for reading, writing, and checking existence of sitemap files. - Updated GenerateSitemapCommand to utilize SitemapStorage for file operations. - Refactored tests to accommodate changes in sitemap file handling. - Enhanced configuration to support output paths and storage disks.
401 lines
15 KiB
PHP
401 lines
15 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Uwil\SitemapGenerator\Tests\Unit\Config;
|
|
|
|
use Cron\CronExpression;
|
|
use Illuminate\Config\Repository as ConfigRepository;
|
|
use Uwil\SitemapGenerator\Config\SitemapConfig;
|
|
use Uwil\SitemapGenerator\Config\SitemapStorage;
|
|
use Uwil\SitemapGenerator\Exceptions\SitemapException;
|
|
use Uwil\SitemapGenerator\Localizers\DefaultRouteLocalizer;
|
|
use Uwil\SitemapGenerator\Localizers\McamaraRouteLocalizer;
|
|
|
|
covers(SitemapConfig::class);
|
|
|
|
describe('SitemapConfig', function () {
|
|
it('can be instantiated with valid configuration', function () {
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['contact'],
|
|
'supported_locales' => ['fr', 'en'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '45 15 * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$sitemapConfig = new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($sitemapConfig)->toBeInstanceOf(SitemapConfig::class)
|
|
->and($sitemapConfig->singlePages)->toBe(['contact'])
|
|
->and($sitemapConfig->supportedLocales)->toBe(['fr', 'en'])
|
|
->and($sitemapConfig->cruds)->toBe([])
|
|
->and($sitemapConfig->schedule)->toBeFalse()
|
|
->and($sitemapConfig->localizer)->toBe('default')
|
|
->and($sitemapConfig->cron)->toBeInstanceOf(CronExpression::class)
|
|
->and($sitemapConfig->sitemapStorage)->toBeInstanceOf(SitemapStorage::class)
|
|
->and((string) $sitemapConfig->sitemapStorage)->toBe(
|
|
"{$this->outputDisk}:" .
|
|
ltrim($this->outputPath, '/')
|
|
);
|
|
});
|
|
|
|
it('can be configured with a relative output path inside disk', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['contact'],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'public',
|
|
'path' => 'sitemaps/sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$sitemapConfig = new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect((string) $sitemapConfig->sitemapStorage)->toBe('public:sitemaps/sitemap.xml');
|
|
});
|
|
|
|
it('throws exception when legacy singlePages config key is used', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'singlePages' => ['contact'],
|
|
'single_pages' => ['contact'],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)->toThrow(
|
|
SitemapException::class,
|
|
"You may migrate your config to use the 'single_pages' key instead of 'singlePages'"
|
|
);
|
|
});
|
|
|
|
it('throws exception when legacy output_path config key is used', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'output_path' => '/tmp/sitemap.xml',
|
|
'single_pages' => ['contact'],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)->toThrow(
|
|
SitemapException::class,
|
|
"You may migrate your config to use the 'output.storage_disk' and 'output.path' keys instead of 'output_path'."
|
|
);
|
|
});
|
|
|
|
it('throws exception when legacy relationFilters key is used in crud config', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [
|
|
[
|
|
'model' => ModelClass::class,
|
|
'relationFilters' => ['posts' => fn () => true],
|
|
],
|
|
],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)->toThrow(
|
|
SitemapException::class,
|
|
"CRUD config must use the 'relation_filters' key instead of 'relationFilters'."
|
|
);
|
|
});
|
|
|
|
it('throws exception when legacy modelFilters key is used in crud config', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [
|
|
[
|
|
'model' => ModelClass::class,
|
|
'modelFilters' => [['is_active', '=', true]],
|
|
],
|
|
],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)->toThrow(
|
|
SitemapException::class,
|
|
"CRUD config must use the 'model_filters' key instead of 'modelFilters'."
|
|
);
|
|
});
|
|
|
|
it('throws exception when legacy allowNullRelation key is used in crud config', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [
|
|
[
|
|
'model' => ModelClass::class,
|
|
'allowNullRelation' => ['category'],
|
|
],
|
|
],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)->toThrow(
|
|
SitemapException::class,
|
|
"CRUD config must use the 'allow_null_relation' key instead of 'allowNullRelation'."
|
|
);
|
|
});
|
|
|
|
it('supports associative array for supported_locales and filters empty values', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['contact', '', ' ', 123, null],
|
|
'supported_locales' => [
|
|
'fr' => 'Français',
|
|
'en' => 'English',
|
|
'' => 'Vide',
|
|
' ' => 'Espaces',
|
|
],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$sitemapConfig = new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($sitemapConfig->supportedLocales)->toBe(['fr', 'en'])
|
|
->and($sitemapConfig->singlePages)->toBe(['contact']);
|
|
});
|
|
|
|
it('throws exception when cron expression is invalid', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => 'invalid-cron',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)
|
|
->toThrow(SitemapException::class, "Cron config is not a valid expression 'invalid-cron'");
|
|
});
|
|
|
|
it('throws exception when output path does not end with .xml', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => '/tmp/sitemap.txt',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$action = fn () => new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($action)
|
|
->toThrow(SitemapException::class, 'The path must indicate a valid XML file location.');
|
|
});
|
|
|
|
it('can parse cruds configuration properly', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [
|
|
[
|
|
'model' => ModelClass::class,
|
|
'relation_filters' => ['posts' => fn () => true],
|
|
'model_filters' => [['is_active', '=', true]],
|
|
'allow_null_relation' => ['category'],
|
|
],
|
|
],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'default',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$sitemapConfig = new SitemapConfig($configRepository);
|
|
|
|
// THEN
|
|
expect($sitemapConfig->cruds)->toHaveCount(1)
|
|
->and($sitemapConfig->cruds[0]->modelClass)->toBe(ModelClass::class)
|
|
->and($sitemapConfig->cruds[0]->allowNullRelations)->toBe(['category']);
|
|
});
|
|
|
|
it('returns the configured localizer instance', function (string $strategy, string $expectedClass) {
|
|
/** @var class-string $expectedClass */
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => $strategy,
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$sitemapConfig = new SitemapConfig($configRepository);
|
|
$localizer = $sitemapConfig->getConfiguredLocalizerFor(app());
|
|
|
|
// THEN
|
|
expect($localizer)->toBeInstanceOf($expectedClass);
|
|
})->with([
|
|
'default alias' => ['default', DefaultRouteLocalizer::class],
|
|
'default class string' => [DefaultRouteLocalizer::class, DefaultRouteLocalizer::class],
|
|
'mcamara alias' => ['mcamara', McamaraRouteLocalizer::class],
|
|
'mcamara class string' => [McamaraRouteLocalizer::class, McamaraRouteLocalizer::class],
|
|
]);
|
|
|
|
it('throws exception when localizer is unsupported', function () {
|
|
// GIVEN
|
|
$configRepository = new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'unsupported-localizer',
|
|
'output' => [
|
|
'storage_disk' => 'local',
|
|
'path' => 'sitemap.xml',
|
|
],
|
|
],
|
|
]);
|
|
|
|
// WHEN
|
|
$sitemapConfig = new SitemapConfig($configRepository);
|
|
$action = fn () => $sitemapConfig->getConfiguredLocalizerFor(app());
|
|
|
|
// THEN
|
|
expect($action)->toThrow(
|
|
SitemapException::class,
|
|
"Unsupported localizer 'unsupported-localizer'"
|
|
);
|
|
});
|
|
});
|