From 4cbb6590d28bb1918485c85fb1ade118a2211c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Wojda=C5=82owicz?= Date: Mon, 19 Feb 2024 08:25:43 +0100 Subject: [PATCH 1/2] OP-237 - write phpspec tests --- spec/ApiClient/SuluApiClientSpec.php | 68 ++++++++++++++ .../Action/PurgeSuluCacheActionSpec.php | 62 +++++++++++++ .../Action/RenderPageActionSpec.php | 84 +++++++++++++++++ .../Block/SuluBlockRendererStrategySpec.php | 63 +++++++++++++ .../Page/SuluPageRendererStrategySpec.php | 64 +++++++++++++ spec/Twig/Runtime/SuluRuntimeSpec.php | 90 +++++++++++++++++++ src/ApiClient/SuluApiClient.php | 2 +- src/ApiClient/SuluApiClientInterface.php | 10 +++ src/Controller/Action/RenderPageAction.php | 10 +-- src/Entity/ChannelInterface.php | 4 +- .../Block/SuluBlockRendererStrategy.php | 2 +- .../SuluBlockRendererStrategyInterface.php | 10 +++ .../Page/SuluPageRendererStrategy.php | 2 +- .../SuluPageRendererStrategyInterface.php | 10 +++ src/Twig/Runtime/SuluRuntime.php | 12 +-- 15 files changed, 478 insertions(+), 15 deletions(-) create mode 100644 spec/ApiClient/SuluApiClientSpec.php create mode 100644 spec/Controller/Action/PurgeSuluCacheActionSpec.php create mode 100644 spec/Controller/Action/RenderPageActionSpec.php create mode 100644 spec/Renderer/Block/SuluBlockRendererStrategySpec.php create mode 100644 spec/Renderer/Page/SuluPageRendererStrategySpec.php create mode 100644 spec/Twig/Runtime/SuluRuntimeSpec.php create mode 100644 src/ApiClient/SuluApiClientInterface.php create mode 100644 src/Renderer/Block/SuluBlockRendererStrategyInterface.php create mode 100644 src/Renderer/Page/SuluPageRendererStrategyInterface.php diff --git a/spec/ApiClient/SuluApiClientSpec.php b/spec/ApiClient/SuluApiClientSpec.php new file mode 100644 index 0000000..96d6f07 --- /dev/null +++ b/spec/ApiClient/SuluApiClientSpec.php @@ -0,0 +1,68 @@ +beConstructedWith($client, $shopperContext, $suluBaseUri, $cacheDir); + } + + public function it_is_initializable(): void + { + $this->shouldHaveType(SuluApiClient::class); + } + + public function it_implements_sulu_api_client_interface_interface(): void + { + $this->shouldHaveType(SuluApiClientInterface::class); + } + +// function it_fetches_cms_content( +// HttpClientInterface $client, +// ShopperContextInterface $shopperContext, +// ChannelInterface $channel, +// ) { +// $url = '/cms/content'; +// $locale = 'en_US'; +// +// $shopperContext->getChannel()->willReturn($channel); +// $shopperContext->getLocaleCode()->willReturn($locale); +// $channel->isSuluUseLocalizedUrls()->willReturn(true); +// +// $client->request('GET', 'http://example.com/en_US/cms/content.json', ['headers' => ['Accept' => 'application/json']])->shouldBeCalled(); +// +// $this->fetchCmsContent($url); +// } +// +// function it_fetches_cms_content_with_global_channel( +// HttpClientInterface $client, +// ShopperContextInterface $shopperContext, +// ChannelInterface $channel, +// ) { +// $url = '/cms/content'; +// +// $shopperContext->getChannel()->willReturn($channel); +// $shopperContext->getLocaleCode()->willReturn(null); +// $channel->isSuluUseLocalizedUrls()->willReturn(false); +// +// +// $client->request('GET', 'http://example.com/cms/content.json', ['headers' => ['Accept' => 'application/json']])->shouldBeCalled(); +// +// $this->fetchCmsContent($url); +// } +} diff --git a/spec/Controller/Action/PurgeSuluCacheActionSpec.php b/spec/Controller/Action/PurgeSuluCacheActionSpec.php new file mode 100644 index 0000000..465c477 --- /dev/null +++ b/spec/Controller/Action/PurgeSuluCacheActionSpec.php @@ -0,0 +1,62 @@ +beConstructedWith($channelRepository, $requestStack, $translator, $cacheDir); + } + + function it_is_initializable() + { + $this->shouldHaveType(PurgeSuluCacheAction::class); + } + + function it_returns_response( + ChannelRepositoryInterface $channelRepository, + ChannelInterface $channel, + RequestStack $requestStack, + Request $request, + ServerBag $serverBag, + Session $session, + FlashBagInterface $flashbag, + ) { + $channelId = 1; + $localeCode = 'en_US'; + $referer = 'http://example.com'; + + $request->get('id')->willReturn($channelId); + $request->get('locale')->willReturn($localeCode); + $request->server = $serverBag; + $serverBag->get('HTTP_REFERER')->willReturn($referer); + $session->getFlashBag()->willReturn($flashbag); + + $channel->getCode()->willReturn('TEST'); + $channelRepository->find($channelId)->willReturn($channel); + + $requestStack->getSession()->willReturn($session); + + $this->__invoke($request)->shouldBeAnInstanceOf(RedirectResponse::class); + } +} diff --git a/spec/Controller/Action/RenderPageActionSpec.php b/spec/Controller/Action/RenderPageActionSpec.php new file mode 100644 index 0000000..abadab0 --- /dev/null +++ b/spec/Controller/Action/RenderPageActionSpec.php @@ -0,0 +1,84 @@ +beConstructedWith($suluApiClient, $pageRendererStrategy); + } + + function it_is_initializable() + { + $this->shouldHaveType(RenderPageAction::class); + } + + function it_returns_response_for_valid_url( + SuluApiClientInterface $suluApiClient, + SuluPageRendererStrategyInterface $pageRendererStrategy, + Request $request, + ) { + $url = 'example-page'; + $pageContent = '

