- 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.
389 lines
14 KiB
PHP
389 lines
14 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Uwil\SitemapGenerator\Tests\Integration;
|
|
|
|
use Illuminate\Config\Repository as ConfigRepository;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Translation\Translator;
|
|
use Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider;
|
|
use Spatie\Sitemap\Sitemap;
|
|
use Spatie\Sitemap\Tags\Url;
|
|
use Uwil\SitemapGenerator\Config\SitemapConfig;
|
|
use Uwil\SitemapGenerator\Localizers\McamaraRouteLocalizer;
|
|
use Uwil\SitemapGenerator\SitemapGenerator;
|
|
use Uwil\SitemapGenerator\SitemapHelper;
|
|
use Uwil\SitemapGenerator\Tests\Unit\Config\ModelClass;
|
|
use Webmozart\Assert\Assert;
|
|
|
|
covers([SitemapGenerator::class, SitemapHelper::class, McamaraRouteLocalizer::class]);
|
|
|
|
describe('SitemapGenerator with McamaraRouteLocalizer', function () {
|
|
beforeEach(function () {
|
|
app()->register(LaravelLocalizationServiceProvider::class);
|
|
config()->set('laravellocalization.supportedLocales', [
|
|
'fr' => ['name' => 'French', 'script' => 'Latn', 'native' => 'Français'],
|
|
'en' => ['name' => 'English', 'script' => 'Latn', 'native' => 'English'],
|
|
]);
|
|
config()->set('laravellocalization.hideDefaultLocaleInURL', false);
|
|
});
|
|
|
|
afterEach(function () {
|
|
Schema::dropIfExists('model_classes');
|
|
});
|
|
|
|
it('can be instantiated and resolved from container with mcamara localizer', function () {
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
// GIVEN
|
|
config()->set('sitemap-generator.localizer', 'mcamara');
|
|
config()->set('sitemap-generator.output', [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
]);
|
|
config()->set('sitemap-generator.supported_locales', ['fr', 'en']);
|
|
|
|
// WHEN
|
|
$generator = app(SitemapGenerator::class);
|
|
|
|
// THEN
|
|
expect($generator)->toBeInstanceOf(SitemapGenerator::class);
|
|
});
|
|
|
|
it('generates an empty sitemap when no pages or cruds are configured', function () {
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
// GIVEN
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap)->toBeInstanceOf(Sitemap::class)
|
|
->and($sitemap->getTags())->toBeEmpty();
|
|
});
|
|
|
|
it('generates a sitemap with single pages in a single locale', function () {
|
|
// GIVEN
|
|
app('translator')->addLines([
|
|
'routes.about' => 'a-propos',
|
|
'routes.contact' => 'contactez-nous',
|
|
], 'fr');
|
|
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['about', 'contact'],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap)->toBeInstanceOf(Sitemap::class)
|
|
->and($sitemap->hasUrl('http://localhost/fr/a-propos'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/fr/contactez-nous'))->toBeTrue()
|
|
->and($sitemap->getTags())->toHaveCount(2);
|
|
});
|
|
|
|
it('generates a sitemap with single pages and alternates across multiple locales', function () {
|
|
// GIVEN
|
|
app('translator')->addLines([
|
|
'routes.about' => 'a-propos',
|
|
'routes.contact' => 'contactez-nous',
|
|
], 'fr');
|
|
|
|
app('translator')->addLines([
|
|
'routes.about' => 'about-us',
|
|
'routes.contact' => 'contact-us',
|
|
], 'en');
|
|
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['about', 'contact'],
|
|
'supported_locales' => ['fr', 'en'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap)->toBeInstanceOf(Sitemap::class)
|
|
->and($sitemap->hasUrl('http://localhost/fr/a-propos'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/en/about-us'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/fr/contactez-nous'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/en/contact-us'))->toBeTrue();
|
|
|
|
$aboutTagFr = collect($sitemap->getTags())
|
|
->first(fn (mixed $tag): bool => $tag instanceof Url && $tag->url === 'http://localhost/fr/a-propos');
|
|
Assert::isInstanceOf($aboutTagFr, Url::class);
|
|
expect($aboutTagFr->alternates)->toHaveCount(1)
|
|
->and($aboutTagFr->alternates[0]->url)->toBe('http://localhost/en/about-us')
|
|
->and($aboutTagFr->alternates[0]->locale)->toBe('en');
|
|
|
|
$aboutTagEn = collect($sitemap->getTags())
|
|
->first(fn (mixed $tag): bool => $tag instanceof Url && $tag->url === 'http://localhost/en/about-us');
|
|
Assert::isInstanceOf($aboutTagEn, Url::class);
|
|
expect($aboutTagEn->alternates)->toHaveCount(1)
|
|
->and($aboutTagEn->alternates[0]->url)->toBe('http://localhost/fr/a-propos')
|
|
->and($aboutTagEn->alternates[0]->locale)->toBe('fr');
|
|
});
|
|
|
|
it('ignores untranslated routes gracefully without producing bare locale root', function () {
|
|
// GIVEN
|
|
app('translator')->addLines([
|
|
'routes.contact' => 'contactez-nous',
|
|
], 'fr');
|
|
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['contact', 'missing_translation'],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap->hasUrl('http://localhost/fr/contactez-nous'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/fr'))->toBeFalse()
|
|
->and($sitemap->getTags())->toHaveCount(1);
|
|
});
|
|
|
|
it('handles partially translated routes across locales', function () {
|
|
// GIVEN
|
|
app('translator')->addLines([
|
|
'routes.contact' => 'contactez-nous',
|
|
'routes.french_only' => 'seulement-francais',
|
|
], 'fr');
|
|
|
|
app('translator')->addLines([
|
|
'routes.contact' => 'contact-us',
|
|
], 'en');
|
|
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['contact', 'french_only'],
|
|
'supported_locales' => ['fr', 'en'],
|
|
'cruds' => [],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap->hasUrl('http://localhost/fr/contactez-nous'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/en/contact-us'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/fr/seulement-francais'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/en'))->toBeFalse()
|
|
->and($sitemap->getTags())->toHaveCount(3);
|
|
|
|
$frenchOnlyTag = collect($sitemap->getTags())
|
|
->first(fn (mixed $tag): bool => $tag instanceof Url && $tag->url === 'http://localhost/fr/seulement-francais');
|
|
Assert::isInstanceOf($frenchOnlyTag, Url::class);
|
|
expect($frenchOnlyTag->alternates)->toBeEmpty();
|
|
});
|
|
|
|
it('generates a sitemap with cruds models and alternates', function () {
|
|
// GIVEN
|
|
Schema::create('model_classes', function (Blueprint $table) {
|
|
$table->id();
|
|
$table->timestamps();
|
|
});
|
|
|
|
ModelClass::create();
|
|
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => [],
|
|
'supported_locales' => ['fr', 'en'],
|
|
'cruds' => [
|
|
[
|
|
'model' => ModelClass::class,
|
|
],
|
|
],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap)->toBeInstanceOf(Sitemap::class)
|
|
->and($sitemap->hasUrl('http://localhost/fr/posts'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/en/posts'))->toBeTrue();
|
|
|
|
$crudTagFr = collect($sitemap->getTags())
|
|
->first(fn (mixed $tag): bool => $tag instanceof Url && $tag->url === 'http://localhost/fr/posts');
|
|
Assert::isInstanceOf($crudTagFr, Url::class);
|
|
expect($crudTagFr->alternates)->toHaveCount(1)
|
|
->and($crudTagFr->alternates[0]->url)->toBe('http://localhost/en/posts')
|
|
->and($crudTagFr->alternates[0]->locale)->toBe('en');
|
|
});
|
|
|
|
it('generates a combined sitemap with single pages and cruds', function () {
|
|
// GIVEN
|
|
app('translator')->addLines([
|
|
'routes.home' => 'accueil',
|
|
], 'fr');
|
|
|
|
Schema::create('model_classes', function (Blueprint $table) {
|
|
$table->id();
|
|
$table->timestamps();
|
|
});
|
|
|
|
ModelClass::create();
|
|
|
|
/** @var \Uwil\SitemapGenerator\Tests\TestCase $this */
|
|
$config = new SitemapConfig(new ConfigRepository([
|
|
SitemapConfig::CONFIG_KEY => [
|
|
'single_pages' => ['home'],
|
|
'supported_locales' => ['fr'],
|
|
'cruds' => [
|
|
[
|
|
'model' => ModelClass::class,
|
|
],
|
|
],
|
|
'schedule' => false,
|
|
'cron' => '* * * * *',
|
|
'localizer' => 'mcamara',
|
|
'output' => [
|
|
'storage_disk' => $this->outputDisk,
|
|
'path' => $this->outputPath,
|
|
],
|
|
],
|
|
]));
|
|
|
|
$translator = app()->make(Translator::class);
|
|
$generator = new SitemapGenerator(
|
|
$config,
|
|
new SitemapHelper(
|
|
$config,
|
|
new McamaraRouteLocalizer($translator)
|
|
)
|
|
);
|
|
|
|
// WHEN
|
|
$sitemap = $generator->generate();
|
|
|
|
// THEN
|
|
expect($sitemap->hasUrl('http://localhost/fr/accueil'))->toBeTrue()
|
|
->and($sitemap->hasUrl('http://localhost/fr/posts'))->toBeTrue()
|
|
->and($sitemap->getTags())->toHaveCount(2);
|
|
});
|
|
});
|