Merge branch 'feature/opensearch' into development

This commit is contained in:
Dan Brown 2024-09-30 17:21:51 +01:00
commit e65655594f
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
12 changed files with 117 additions and 31 deletions

View File

@ -64,4 +64,14 @@ class MetaController extends Controller
'jsLibData' => file_get_contents(base_path('dev/licensing/js-library-licenses.txt')),
]);
}
/**
* Show the view for /opensearch.xml.
*/
public function opensearch()
{
return response()
->view('misc.opensearch')
->header('Content-Type', 'application/opensearchdescription+xml');
}
}

View File

@ -107,4 +107,7 @@ return [
// Not directly used but available for convenience to users.
'privacy_policy' => 'Privacy Policy',
'terms_of_service' => 'Terms of Service',
// OpenSearch
'opensearch_description' => 'Search :appName',
];

View File

@ -32,6 +32,9 @@
<link rel="manifest" href="{{ url('/manifest.json') }}">
<meta name="mobile-web-app-capable" content="yes">
<!-- OpenSearch -->
<link rel="search" type="application/opensearchdescription+xml" title="{{ setting('app-name') }}" href="{{ url('/opensearch.xml') }}">
@yield('head')
<!-- Custom Styles & Head Content -->

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>{{ mb_strimwidth(setting('app-name'), 0, 16) }}</ShortName>
<Description>{{ trans('common.opensearch_description', ['appName' => setting('app-name')]) }}</Description>
<Image width="256" height="256" type="image/png">{{ setting('app-icon') ?: url('/icon.png') }}</Image>
<Image width="180" height="180" type="image/png">{{ setting('app-icon-180') ?: url('/icon-180.png') }}</Image>
<Image width="128" height="128" type="image/png">{{ setting('app-icon-128') ?: url('/icon-128.png') }}</Image>
<Image width="64" height="64" type="image/png">{{ setting('app-icon-64') ?: url('/icon-64.png') }}</Image>
<Image width="32" height="32" type="image/png">{{ setting('app-icon-32') ?: url('/icon-32.png') }}</Image>
<Url type="text/html" rel="results" template="{{ url('/search') }}?term={searchTerms}"/>
<Url type="application/opensearchdescription+xml" rel="self" template="{{ url('/opensearch.xml') }}"/>
</OpenSearchDescription>

View File

@ -23,6 +23,7 @@ Route::get('/robots.txt', [MetaController::class, 'robots']);
Route::get('/favicon.ico', [MetaController::class, 'favicon']);
Route::get('/manifest.json', [MetaController::class, 'pwaManifest']);
Route::get('/licenses', [MetaController::class, 'licenses']);
Route::get('/opensearch.xml', [MetaController::class, 'opensearch']);
// Authenticated routes...
Route::middleware('auth')->group(function () {

View File

@ -1,6 +1,8 @@
<?php
namespace Tests;
namespace Tests\Meta;
use Tests\TestCase;
class HelpTest extends TestCase
{

View File

@ -1,6 +1,8 @@
<?php
namespace Tests;
namespace Tests\Meta;
use Tests\TestCase;
class LicensesTest extends TestCase
{

View File

@ -1,11 +1,12 @@
<?php
namespace Tests;
namespace Tests\Meta;
use BookStack\Entities\Repos\BaseRepo;
use BookStack\Entities\Repos\BookRepo;
use Illuminate\Support\Str;
use Illuminate\Testing\TestResponse;
use Tests\TestCase;
class OpenGraphTest extends TestCase
{

View File

@ -0,0 +1,42 @@
<?php
namespace Tests\Meta;
use Tests\TestCase;
class OpensearchTest extends TestCase
{
public function test_opensearch_endpoint()
{
$appName = 'MyAppNameThatsReallyLongLikeThis';
setting()->put('app-name', $appName);
$resultUrl = url('/search') . '?term={searchTerms}';
$selfUrl = url('/opensearch.xml');
$resp = $this->get('/opensearch.xml');
$resp->assertOk();
$html = $this->withHtml($resp);
$html->assertElementExists('OpenSearchDescription > ShortName');
$html->assertElementContains('OpenSearchDescription > ShortName', mb_strimwidth($appName, 0, 16));
$html->assertElementNotContains('OpenSearchDescription > ShortName', $appName);
$html->assertElementExists('OpenSearchDescription > Description');
$html->assertElementContains('OpenSearchDescription > Description', "Search {$appName}");
$html->assertElementExists('OpenSearchDescription > Image');
$html->assertElementExists('OpenSearchDescription > Url[rel="results"][template="' . htmlspecialchars($resultUrl) . '"]');
$html->assertElementExists('OpenSearchDescription > Url[rel="self"][template="' . htmlspecialchars($selfUrl) . '"]');
}
public function test_opensearch_linked_to_from_home()
{
$appName = setting('app-name');
$endpointUrl = url('/opensearch.xml');
$resp = $this->asViewer()->get('/');
$html = $this->withHtml($resp);
$html->assertElementExists('head > link[rel="search"][type="application/opensearchdescription+xml"][title="' . htmlspecialchars($appName) . '"][href="' . htmlspecialchars($endpointUrl) . '"]');
}
}

View File

@ -1,6 +1,8 @@
<?php
namespace Tests;
namespace Tests\Meta;
use Tests\TestCase;
class PwaManifestTest extends TestCase
{

35
tests/Meta/RobotsTest.php Normal file
View File

@ -0,0 +1,35 @@
<?php
namespace Tests\Meta;
use Tests\TestCase;
class RobotsTest extends TestCase
{
public function test_robots_effected_by_public_status()
{
$this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
$this->setSettings(['app-public' => 'true']);
$resp = $this->get('/robots.txt');
$resp->assertSee("User-agent: *\nDisallow:");
$resp->assertDontSee('Disallow: /');
}
public function test_robots_effected_by_setting()
{
$this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
config()->set('app.allow_robots', true);
$resp = $this->get('/robots.txt');
$resp->assertSee("User-agent: *\nDisallow:");
$resp->assertDontSee('Disallow: /');
// Check config overrides app-public setting
config()->set('app.allow_robots', false);
$this->setSettings(['app-public' => 'true']);
$this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
}
}

View File

@ -128,33 +128,6 @@ class PublicActionTest extends TestCase
$resp->assertDontSee($page->name);
}
public function test_robots_effected_by_public_status()
{
$this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
$this->setSettings(['app-public' => 'true']);
$resp = $this->get('/robots.txt');
$resp->assertSee("User-agent: *\nDisallow:");
$resp->assertDontSee('Disallow: /');
}
public function test_robots_effected_by_setting()
{
$this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
config()->set('app.allow_robots', true);
$resp = $this->get('/robots.txt');
$resp->assertSee("User-agent: *\nDisallow:");
$resp->assertDontSee('Disallow: /');
// Check config overrides app-public setting
config()->set('app.allow_robots', false);
$this->setSettings(['app-public' => 'true']);
$this->get('/robots.txt')->assertSee("User-agent: *\nDisallow: /");
}
public function test_default_favicon_file_created_upon_access()
{
$faviconPath = public_path('favicon.ico');