Example Page

'; + + $request->get('slug')->willReturn($url); + $request->get('second_slug')->willReturn(null); + + $suluApiClient->fetchCmsContent($url)->willReturn(['content' => $pageContent]); + $pageRendererStrategy->renderPage(['content' => $pageContent])->willReturn($pageContent); + + $this->__invoke($request)->shouldBeAnInstanceOf(Response::class); + $this->__invoke($request)->getContent()->shouldReturn($pageContent); + } + + function it_returns_response_for_valid_url_with_second_slug( + SuluApiClientInterface $suluApiClient, + SuluPageRendererStrategyInterface $pageRendererStrategy, + Request $request, + ) { + $url = 'example-page'; + $secondSlug = 'second-slug'; + $fullUrl = "{$url}/{$secondSlug}"; + $pageContent = '

Example Page

'; + + $request->get('slug')->willReturn($url); + $request->get('second_slug')->willReturn($secondSlug); + + $suluApiClient->fetchCmsContent($fullUrl)->willReturn(['content' => $pageContent]); + $pageRendererStrategy->renderPage(['content' => $pageContent])->willReturn($pageContent); + + $this->__invoke($request)->shouldBeAnInstanceOf(Response::class); + $this->__invoke($request)->getContent()->shouldReturn($pageContent); + } + + function it_returns_404_response_for_unknown_url( + SuluApiClientInterface $suluApiClient, + Request $request, + SuluPageRendererStrategyInterface $pageRendererStrategy, + ) { + $url = 'non-existing-page'; + + $request->get('slug')->willReturn($url); + $request->get('second_slug')->willReturn(null); + + $suluApiClient->fetchCmsContent($url)->willReturn([]); + $pageRendererStrategy->renderPage([])->willReturn(''); + + $response = $this->__invoke($request); + $response->shouldBeAnInstanceOf(Response::class); + $response->getStatusCode()->shouldReturn(404); + } +} diff --git a/spec/Renderer/Block/SuluBlockRendererStrategySpec.php b/spec/Renderer/Block/SuluBlockRendererStrategySpec.php new file mode 100644 index 0000000..9bf9480 --- /dev/null +++ b/spec/Renderer/Block/SuluBlockRendererStrategySpec.php @@ -0,0 +1,63 @@ +beConstructedWith([$blockRenderer1, $blockRenderer2]); + } + + function it_is_initializable() + { + $this->shouldHaveType(SuluBlockRendererStrategy::class); + } + + function it_throws_runtime_error_if_no_renderer_is_found( + SuluBlockRenderStrategyInterface $blockRenderer1, + SuluBlockRenderStrategyInterface $blockRenderer2, + ) { + $blockData = ['type' => 'non-existing-type']; + + $blockRenderer1->support($blockData)->willReturn(false); + $blockRenderer2->support($blockData)->willReturn(false); + + $this->shouldThrow(RuntimeError::class)->during('renderBlock', [$blockData]); + } + + function it_returns_rendered_block_content( + SuluBlockRenderStrategyInterface $blockRenderer1, + SuluBlockRenderStrategyInterface $blockRenderer2, + ) { + $blockData = ['type' => 'existing-type', 'data' => []]; + $renderedContent = '
Rendered content
'; + + $blockRenderer1->support($blockData)->willReturn(false); + $blockRenderer2->support($blockData)->willReturn(true); + $blockRenderer2->render($blockData)->willReturn($renderedContent); + + $this->renderBlock($blockData)->shouldReturn($renderedContent); + } + + function it_returns_empty_string_on_render_error( + SuluBlockRenderStrategyInterface $blockRenderer1, + SuluBlockRenderStrategyInterface $blockRenderer2, + ) { + $blockData = ['type' => 'existing-type', 'data' => []]; + + $blockRenderer1->support($blockData)->willReturn(false); + $blockRenderer2->support($blockData)->willReturn(true); + $blockRenderer2->render($blockData)->willThrow(Error::class); + + $this->renderBlock($blockData)->shouldReturn(''); + } +} diff --git a/spec/Renderer/Page/SuluPageRendererStrategySpec.php b/spec/Renderer/Page/SuluPageRendererStrategySpec.php new file mode 100644 index 0000000..5442595 --- /dev/null +++ b/spec/Renderer/Page/SuluPageRendererStrategySpec.php @@ -0,0 +1,64 @@ +beConstructedWith([$pageRenderer1, $pageRenderer2]); + } + + function it_is_initializable() + { + $this->shouldHaveType(SuluPageRendererStrategy::class); + } + + function it_throws_runtime_error_if_no_renderer_is_found( + SuluPageRenderStrategyInterface $pageRenderer1, + SuluPageRenderStrategyInterface $pageRenderer2, + ) { + $page = ['template' => 'non-existing-template']; + + $pageRenderer1->support($page)->willReturn(false); + $pageRenderer2->support($page)->willReturn(false); + + $this->shouldThrow(\Twig\Error\RuntimeError::class)->during('renderPage', [$page]); + } + + function it_returns_rendered_page_content( + SuluPageRenderStrategyInterface $pageRenderer1, + SuluPageRenderStrategyInterface $pageRenderer2, + ) { + $page = ['template' => 'existing-template', 'data' => []]; + $renderedContent = '

