diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index aee5d81..714f79d 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -24,7 +24,7 @@ jobs: run: composer install --no-scripts - name: Lint PHP - run: php -l src/**/*.php + run: php -l src/**/*.php tests/**/*.php - name: Lint Templates run: bin/console lint:twig templates diff --git a/.gitignore b/.gitignore index c1d6b1c..a94a1b6 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ phpstan.neon ###< phpunit/phpunit ### chromadb +coverage diff --git a/composer.json b/composer.json index 9e20ab7..40b14ca 100644 --- a/composer.json +++ b/composer.json @@ -106,6 +106,16 @@ "cache:clear": "symfony-cmd", "assets:install %PUBLIC_DIR%": "symfony-cmd", "importmap:install": "symfony-cmd" - } + }, + "pipeline": [ + "composer validate --strict", + "php -l src/**/*.php tests/**/*.php", + "bin/console lint:twig templates", + "bin/console lint:yaml config", + "bin/console lint:container", + "PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --dry-run", + "phpstan analyse", + "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html=coverage" + ] } } diff --git a/src/ProfilerSubscriber.php b/src/ProfilerSubscriber.php index 49459c7..26d3d46 100644 --- a/src/ProfilerSubscriber.php +++ b/src/ProfilerSubscriber.php @@ -4,9 +4,9 @@ namespace App; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelInterface; /** * Can be deleted with Symfony 7.3, see https://github.com/symfony/symfony/pull/59123. @@ -14,7 +14,8 @@ final class ProfilerSubscriber implements EventSubscriberInterface { public function __construct( - private KernelInterface $kernel, + #[Autowire('kernel.debug')] + private readonly bool $debug, ) { } @@ -27,7 +28,7 @@ public static function getSubscribedEvents(): array public function onKernelResponse(ResponseEvent $event): void { - if (!$this->kernel->isDebug()) { + if (!$this->debug && !$event->isMainRequest()) { return; } diff --git a/templates/index.html.twig b/templates/index.html.twig index 8ac30b2..aa16a7b 100644 --- a/templates/index.html.twig +++ b/templates/index.html.twig @@ -23,10 +23,13 @@

Retrieval Augmented Generation based on Symfony's blog dumped to a vector store.