Rendered Page

'; + + $pageRenderer1->support($page)->willReturn(false); + $pageRenderer2->support($page)->willReturn(true); + $pageRenderer2->render($page)->willReturn($renderedContent); + + $this->renderPage($page)->shouldReturn($renderedContent); + } + + function it_returns_empty_string_on_render_error( + SuluPageRenderStrategyInterface $pageRenderer1, + SuluPageRenderStrategyInterface $pageRenderer2, + ) { + $page = ['template' => 'existing-template', 'data' => []]; + + $pageRenderer1->support($page)->willReturn(false); + $pageRenderer2->support($page)->willReturn(true); + $pageRenderer2->render($page)->willThrow(Error::class); + + $this->renderPage($page)->shouldReturn(''); + } +} diff --git a/spec/Twig/Runtime/SuluRuntimeSpec.php b/spec/Twig/Runtime/SuluRuntimeSpec.php new file mode 100644 index 0000000..41247a0 --- /dev/null +++ b/spec/Twig/Runtime/SuluRuntimeSpec.php @@ -0,0 +1,90 @@ +beConstructedWith($suluApiClient, $blockRendererStrategy, $pageRendererStrategy); + } + + function it_is_initializable() + { + $this->shouldHaveType(SuluRuntime::class); + } + + function it_fetches_sulu_page_from_api_client(SuluApiClientInterface $suluApiClient) + { + $id = 'example-page-id'; + $page = ['id' => $id, 'title' => 'Example Page']; + + $suluApiClient->fetchCmsContent($id)->willReturn($page); + + $this->getSuluPage($id)->shouldReturn($page); + } + + function it_renders_sulu_page_using_page_renderer_strategy( + SuluApiClientInterface $suluApiClient, + SuluPageRendererStrategyInterface $pageRendererStrategy, + ) { + $id = 'example-page-id'; + $page = ['id' => $id, 'title' => 'Example Page']; + $renderedPage = '

Example Page

'; + + $suluApiClient->fetchCmsContent($id)->willReturn($page); + $pageRendererStrategy->renderPage($page)->willReturn($renderedPage); + + $this->renderSuluPage($id)->shouldReturn($renderedPage); + } + + function it_renders_sulu_blocks_using_block_renderer_strategy( + SuluBlockRendererStrategyInterface $blockRendererStrategy, + ) { + $blocks = [['type' => 'block-type-1'], ['type' => 'block-type-2']]; + $renderedBlocks = '
Block 1

Block 2

'; + $divider = '
'; + + $blockRendererStrategy->renderBlock($blocks[0])->willReturn('
Block 1
'); + $blockRendererStrategy->renderBlock($blocks[1])->willReturn('
Block 2
'); + + $this->renderSuluBlocks($blocks, $divider)->shouldReturn($renderedBlocks); + } + + function it_renders_sulu_blocks_with_specified_type_using_block_renderer_strategy( + SuluBlockRendererStrategyInterface $blockRendererStrategy, + ) { + $blocks = [['type' => 'block-type-1'], ['type' => 'block-type-2'], ['type' => 'block-type-1']]; + $filteredBlocks = [['type' => 'block-type-1'], ['type' => 'block-type-1']]; + $renderedBlocks = '
Block 1

Block 1