Try RAG Chat Bot - + {# Profiler route only available in dev #} + {% if 'dev' == app.environment %} + + {% endif %}
@@ -39,10 +42,13 @@

Question answering initialized with transcript of YouTube video.

Try YouTube Transcript Bot
- + {# Profiler route only available in dev #} + {% if 'dev' == app.environment %} + + {% endif %}
@@ -55,10 +61,13 @@

Some quick example text to build on the card title and make up the bulk of the card's content.

Try Wikipedia Research Bot
- + {# Profiler route only available in dev #} + {% if 'dev' == app.environment %} + + {% endif %} diff --git a/tests/ProfilerSubscriberTest.php b/tests/ProfilerSubscriberTest.php new file mode 100644 index 0000000..8d02dff --- /dev/null +++ b/tests/ProfilerSubscriberTest.php @@ -0,0 +1,61 @@ +headers->set('X-Requested-With', 'XMLHttpRequest'); + } + + $response = new Response(); + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), $requestType, $response); + + $listener = new ProfilerSubscriber($debug); + $listener->onKernelResponse($event); + + $this->assertFalse($response->headers->has('Symfony-Debug-Toolbar-Replace')); + } + + /** + * @return iterable + */ + public static function provideInvalidRequests(): iterable + { + yield 'sub request, not debug, not XHR' => [HttpKernelInterface::SUB_REQUEST, false, false]; + yield 'sub request, not debug, XHR' => [HttpKernelInterface::SUB_REQUEST, false, true]; + yield 'sub request, debug, XHR' => [HttpKernelInterface::SUB_REQUEST, true, true]; + yield 'main request, not debug, not XHR' => [HttpKernelInterface::MAIN_REQUEST, false, false]; + yield 'main request, debug, not XHR' => [HttpKernelInterface::MAIN_REQUEST, true, false]; + } + + public function testAjaxReplaceHeaderOnEnabledAndXHR(): void + { + $request = new Request(); + $request->headers->set('X-Requested-With', 'XMLHttpRequest'); + $response = new Response(); + $event = new ResponseEvent($this->createMock(Kernel::class), $request, HttpKernelInterface::MAIN_REQUEST, $response); + + $listener = new ProfilerSubscriber(true); + $listener->onKernelResponse($event); + + $this->assertEquals('1', $response->headers->get('Symfony-Debug-Toolbar-Replace')); + } +} diff --git a/tests/SmokeTest.php b/tests/SmokeTest.php new file mode 100644 index 0000000..fbbb016 --- /dev/null +++ b/tests/SmokeTest.php @@ -0,0 +1,55 @@ +request('GET', '/'); + + self::assertResponseIsSuccessful(); + self::assertSelectorTextContains('h1', 'Welcome'); + self::assertSelectorCount(3, '.card'); + } + + public function testRag(): void + { + $client = static::createClient(); + $client->request('GET', '/rag'); + + self::assertResponseIsSuccessful(); + self::assertSelectorTextContains('h4', 'Retrieval Augmented Generation with the Symfony blog'); + self::assertSelectorCount(1, '#chat-submit'); + } + + public function testYouTube(): void + { + $client = static::createClient(); + $client->request('GET', '/youtube'); + + self::assertResponseIsSuccessful(); + self::assertSelectorTextContains('h4', 'Chat about a YouTube Video'); + self::assertSelectorCount(1, '#chat-submit'); + } + + public function testWikipedia(): void + { + $client = static::createClient(); + $client->request('GET', '/wikipedia'); + + self::assertResponseIsSuccessful(); + self::assertSelectorTextContains('h4', 'Wikipedia Research'); + self::assertSelectorCount(1, '#chat-submit'); + } +} diff --git a/tests/YouTube/TranscriptFetcherTest.php b/tests/YouTube/TranscriptFetcherTest.php new file mode 100644 index 0000000..5a65b4a --- /dev/null +++ b/tests/YouTube/TranscriptFetcherTest.php @@ -0,0 +1,27 @@ +fetchTranscript('6uXW-ulpj0s'); + + self::assertStringContainsString('symphony is a PHP framework', $transcript); + } +} diff --git a/tests/YouTube/fixtures/transcript.xml b/tests/YouTube/fixtures/transcript.xml new file mode 100644 index 0000000..f93f51b --- /dev/null +++ b/tests/YouTube/fixtures/transcript.xml @@ -0,0 +1,66 @@ + + + symphony is a PHP framework and this is + an advantage why because almost 80 + percent of all websites in the internet + use PHP as a server-side language eighty + percent this does mean that wherever you + are right now there is someone near you + probably searching to hire a PHP + developer Symphony will not only teach + you more PHP but also will teach you + different software architecture patterns + that you can use in different languages + software architecture patterns are so + much important in your skill sets + because they allow you to understand + complex software when you only know the + architecture that was used in that + software please let me tell you a story + that happened to me I had a PHP laravel + interview in a company and the interview + was successful so they invite me for a + test work day and that test work day + they asked me to build an application + using.net and Seashore they told me we + know you didn&#39;t had any previous + experience using C sharp but we want to + see how you can get along with different + programming language I was able to + Google and found out that the dotnet + framework is an MVC architect framework + the same framework is used in Symphony + and Bam I built the application in + c-sharp and I got a wonderful job offer + so yes learning Symphony will teach you + software architecture patterns that are + essential in your skill set symphony is + a full stack framework that mean you can + create deploy ready application you will + be using front-end Technologies like + HTML CSS and JavaScript and back-end or + server Technologies like PHP databases + that will process the user request all + in one place Symphony can integrate + easily with modern JavaScript Frameworks + like vue.js or react.js or even you can + set up different databases like MySQL + postgres or whatever you want Symphony + has a CLI tool that can help build and + speak and debug your application and is + one of the most advanced code generation + tool in the planner is relate in the + comment if you know anything that is + good finally documentation Symphony has + good documentation that will make it + easy for newcomers to learn and have fun + with the technology so that was my 6y2 + simple normally I don&#39;t do this but + right now go and check the description + see the comment and write me what you + think like the video and subscribe to my + channel then go to the channel check the + videos and like each one of them and + comment again and come back to this + video and watch it again thank you + diff --git a/tests/YouTube/fixtures/video.html b/tests/YouTube/fixtures/video.html new file mode 100644 index 0000000..9ecea3f --- /dev/null +++ b/tests/YouTube/fixtures/video.html @@ -0,0 +1,88 @@ +Learn Symfony in 2025, 6 reasons why - YouTube
InfoPresseUrheberrechtKontaktCreatorWerbenEntwicklerImpressumVerträge hier kündigenNutzungsbedingungenDatenschutzRichtlinien & SicherheitWie funktioniert YouTube?Neue Funktionen testen
\ No newline at end of file