'; + $divider = '
'; + + $blockRendererStrategy->renderBlock($filteredBlocks[0])->willReturn('
Block 1
'); + $blockRendererStrategy->renderBlock($filteredBlocks[1])->willReturn('
Block 1
'); + + $this->renderSuluBlocksWithType($blocks, 'block-type-1', $divider)->shouldReturn($renderedBlocks); + } + + function it_renders_first_sulu_block_with_specified_type_using_block_renderer_strategy( + SuluBlockRendererStrategyInterface $blockRendererStrategy, + ) { + $blocks = [['type' => 'block-type-1', 'content' => 'Block 1 content'], ['type' => 'block-type-2']]; + $filteredBlocks = [['type' => 'block-type-1', 'content' => 'Block 1 content']]; + $renderedBlock = '
Block 1
'; + + $blockRendererStrategy->renderBlock($filteredBlocks[0])->willReturn('
Block 1
'); + + $this->renderSuluBlockWithType($blocks, 'block-type-1')->shouldReturn($renderedBlock); + } +} diff --git a/src/ApiClient/SuluApiClient.php b/src/ApiClient/SuluApiClient.php index d98694d..e345cdf 100644 --- a/src/ApiClient/SuluApiClient.php +++ b/src/ApiClient/SuluApiClient.php @@ -12,7 +12,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface; use Webmozart\Assert\Assert; -final class SuluApiClient +final class SuluApiClient implements SuluApiClientInterface { public function __construct( private HttpClientInterface $client, diff --git a/src/ApiClient/SuluApiClientInterface.php b/src/ApiClient/SuluApiClientInterface.php new file mode 100644 index 0000000..2a8553e --- /dev/null +++ b/src/ApiClient/SuluApiClientInterface.php @@ -0,0 +1,10 @@ +pageRendererStrategy->renderPage($page); if (strlen($page) === 0) { - return new Response(null, 404); + return new Response('', 404); } return new Response($page); diff --git a/src/Entity/ChannelInterface.php b/src/Entity/ChannelInterface.php index 7a5e04f..135c82d 100644 --- a/src/Entity/ChannelInterface.php +++ b/src/Entity/ChannelInterface.php @@ -4,7 +4,9 @@ namespace BitBag\SyliusSuluPlugin\Entity; -interface ChannelInterface +use Sylius\Component\Core\Model\ChannelInterface as BaseChannelInterface; + +interface ChannelInterface extends BaseChannelInterface { public function isSuluUseLocalizedUrls(): bool; diff --git a/src/Renderer/Block/SuluBlockRendererStrategy.php b/src/Renderer/Block/SuluBlockRendererStrategy.php index 79ab6ae..421fa40 100644 --- a/src/Renderer/Block/SuluBlockRendererStrategy.php +++ b/src/Renderer/Block/SuluBlockRendererStrategy.php @@ -7,7 +7,7 @@ use Twig\Error\Error; use Twig\Error\RuntimeError; -final class SuluBlockRendererStrategy +final class SuluBlockRendererStrategy implements SuluBlockRendererStrategyInterface { public function __construct( private iterable $blockRenderers, diff --git a/src/Renderer/Block/SuluBlockRendererStrategyInterface.php b/src/Renderer/Block/SuluBlockRendererStrategyInterface.php new file mode 100644 index 0000000..80940e3 --- /dev/null +++ b/src/Renderer/Block/SuluBlockRendererStrategyInterface.php @@ -0,0 +1,10 @@ + Date: Fri, 23 Feb 2024 08:31:18 +0100 Subject: [PATCH 2/2] OP-237 - write behat tests, mock api responses, create examples of renderers --- composer.json | 2 +- features/caching_sulu_request.feature | 50 +++++ features/render_sulu_page.feature | 27 +++ .../show_featured_pages_on_homepage.feature | 20 ++ src/Entity/SuluChannelConfigurationTrait.php | 10 + src/Twig/Extension/SuluPageExtension.php | 1 + src/Twig/Runtime/SuluRuntime.php | 19 +- src/Twig/Runtime/SuluRuntimeInterface.php | 2 + .../Grid/Action/invalidateSuluCache.html.twig | 2 +- tests/Application/.env | 4 + tests/Application/config/bundles.php | 2 + .../config/doctrine/Channel.Channel.orm.xml | 12 ++ .../Application/config/packages/_sylius.yaml | 32 +++ .../Application/config/packages/doctrine.yaml | 11 ++ .../config/packages/framework.yaml | 5 + .../config/routes/sylius_admin.yaml | 12 ++ .../config/routes/sylius_shop.yaml | 16 ++ tests/Application/config/services.yaml | 2 + tests/Application/config/services_test.yaml | 30 +++ .../src/Entity/Channel/Channel.php | 13 ++ .../src/Renderer/Block/ImageRenderer.php | 47 +++++ .../src/Renderer/Block/QuoteRenderer.php | 47 +++++ .../src/Renderer/Block/TextRenderer.php | 48 +++++ .../src/Renderer/Page/BlogPageRenderer.php | 46 +++++ .../Renderer/Page/FeaturedPagesRenderer.php | 49 +++++ .../shop/block/image.html.twig | 1 + .../shop/block/quote.html.twig | 1 + .../shop/block/text.html.twig | 1 + .../shop/page/blog.html.twig | 48 +++++ .../shop/page/featuredPages.html.twig | 16 ++ .../Homepage/_featuredPages.html.twig | 7 + .../blog_page_with_blocks_and_links.json | 183 ++++++++++++++++++ .../blog_page_with_properties.json | 62 ++++++ .../Behat/ApiResponseMock/featured_pages.json | 141 ++++++++++++++ tests/Behat/Context/Setup/SuluPageContext.php | 119 ++++++++++++ .../Context/Ui/SuluAdminPanelContext.php | 108 +++++++++++ tests/Behat/Context/Ui/SuluPageContext.php | 89 +++++++++ tests/Behat/Page/ChannelIndexPage.php | 21 ++ tests/Behat/Page/HomePage.php | 18 ++ tests/Behat/Page/SuluPage.php | 37 ++++ tests/Behat/Resources/services.xml | 63 ++++++ tests/Behat/Resources/suites.yml | 4 + .../Resources/suites/ui/cache_sulu_page.yml | 22 +++ .../Resources/suites/ui/render_sulu_page.yml | 19 ++ tests/Behat/Resources/suites/ui/sulu_page.yml | 19 ++ tests/Behat/Services/SuluApiClient.php | 100 ++++++++++ 46 files changed, 1585 insertions(+), 3 deletions(-) create mode 100644 features/caching_sulu_request.feature create mode 100644 features/render_sulu_page.feature create mode 100644 features/show_featured_pages_on_homepage.feature create mode 100644 tests/Application/config/doctrine/Channel.Channel.orm.xml create mode 100644 tests/Application/src/Entity/Channel/Channel.php create mode 100644 tests/Application/src/Renderer/Block/ImageRenderer.php create mode 100644 tests/Application/src/Renderer/Block/QuoteRenderer.php create mode 100644 tests/Application/src/Renderer/Block/TextRenderer.php create mode 100644 tests/Application/src/Renderer/Page/BlogPageRenderer.php create mode 100644 tests/Application/src/Renderer/Page/FeaturedPagesRenderer.php create mode 100644 tests/Application/templates/bundles/BitBagSyliusSuluPlugin/shop/block/image.html.twig create mode 100644 tests/Application/templates/bundles/BitBagSyliusSuluPlugin/shop/block/quote.html.twig create mode 100644 tests/Application/templates/bundles/BitBagSyliusSuluPlugin/shop/block/text.html.twig create mode 100644 tests/Application/templates/bundles/BitBagSyliusSuluPlugin/shop/page/blog.html.twig create mode 100644 tests/Application/templates/bundles/BitBagSyliusSuluPlugin/shop/page/featuredPages.html.twig create mode 100644 tests/Application/templates/bundles/SyliusShopBundle/Homepage/_featuredPages.html.twig create mode 100644 tests/Behat/ApiResponseMock/blog_page_with_blocks_and_links.json create mode 100644 tests/Behat/ApiResponseMock/blog_page_with_properties.json create mode 100644 tests/Behat/ApiResponseMock/featured_pages.json create mode 100644 tests/Behat/Context/Setup/SuluPageContext.php create mode 100644 tests/Behat/Context/Ui/SuluAdminPanelContext.php create mode 100644 tests/Behat/Context/Ui/SuluPageContext.php create mode 100644 tests/Behat/Page/ChannelIndexPage.php create mode 100644 tests/Behat/Page/HomePage.php create mode 100644 tests/Behat/Page/SuluPage.php create mode 100644 tests/Behat/Resources/suites.yml create mode 100644 tests/Behat/Resources/suites/ui/cache_sulu_page.yml create mode 100644 tests/Behat/Resources/suites/ui/render_sulu_page.yml create mode 100644 tests/Behat/Resources/suites/ui/sulu_page.yml create mode 100644 tests/Behat/Services/SuluApiClient.php diff --git a/composer.json b/composer.json index 7c83bb2..111e7a1 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ }, "require-dev": { "behat/behat": "^3.6.1", - "behat/mink-selenium2-driver": "^1.4", + "behat/mink-selenium2-driver": "~1.6.0", "bitbag/coding-standard": "^3.0", "dmore/behat-chrome-extension": "^1.3", "dmore/chrome-mink-driver": "^2.7", diff --git a/features/caching_sulu_request.feature b/features/caching_sulu_request.feature new file mode 100644 index 0000000..4cc118d --- /dev/null +++ b/features/caching_sulu_request.feature @@ -0,0 +1,50 @@ +@sulu_cache +Feature: Caching sulu page request + In order to see again some page + As a Visitor + I want to be able to see the page without sending request to sulu + + Background: + Given the store operates on a single channel in "United States" + And Sulu has defined page "blog_page_with_blocks_and_links" in locale "en_US" + And Cache for sulu not exists + + + @ui + Scenario: See the featured pages on homepage + When I visit this channel's homepage + And "United States" has enabled sulu localized requests + Then Sulu cache should not exists + And I visit a sulu page "blog_page_with_blocks_and_links" in locale en_US + And Sulu cache should exists for "United States" with locale en_US + + @ui + Scenario: Manually clear cache when localized urls are disabled + When I visit a sulu page "blog_page_with_blocks_and_links" in locale en_US + Then Sulu cache should exists + And I am logged in as an administrator + And I browse channels + And I should see button "Purge sulu cache" in "United States" + And I click "Clear Cache" button in "United States" + And I should see success "Successfully purged" flash message + And Sulu cache should exists for "United States" with locale en_US + + @ui + Scenario: Manually clear cache when localized urls are enabled + When "United States" has enabled sulu localized requests + And I visit a sulu page "blog_page_with_blocks_and_links" in locale en_US + Then Sulu cache should exists + And I am logged in as an administrator + And I browse channels + And I should see expanded button "Purge sulu cache" in "United States" + And I click expanded "en_US" button in "United States" + And I should see success "Successfully purged" flash message + And Sulu cache should exists for "United States" with locale en_US + + @ui + Scenario: Manually clear cache when localized urls are disabled and cache not exists + When I am logged in as an administrator + And I browse channels + Then I should see button "Purge sulu cache" in "United States" + And I click "Purge sulu cache" button in "United States" + And I should see error "Dir with sulu cache not found" flash message diff --git a/features/render_sulu_page.feature b/features/render_sulu_page.feature new file mode 100644 index 0000000..b617487 --- /dev/null +++ b/features/render_sulu_page.feature @@ -0,0 +1,27 @@ +@render_sulu_page +Feature: Render sulu page + In order to see a sulu page + As a Visitor + I want to be able to see rendered sulu page + + Background: + Given the store operates on a single channel in "United States" + And Sulu has defined page "blog_page_with_properties" in locale "en_US" + And Sulu has defined page "blog_page_with_blocks_and_links" in locale "en_US" + And Page "blog_page_with_blocks_and_links" has block "quote" + And Page "blog_page_with_blocks_and_links" has block "text" + And Page "blog_page_with_blocks_and_links" has block "image" + + @ui + Scenario: Rendering a sulu page with properties + When I visit a sulu page "blog_page_with_properties" in locale en_US + Then I should see a "title" with value "E-commerce trends" + And I should see a "content" with value "CONTENT" + + @ui + Scenario: Rendering a sulu page with properties and blocks + When I visit a sulu page "blog_page_with_blocks_and_links" in locale en_US + Then I should see a "title" with value "E-commerce trends" + And I should see a block "content" with value "2021 was followed by the time of the 2020 pandemic. During these two years, a lot has changed..." + And I should see a block image with url "https://en.wikipedia.org/wiki/Cat#/media/File:Sheba1.JPG" + And I should see a block "quote" with value "Lorem ipsum dolor sit amet, con" diff --git a/features/show_featured_pages_on_homepage.feature b/features/show_featured_pages_on_homepage.feature new file mode 100644 index 0000000..daa2964 --- /dev/null +++ b/features/show_featured_pages_on_homepage.feature @@ -0,0 +1,20 @@ +@sulu_page +Feature: Show featured pages on homepage + In order to see featured pages on homepage + As a Visitor + I want to be able to see featured pages on homepage + + Background: + Given the store operates on a single channel in "United States" + And Sulu has defined featured pages list featured_pages in locale en_US + And One of the featured page is page "Blog Page 1" + And One of the featured page is page "Blog Page 2" + And One of the featured page is page "Blog Page 3" + + @ui + Scenario: See the featured pages on homepage + When I visit this channel's homepage + Then I should see 3 featured pages. + And I should see featured page "Blog Page 1" + And I should see featured page "Blog Page 2" + And I should see featured page "Blog Page 3" diff --git a/src/Entity/SuluChannelConfigurationTrait.php b/src/Entity/SuluChannelConfigurationTrait.php index 2143228..583e729 100644 --- a/src/Entity/SuluChannelConfigurationTrait.php +++ b/src/Entity/SuluChannelConfigurationTrait.php @@ -4,8 +4,18 @@ namespace BitBag\SyliusSuluPlugin\Entity; +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity + * + * @ORM\Table(name="sylius_channel") + */ +#[ORM\Entity] +#[ORM\Table(name: 'sylius_channel')] trait SuluChannelConfigurationTrait { + /** @ORM\Column(type="boolean", nullable=false) */ protected bool $suluUseLocalizedUrls = false; public function isSuluUseLocalizedUrls(): bool diff --git a/src/Twig/Extension/SuluPageExtension.php b/src/Twig/Extension/SuluPageExtension.php index 064137c..6d927ee 100644 --- a/src/Twig/Extension/SuluPageExtension.php +++ b/src/Twig/Extension/SuluPageExtension.php @@ -23,6 +23,7 @@ public function getFunctions(): array new TwigFunction('bitbag_render_sulu_blocks', [$this->suluRuntime, 'renderSuluBlocks']), new TwigFunction('bitbag_render_sulu_blocks_with_type', [$this->suluRuntime, 'renderSuluBlocksWithType']), new TwigFunction('bitbag_render_sulu_block_with_type', [$this->suluRuntime, 'renderSuluBlockWithType']), + new TwigFunction('bitbag_page_has_sulu_block', [$this->suluRuntime, 'hasSuluBlock']), ]; } } diff --git a/src/Twig/Runtime/SuluRuntime.php b/src/Twig/Runtime/SuluRuntime.php index c8e7104..f31e6ea 100644 --- a/src/Twig/Runtime/SuluRuntime.php +++ b/src/Twig/Runtime/SuluRuntime.php @@ -59,10 +59,10 @@ public function renderSuluBlocksWithType(array $blocks, string $type, ?string $d public function renderSuluBlockWithType(array $blocks, string $type): string { $blocks = array_filter($blocks, fn (array $block) => $block['type'] === $type); - if (count($blocks) > 1) { $blocks = $blocks[0]; } + $content = ''; foreach ($blocks as $block) { @@ -71,4 +71,21 @@ public function renderSuluBlockWithType(array $blocks, string $type): string return $content; } + + public function hasSuluBlock(array $page, string $type): bool + { + if (!array_key_exists('blocks', $page)) { + return false; + } + + $blocks = $page['blocks']; + + if (count($blocks) === 0) { + return false; + } + + $blocks = array_filter($blocks, fn (array $block) => $block['type'] === $type); + + return count($blocks) !== 0; + } } diff --git a/src/Twig/Runtime/SuluRuntimeInterface.php b/src/Twig/Runtime/SuluRuntimeInterface.php index 643f1ec..f1c7753 100644 --- a/src/Twig/Runtime/SuluRuntimeInterface.php +++ b/src/Twig/Runtime/SuluRuntimeInterface.php @@ -17,4 +17,6 @@ public function renderSuluBlocks(array $blocks): string; public function renderSuluBlocksWithType(array $blocks, string $type): string; public function renderSuluBlockWithType(array $blocks, string $type): string; + + public function hasSuluBlock(array $page, string $type): bool; } diff --git a/templates/Admin/Grid/Action/invalidateSuluCache.html.twig b/templates/Admin/Grid/Action/invalidateSuluCache.html.twig index 2523db1..24be26c 100644 --- a/templates/Admin/Grid/Action/invalidateSuluCache.html.twig +++ b/templates/Admin/Grid/Action/invalidateSuluCache.html.twig @@ -1,5 +1,5 @@ {% if true == data.isSuluUseLocalizedUrls %} -