From 8a1161ee7a78d8a28f04042c2f97f8dfa83ccee7 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 6 Mar 2025 02:14:48 +0300 Subject: [PATCH 01/20] tests --- src/UrlParametersFactory.php | 3 + tests/Column/Base/GlobalContextTest.php | 85 ++++++++ tests/Column/Base/RendererContainerTest.php | 114 ++++++++++ tests/Column/CheckboxColumnRendererTest.php | 224 ++++++++++++++++++++ tests/Column/DataColumnRendererTest.php | 219 +++++++++++++++++++ tests/UrlParametersFactoryTest.php | 76 ++++--- 6 files changed, 688 insertions(+), 33 deletions(-) create mode 100644 tests/Column/Base/GlobalContextTest.php create mode 100644 tests/Column/Base/RendererContainerTest.php create mode 100644 tests/Column/CheckboxColumnRendererTest.php diff --git a/src/UrlParametersFactory.php b/src/UrlParametersFactory.php index 063f5ab73..d100a327c 100644 --- a/src/UrlParametersFactory.php +++ b/src/UrlParametersFactory.php @@ -32,6 +32,9 @@ final class UrlParametersFactory * - Path arguments as key-value pairs * - Query parameters as key-value pairs */ + /** + * @return array{0: array, 1: array} + */ public static function create( ?PageToken $pageToken, int|string|null $pageSize, diff --git a/tests/Column/Base/GlobalContextTest.php b/tests/Column/Base/GlobalContextTest.php new file mode 100644 index 000000000..bbdf46b80 --- /dev/null +++ b/tests/Column/Base/GlobalContextTest.php @@ -0,0 +1,85 @@ +createMock(ReadableDataInterface::class); + $translator = $this->createMock(TranslatorInterface::class); + $pathArguments = ['id' => 123]; + $queryParameters = ['sort' => 'name']; + $translationCategory = 'app'; + + $context = new GlobalContext( + $dataReader, + $pathArguments, + $queryParameters, + $translator, + $translationCategory + ); + + $this->assertSame($dataReader, $context->dataReader); + $this->assertSame($pathArguments, $context->pathArguments); + $this->assertSame($queryParameters, $context->queryParameters); + } + + public function testTranslateWithString(): void + { + $translator = $this->createMock(TranslatorInterface::class); + $translator + ->expects($this->once()) + ->method('translate') + ->with('test.message', [], 'app') + ->willReturn('Test Message'); + + $context = new GlobalContext( + $this->createMock(ReadableDataInterface::class), + [], + [], + $translator, + 'app' + ); + + $this->assertSame('Test Message', $context->translate('test.message')); + } + + public function testTranslateWithStringable(): void + { + $stringable = new class implements Stringable { + public function __toString(): string + { + return 'test.stringable'; + } + }; + + $translator = $this->createMock(TranslatorInterface::class); + $translator + ->expects($this->once()) + ->method('translate') + ->with('test.stringable', [], 'app') + ->willReturn('Test Stringable'); + + $context = new GlobalContext( + $this->createMock(ReadableDataInterface::class), + [], + [], + $translator, + 'app' + ); + + $this->assertSame('Test Stringable', $context->translate($stringable)); + } +} diff --git a/tests/Column/Base/RendererContainerTest.php b/tests/Column/Base/RendererContainerTest.php new file mode 100644 index 000000000..cecb00059 --- /dev/null +++ b/tests/Column/Base/RendererContainerTest.php @@ -0,0 +1,114 @@ +renderer = new TestRenderer(); + $this->container = $this->createMock(ContainerInterface::class); + $this->container + ->method('get') + ->willReturnCallback(fn(string $class) => match ($class) { + TestRenderer::class => $this->renderer, + default => throw new \RuntimeException("Unexpected class: $class"), + }); + $this->rendererContainer = new RendererContainer($this->container); + } + + public function testGetCreatesNewInstance(): void + { + $instance = $this->rendererContainer->get(TestRenderer::class); + $this->assertInstanceOf(TestRenderer::class, $instance); + } + + public function testGetReturnsCachedInstance(): void + { + $instance1 = $this->rendererContainer->get(TestRenderer::class); + $instance2 = $this->rendererContainer->get(TestRenderer::class); + $this->assertSame($instance1, $instance2); + } + + public function testAddConfigsCreatesNewInstanceWithConfig(): void + { + $container = $this->rendererContainer->addConfigs([ + TestRenderer::class => ['value' => 'custom'], + ]); + + $instance = $container->get(TestRenderer::class); + $this->assertSame('custom', $instance->getValue()); + } + + public function testAddConfigsMergesExistingConfig(): void + { + $container = $this->rendererContainer + ->addConfigs([TestRenderer::class => ['value' => 'first']]) + ->addConfigs([TestRenderer::class => ['option' => 'second']]); + + $instance = $container->get(TestRenderer::class); + $this->assertSame('first', $instance->getValue()); + $this->assertSame('second', $instance->getOption()); + } +} + +/** + * Test renderer implementation. + */ +final class TestRenderer implements ColumnRendererInterface +{ + public function __construct( + private string $value = 'default', + private string $option = 'default', + ) { + } + + public function getValue(): string + { + return $this->value; + } + + public function getOption(): string + { + return $this->option; + } + + public function renderColumn(ColumnInterface $column, Cell $cell, GlobalContext $context): Cell + { + return $cell; + } + + public function renderHeader(ColumnInterface $column, Cell $cell, HeaderContext $context): ?Cell + { + return $cell; + } + + public function renderBody(ColumnInterface $column, Cell $cell, DataContext $context): Cell + { + return $cell; + } + + public function renderFooter(ColumnInterface $column, Cell $cell, GlobalContext $context): Cell + { + return $cell; + } +} diff --git a/tests/Column/CheckboxColumnRendererTest.php b/tests/Column/CheckboxColumnRendererTest.php new file mode 100644 index 000000000..85ba7c6bb --- /dev/null +++ b/tests/Column/CheckboxColumnRendererTest.php @@ -0,0 +1,224 @@ +renderer = new CheckboxColumnRenderer(); + $this->cell = new Cell(); + $this->dataReader = new IterableDataReader([ + ['id' => 1, 'name' => 'John'], + ['id' => 2, 'name' => 'Mary'], + ]); + $this->globalContext = new GlobalContext( + $this->dataReader, + [], + [], + Mock::translator('en'), + 'test' + ); + } + + public function testRenderColumn(): void + { + $column = new CheckboxColumn(columnAttributes: ['class' => 'test-class']); + $result = $this->renderer->renderColumn($column, $this->cell, $this->globalContext); + $this->assertSame(['class' => 'test-class'], $result->getAttributes()); + } + + public function testRenderHeaderWithoutHeaderAndSingleSelection(): void + { + $column = new CheckboxColumn(multiple: false); + $sort = Sort::any(); + $context = new HeaderContext( + $sort, + $sort, + ['test' => 'test'], + 'sortable', + '', + '', + 'asc', + '', + '', + 'desc', + '', + '', + [], + 'asc-link', + 'desc-link', + null, + 10, + false, + new UrlConfig(), + null, + Mock::translator('en'), + 'test' + ); + $result = $this->renderer->renderHeader($column, $this->cell, $context); + $this->assertNull($result); + } + + public function testRenderHeaderWithoutHeaderAndMultipleSelection(): void + { + $column = new CheckboxColumn(multiple: true); + $sort = Sort::any(); + $context = new HeaderContext( + $sort, + $sort, + ['test' => 'test'], + 'sortable', + '', + '', + 'asc', + '', + '', + 'desc', + '', + '', + [], + 'asc-link', + 'desc-link', + null, + 10, + false, + new UrlConfig(), + null, + Mock::translator('en'), + 'test' + ); + $result = $this->renderer->renderHeader($column, $this->cell, $context); + $this->assertNotNull($result); + $this->assertStringContainsString('checkbox-selection-all', (string) $result->getContent()[0]); + } + + public function testRenderHeaderWithCustomHeader(): void + { + $column = new CheckboxColumn( + header: 'Custom Header', + headerAttributes: ['class' => 'header-class'] + ); + $sort = Sort::any(); + $context = new HeaderContext( + $sort, + $sort, + ['test' => 'test'], + 'sortable', + '', + '', + 'asc', + '', + '', + 'desc', + '', + '', + [], + 'asc-link', + 'desc-link', + null, + 10, + false, + new UrlConfig(), + null, + Mock::translator('en'), + 'test' + ); + $result = $this->renderer->renderHeader($column, $this->cell, $context); + $this->assertNotNull($result); + $this->assertSame('Custom Header', $result->getContent()[0]); + $this->assertSame(['class' => 'header-class'], $result->getAttributes()); + } + + public function testRenderBodyWithDefaultNameAndValue(): void + { + $column = new CheckboxColumn(); + $context = new DataContext( + $this->dataReader, + $column, + ['id' => 1, 'name' => 'John'], + 1, + 0 + ); + $result = $this->renderer->renderBody($column, $this->cell, $context); + $content = (string) $result->getContent()[0]; + $this->assertStringContainsString('name="checkbox-selection"', $content); + $this->assertStringContainsString('value="1"', $content); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithCustomNameAndValue(): void + { + $column = new CheckboxColumn( + inputAttributes: [ + 'name' => 'custom-name', + 'value' => 'custom-value', + 'class' => 'custom-class', + ] + ); + $context = new DataContext( + $this->dataReader, + $column, + ['id' => 1, 'name' => 'John'], + 1, + 0 + ); + $result = $this->renderer->renderBody($column, $this->cell, $context); + $content = (string) $result->getContent()[0]; + $this->assertStringContainsString('name="custom-name"', $content); + $this->assertStringContainsString('value="custom-value"', $content); + $this->assertStringContainsString('class="custom-class"', $content); + } + + public function testRenderBodyWithCustomContent(): void + { + $column = new CheckboxColumn( + content: static fn(Checkbox $input, DataContext $context): string => "
{$input->render()}
" + ); + $context = new DataContext( + $this->dataReader, + $column, + ['id' => 1, 'name' => 'John'], + 1, + 0 + ); + $result = $this->renderer->renderBody($column, $this->cell, $context); + $content = (string) $result->getContent()[0]; + $this->assertStringStartsWith('
', $content); + $this->assertStringEndsWith('
', $content); + } + + public function testRenderFooterWithContent(): void + { + $column = new CheckboxColumn(footer: 'Test Footer'); + $result = $this->renderer->renderFooter($column, $this->cell, $this->globalContext); + $this->assertSame('Test Footer', $result->getContent()[0]); + } + + public function testRenderFooterWithoutContent(): void + { + $column = new CheckboxColumn(); + $result = $this->renderer->renderFooter($column, $this->cell, $this->globalContext); + $this->assertEmpty($result->getContent()); + } +} diff --git a/tests/Column/DataColumnRendererTest.php b/tests/Column/DataColumnRendererTest.php index 47709bcb0..7a93d8a82 100644 --- a/tests/Column/DataColumnRendererTest.php +++ b/tests/Column/DataColumnRendererTest.php @@ -15,11 +15,14 @@ use Yiisoft\Yii\DataView\Column\Base\DataContext; use Yiisoft\Yii\DataView\Column\Base\GlobalContext; use Yiisoft\Yii\DataView\Column\Base\HeaderContext; +use Yiisoft\Yii\DataView\Column\Base\FilterContext; +use Yiisoft\Yii\DataView\Column\Base\MakeFilterContext; use Yiisoft\Yii\DataView\Column\DataColumn; use Yiisoft\Yii\DataView\Column\DataColumnRenderer; use Yiisoft\Yii\DataView\Tests\Support\Mock; use Yiisoft\Yii\DataView\Tests\Support\TestTrait; use Yiisoft\Yii\DataView\UrlConfig; +use Yiisoft\Validator\Rule\Number; final class DataColumnRendererTest extends TestCase { @@ -144,4 +147,220 @@ public function testGetOrderProperties(): void $result = $renderer->getOrderProperties($column); $this->assertEquals(['test' => 'test'], $result); } + + public function testRenderBodyWithCustomContentCallback(): void + { + $column = new DataColumn( + 'name', + content: static fn (array $data) => strtoupper($data['name']) + ); + $cell = new Cell(); + $data = ['id' => 1, 'name' => 'John Doe', 'age' => 20]; + + $context = new DataContext( + $this->dataReader, + $column, + $data, + 1, + 0 + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderBody($column, $cell, $context); + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('JOHN DOE', (string)$content[0]); + } + + public function testRenderBodyWithDateTime(): void + { + $date = new \DateTime('2025-03-06 02:00:22'); + $column = new DataColumn('created_at', dateTimeFormat: 'Y-m-d'); + $cell = new Cell(); + $data = ['id' => 1, 'created_at' => $date]; + + $context = new DataContext( + $this->dataReader, + $column, + $data, + 1, + 0 + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderBody($column, $cell, $context); + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('2025-03-06', (string)$content[0]); + } + + public function testRenderBodyWithDynamicAttributes(): void + { + $column = new DataColumn( + 'age', + bodyAttributes: static fn (array $data) => ['class' => $data['age'] >= 21 ? 'adult' : 'minor'] + ); + $cell = new Cell(); + $data = ['id' => 2, 'name' => 'Mary', 'age' => 21]; + + $context = new DataContext( + $this->dataReader, + $column, + $data, + 1, + 0 + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderBody($column, $cell, $context); + $this->assertStringContainsString('adult', $result->getAttributes()['class']); + } + + public function testRenderFilterWithDropdown(): void + { + $column = new DataColumn( + 'status', + filter: ['active' => 'Active', 'inactive' => 'Inactive'] + ); + $cell = new Cell(); + + $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return 'active'; + } + }; + + $context = new FilterContext( + 'filter-form', + new \Yiisoft\Validator\Result(), + 'invalid', + ['class' => 'error-container'], + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderFilter($column, $cell, $context); + $this->assertNotNull($result); + $content = $result->getContent(); + $this->assertStringContainsString('select', (string)$content[0]); + $this->assertStringContainsString('Active', (string)$content[0]); + $this->assertStringContainsString('Inactive', (string)$content[0]); + } + + public function testMakeFilterWithCustomFactory(): void + { + $column = new DataColumn( + 'name', + filterFactory: \Yiisoft\Yii\DataView\Filter\Factory\LikeFilterFactory::class + ); + + $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return match ($name) { + 'name' => 'John', + 'age' => 'not-a-number', + 'status' => '', + default => null, + }; + } + }; + + $context = new MakeFilterContext( + new \Yiisoft\Validator\Result(), + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->makeFilter($column, $context); + $this->assertNotNull($result); + } + + public function testMakeFilterWithValidation(): void + { + $column = new DataColumn( + 'age', + filterValidation: [new Number()] + ); + + $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return match ($name) { + 'name' => 'John', + 'age' => 'not-a-number', + 'status' => '', + default => null, + }; + } + }; + + $context = new MakeFilterContext( + new \Yiisoft\Validator\Result(), + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->makeFilter($column, $context); + $this->assertNull($result); + $this->assertNotEmpty($context->validationResult->getErrors()); + } + + public function testMakeFilterWithEmptyValue(): void + { + $column = new DataColumn( + 'status', + filterEmpty: true + ); + + $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return match ($name) { + 'name' => 'John', + 'age' => 'not-a-number', + 'status' => '', + default => null, + }; + } + }; + + $context = new MakeFilterContext( + new \Yiisoft\Validator\Result(), + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->makeFilter($column, $context); + $this->assertNull($result); + } } diff --git a/tests/UrlParametersFactoryTest.php b/tests/UrlParametersFactoryTest.php index 63166e1ff..90022f22e 100644 --- a/tests/UrlParametersFactoryTest.php +++ b/tests/UrlParametersFactoryTest.php @@ -16,31 +16,6 @@ */ final class UrlParametersFactoryTest extends TestCase { - public function testCreateWithNullValues(): void - { - $config = new UrlConfig( - pageParameterType: UrlParameterType::QUERY, - previousPageParameterType: UrlParameterType::QUERY, - pageSizeParameterType: UrlParameterType::QUERY, - sortParameterType: UrlParameterType::QUERY - ); - - [$arguments, $queryParameters] = UrlParametersFactory::create( - null, - null, - null, - $config - ); - - $this->assertSame([], $arguments); - $this->assertSame([ - 'page' => null, - 'prev-page' => null, - 'pagesize' => null, - 'sort' => null, - ], $queryParameters); - } - public function testCreateWithNextPageTokenInQueryParameter(): void { $config = new UrlConfig( @@ -293,25 +268,60 @@ public function testCreateWithExistingArgumentsAndQueryParameters(): void ], $queryParameters); } - public function testCreateWithInstanceMethod(): void + public function testCreateWithMixedParameterTypesAndValues(): void { $config = new UrlConfig( - pageParameterType: UrlParameterType::QUERY, + pageParameterType: UrlParameterType::PATH, previousPageParameterType: UrlParameterType::QUERY, + pageSizeParameterType: UrlParameterType::PATH, + sortParameterType: UrlParameterType::QUERY, + arguments: ['id' => 123], + queryParameters: ['filter' => 'active'] + ); + + [$arguments, $queryParameters] = UrlParametersFactory::create( + PageToken::next('token123'), + 20, + 'name,-date', + $config + ); + + $this->assertSame([ + 'id' => 123, + 'page' => 'token123', + 'pagesize' => 20, + ], $arguments); + $this->assertSame([ + 'filter' => 'active', + 'prev-page' => null, + 'sort' => 'name,-date', + ], $queryParameters); + } + + public function testCreateWithNullPageToken(): void + { + $config = new UrlConfig( + pageParameterType: UrlParameterType::PATH, + previousPageParameterType: UrlParameterType::PATH, pageSizeParameterType: UrlParameterType::QUERY, sortParameterType: UrlParameterType::QUERY ); - $result = UrlParametersFactory::create(null, null, null, $config); - - [$arguments, $queryParameters] = $result; + [$arguments, $queryParameters] = UrlParametersFactory::create( + null, + 20, + 'name,-date', + $config + ); - $this->assertSame([], $arguments); $this->assertSame([ 'page' => null, 'prev-page' => null, - 'pagesize' => null, - 'sort' => null, + ], $arguments); + $this->assertSame([ + 'pagesize' => 20, + 'sort' => 'name,-date', ], $queryParameters); } } + From c99b92819ea9b2f6f8b3d8255e82c68a3850431d Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 6 Mar 2025 00:09:57 +0000 Subject: [PATCH 02/20] Apply fixes from StyleCI --- src/UrlParametersFactory.php | 2 +- tests/Column/Base/GlobalContextTest.php | 2 +- tests/Column/DataColumnRendererTest.php | 8 ++++---- tests/UrlParametersFactoryTest.php | 1 - 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/UrlParametersFactory.php b/src/UrlParametersFactory.php index d100a327c..d7dcfec5c 100644 --- a/src/UrlParametersFactory.php +++ b/src/UrlParametersFactory.php @@ -33,7 +33,7 @@ final class UrlParametersFactory * - Query parameters as key-value pairs */ /** - * @return array{0: array, 1: array} + * @return array{0: array, 1: array} */ public static function create( ?PageToken $pageToken, diff --git a/tests/Column/Base/GlobalContextTest.php b/tests/Column/Base/GlobalContextTest.php index bbdf46b80..73dc983a2 100644 --- a/tests/Column/Base/GlobalContextTest.php +++ b/tests/Column/Base/GlobalContextTest.php @@ -58,7 +58,7 @@ public function testTranslateWithString(): void public function testTranslateWithStringable(): void { - $stringable = new class implements Stringable { + $stringable = new class () implements Stringable { public function __toString(): string { return 'test.stringable'; diff --git a/tests/Column/DataColumnRendererTest.php b/tests/Column/DataColumnRendererTest.php index 7a93d8a82..9a59995d5 100644 --- a/tests/Column/DataColumnRendererTest.php +++ b/tests/Column/DataColumnRendererTest.php @@ -236,7 +236,7 @@ public function testRenderFilterWithDropdown(): void ); $cell = new Cell(); - $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return 'active'; @@ -271,7 +271,7 @@ public function testMakeFilterWithCustomFactory(): void filterFactory: \Yiisoft\Yii\DataView\Filter\Factory\LikeFilterFactory::class ); - $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -304,7 +304,7 @@ public function testMakeFilterWithValidation(): void filterValidation: [new Number()] ); - $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -338,7 +338,7 @@ public function testMakeFilterWithEmptyValue(): void filterEmpty: true ); - $urlParameterProvider = new class implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { diff --git a/tests/UrlParametersFactoryTest.php b/tests/UrlParametersFactoryTest.php index 90022f22e..2d06b47ec 100644 --- a/tests/UrlParametersFactoryTest.php +++ b/tests/UrlParametersFactoryTest.php @@ -324,4 +324,3 @@ public function testCreateWithNullPageToken(): void ], $queryParameters); } } - From a57bed6e54b0b019af30c33b09fc99a50a24b99a Mon Sep 17 00:00:00 2001 From: samdark <47294+samdark@users.noreply.github.com> Date: Thu, 6 Mar 2025 00:10:52 +0000 Subject: [PATCH 03/20] Apply Rector changes (CI) --- tests/Column/Base/RendererContainerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Column/Base/RendererContainerTest.php b/tests/Column/Base/RendererContainerTest.php index cecb00059..e0b2d31d2 100644 --- a/tests/Column/Base/RendererContainerTest.php +++ b/tests/Column/Base/RendererContainerTest.php @@ -77,8 +77,8 @@ public function testAddConfigsMergesExistingConfig(): void final class TestRenderer implements ColumnRendererInterface { public function __construct( - private string $value = 'default', - private string $option = 'default', + private readonly string $value = 'default', + private readonly string $option = 'default', ) { } From 5cb328b10ab591552aedf4bf17718e31f17614d2 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 6 Mar 2025 03:11:35 +0300 Subject: [PATCH 04/20] Remove unnecessary change --- src/UrlParametersFactory.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/UrlParametersFactory.php b/src/UrlParametersFactory.php index d7dcfec5c..063f5ab73 100644 --- a/src/UrlParametersFactory.php +++ b/src/UrlParametersFactory.php @@ -32,9 +32,6 @@ final class UrlParametersFactory * - Path arguments as key-value pairs * - Query parameters as key-value pairs */ - /** - * @return array{0: array, 1: array} - */ public static function create( ?PageToken $pageToken, int|string|null $pageSize, From 948a90c54a05ee73de82bf5ee8627b0d87e7b871 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 6 Mar 2025 08:59:54 +0300 Subject: [PATCH 05/20] Fix --- tests/Column/Base/GlobalContextTest.php | 36 ++-- tests/Column/CheckboxColumnRendererTest.php | 172 ++++++++++---------- 2 files changed, 103 insertions(+), 105 deletions(-) diff --git a/tests/Column/Base/GlobalContextTest.php b/tests/Column/Base/GlobalContextTest.php index 73dc983a2..76ead0050 100644 --- a/tests/Column/Base/GlobalContextTest.php +++ b/tests/Column/Base/GlobalContextTest.php @@ -6,19 +6,27 @@ use PHPUnit\Framework\TestCase; use Stringable; -use Yiisoft\Data\Reader\ReadableDataInterface; +use Yiisoft\Data\Reader\Iterable\IterableDataReader; use Yiisoft\Translator\TranslatorInterface; use Yiisoft\Yii\DataView\Column\Base\GlobalContext; +use Yiisoft\Yii\DataView\Tests\Support\Mock; +use Yiisoft\Yii\DataView\Tests\Support\TestTrait; /** * @covers \Yiisoft\Yii\DataView\Column\Base\GlobalContext */ final class GlobalContextTest extends TestCase { + use TestTrait; + + private array $data = [ + ['id' => 1, 'name' => 'John'], + ['id' => 2, 'name' => 'Mary'], + ]; public function testConstructor(): void { - $dataReader = $this->createMock(ReadableDataInterface::class); - $translator = $this->createMock(TranslatorInterface::class); + $dataReader = new IterableDataReader($this->data); + $translator = Mock::translator('en'); $pathArguments = ['id' => 123]; $queryParameters = ['sort' => 'name']; $translationCategory = 'app'; @@ -38,22 +46,17 @@ public function testConstructor(): void public function testTranslateWithString(): void { - $translator = $this->createMock(TranslatorInterface::class); - $translator - ->expects($this->once()) - ->method('translate') - ->with('test.message', [], 'app') - ->willReturn('Test Message'); + $translator = Mock::translator('en'); $context = new GlobalContext( - $this->createMock(ReadableDataInterface::class), + new IterableDataReader($this->data), [], [], $translator, 'app' ); - $this->assertSame('Test Message', $context->translate('test.message')); + $this->assertSame('test.message', $context->translate('test.message')); } public function testTranslateWithStringable(): void @@ -65,21 +68,16 @@ public function __toString(): string } }; - $translator = $this->createMock(TranslatorInterface::class); - $translator - ->expects($this->once()) - ->method('translate') - ->with('test.stringable', [], 'app') - ->willReturn('Test Stringable'); + $translator = Mock::translator('en'); $context = new GlobalContext( - $this->createMock(ReadableDataInterface::class), + new IterableDataReader($this->data), [], [], $translator, 'app' ); - $this->assertSame('Test Stringable', $context->translate($stringable)); + $this->assertSame('test.stringable', $context->translate($stringable)); } } diff --git a/tests/Column/CheckboxColumnRendererTest.php b/tests/Column/CheckboxColumnRendererTest.php index 85ba7c6bb..2eec6e977 100644 --- a/tests/Column/CheckboxColumnRendererTest.php +++ b/tests/Column/CheckboxColumnRendererTest.php @@ -33,11 +33,11 @@ protected function setUp(): void ['id' => 2, 'name' => 'Mary'], ]); $this->globalContext = new GlobalContext( - $this->dataReader, - [], - [], - Mock::translator('en'), - 'test' + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: Mock::translator('en'), + translationCategory: 'test' ); } @@ -53,28 +53,28 @@ public function testRenderHeaderWithoutHeaderAndSingleSelection(): void $column = new CheckboxColumn(multiple: false); $sort = Sort::any(); $context = new HeaderContext( - $sort, - $sort, - ['test' => 'test'], - 'sortable', - '', - '', - 'asc', - '', - '', - 'desc', - '', - '', - [], - 'asc-link', - 'desc-link', - null, - 10, - false, - new UrlConfig(), - null, - Mock::translator('en'), - 'test' + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: Mock::translator('en'), + translationCategory: 'test' ); $result = $this->renderer->renderHeader($column, $this->cell, $context); $this->assertNull($result); @@ -85,28 +85,28 @@ public function testRenderHeaderWithoutHeaderAndMultipleSelection(): void $column = new CheckboxColumn(multiple: true); $sort = Sort::any(); $context = new HeaderContext( - $sort, - $sort, - ['test' => 'test'], - 'sortable', - '', - '', - 'asc', - '', - '', - 'desc', - '', - '', - [], - 'asc-link', - 'desc-link', - null, - 10, - false, - new UrlConfig(), - null, - Mock::translator('en'), - 'test' + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: Mock::translator('en'), + translationCategory: 'test' ); $result = $this->renderer->renderHeader($column, $this->cell, $context); $this->assertNotNull($result); @@ -121,28 +121,28 @@ public function testRenderHeaderWithCustomHeader(): void ); $sort = Sort::any(); $context = new HeaderContext( - $sort, - $sort, - ['test' => 'test'], - 'sortable', - '', - '', - 'asc', - '', - '', - 'desc', - '', - '', - [], - 'asc-link', - 'desc-link', - null, - 10, - false, - new UrlConfig(), - null, - Mock::translator('en'), - 'test' + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: Mock::translator('en'), + translationCategory: 'test' ); $result = $this->renderer->renderHeader($column, $this->cell, $context); $this->assertNotNull($result); @@ -154,11 +154,11 @@ public function testRenderBodyWithDefaultNameAndValue(): void { $column = new CheckboxColumn(); $context = new DataContext( - $this->dataReader, - $column, - ['id' => 1, 'name' => 'John'], - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: ['id' => 1, 'name' => 'John'], + key: 1, + index: 0 ); $result = $this->renderer->renderBody($column, $this->cell, $context); $content = (string) $result->getContent()[0]; @@ -177,11 +177,11 @@ public function testRenderBodyWithCustomNameAndValue(): void ] ); $context = new DataContext( - $this->dataReader, - $column, - ['id' => 1, 'name' => 'John'], - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: ['id' => 1, 'name' => 'John'], + key: 1, + index: 0 ); $result = $this->renderer->renderBody($column, $this->cell, $context); $content = (string) $result->getContent()[0]; @@ -196,11 +196,11 @@ public function testRenderBodyWithCustomContent(): void content: static fn(Checkbox $input, DataContext $context): string => "
{$input->render()}
" ); $context = new DataContext( - $this->dataReader, - $column, - ['id' => 1, 'name' => 'John'], - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: ['id' => 1, 'name' => 'John'], + key: 1, + index: 0 ); $result = $this->renderer->renderBody($column, $this->cell, $context); $content = (string) $result->getContent()[0]; From 370e6c82b2a89e9eafc4bb7e5d00c0fa4cb6d57f Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 6 Mar 2025 06:03:40 +0000 Subject: [PATCH 06/20] Apply fixes from StyleCI --- tests/Column/Base/GlobalContextTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Column/Base/GlobalContextTest.php b/tests/Column/Base/GlobalContextTest.php index 76ead0050..36a82f6af 100644 --- a/tests/Column/Base/GlobalContextTest.php +++ b/tests/Column/Base/GlobalContextTest.php @@ -7,7 +7,6 @@ use PHPUnit\Framework\TestCase; use Stringable; use Yiisoft\Data\Reader\Iterable\IterableDataReader; -use Yiisoft\Translator\TranslatorInterface; use Yiisoft\Yii\DataView\Column\Base\GlobalContext; use Yiisoft\Yii\DataView\Tests\Support\Mock; use Yiisoft\Yii\DataView\Tests\Support\TestTrait; @@ -23,6 +22,7 @@ final class GlobalContextTest extends TestCase ['id' => 1, 'name' => 'John'], ['id' => 2, 'name' => 'Mary'], ]; + public function testConstructor(): void { $dataReader = new IterableDataReader($this->data); From 4b69c63f1c4db691db2c5af2ded4c038747e30af Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 6 Mar 2025 09:06:20 +0300 Subject: [PATCH 07/20] Cleanup --- tests/Column/Base/RendererContainerTest.php | 42 +-------- tests/Column/DataColumnRendererTest.php | 94 ++++++++++----------- tests/Support/TestRenderer.php | 54 ++++++++++++ 3 files changed, 102 insertions(+), 88 deletions(-) create mode 100644 tests/Support/TestRenderer.php diff --git a/tests/Column/Base/RendererContainerTest.php b/tests/Column/Base/RendererContainerTest.php index e0b2d31d2..23d4cc337 100644 --- a/tests/Column/Base/RendererContainerTest.php +++ b/tests/Column/Base/RendererContainerTest.php @@ -13,6 +13,7 @@ use Yiisoft\Yii\DataView\Column\Base\RendererContainer; use Yiisoft\Yii\DataView\Column\ColumnInterface; use Yiisoft\Yii\DataView\Column\ColumnRendererInterface; +use Yiisoft\Yii\DataView\Tests\Support\TestRenderer; /** * @covers \Yiisoft\Yii\DataView\Column\Base\RendererContainer @@ -71,44 +72,3 @@ public function testAddConfigsMergesExistingConfig(): void } } -/** - * Test renderer implementation. - */ -final class TestRenderer implements ColumnRendererInterface -{ - public function __construct( - private readonly string $value = 'default', - private readonly string $option = 'default', - ) { - } - - public function getValue(): string - { - return $this->value; - } - - public function getOption(): string - { - return $this->option; - } - - public function renderColumn(ColumnInterface $column, Cell $cell, GlobalContext $context): Cell - { - return $cell; - } - - public function renderHeader(ColumnInterface $column, Cell $cell, HeaderContext $context): ?Cell - { - return $cell; - } - - public function renderBody(ColumnInterface $column, Cell $cell, DataContext $context): Cell - { - return $cell; - } - - public function renderFooter(ColumnInterface $column, Cell $cell, GlobalContext $context): Cell - { - return $cell; - } -} diff --git a/tests/Column/DataColumnRendererTest.php b/tests/Column/DataColumnRendererTest.php index 9a59995d5..f3a2765e8 100644 --- a/tests/Column/DataColumnRendererTest.php +++ b/tests/Column/DataColumnRendererTest.php @@ -52,11 +52,11 @@ public function testRenderColumn(): void $translator = Mock::translator('en'); $context = new GlobalContext( - $this->dataReader, - [], - [], - $translator, - 'test' + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' ); $renderer = new DataColumnRenderer( @@ -76,28 +76,28 @@ public function testRenderHeader(): void $sort = Sort::any(); $context = new HeaderContext( - $sort, - $sort, - ['test' => 'test'], - 'sortable', - '', - '', - 'asc', - '', - '', - 'desc', - '', - '', - [], - 'asc-link', - 'desc-link', - null, - 10, - false, - new UrlConfig(), - null, - $translator, - 'test' + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' ); $renderer = new DataColumnRenderer( @@ -117,11 +117,11 @@ public function testRenderBody(): void $data = ['id' => 1, 'name' => 'John Doe', 'age' => 20]; $context = new DataContext( - $this->dataReader, - $column, - $data, - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 ); $renderer = new DataColumnRenderer( @@ -158,11 +158,11 @@ public function testRenderBodyWithCustomContentCallback(): void $data = ['id' => 1, 'name' => 'John Doe', 'age' => 20]; $context = new DataContext( - $this->dataReader, - $column, - $data, - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 ); $renderer = new DataColumnRenderer( @@ -184,11 +184,11 @@ public function testRenderBodyWithDateTime(): void $data = ['id' => 1, 'created_at' => $date]; $context = new DataContext( - $this->dataReader, - $column, - $data, - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 ); $renderer = new DataColumnRenderer( @@ -212,11 +212,11 @@ public function testRenderBodyWithDynamicAttributes(): void $data = ['id' => 2, 'name' => 'Mary', 'age' => 21]; $context = new DataContext( - $this->dataReader, - $column, - $data, - 1, - 0 + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 ); $renderer = new DataColumnRenderer( diff --git a/tests/Support/TestRenderer.php b/tests/Support/TestRenderer.php new file mode 100644 index 000000000..e0ed18d68 --- /dev/null +++ b/tests/Support/TestRenderer.php @@ -0,0 +1,54 @@ +value; + } + + public function getOption(): string + { + return $this->option; + } + + public function renderColumn(ColumnInterface $column, Cell $cell, GlobalContext $context): Cell + { + return $cell; + } + + public function renderHeader(ColumnInterface $column, Cell $cell, HeaderContext $context): ?Cell + { + return $cell; + } + + public function renderBody(ColumnInterface $column, Cell $cell, DataContext $context): Cell + { + return $cell; + } + + public function renderFooter(ColumnInterface $column, Cell $cell, GlobalContext $context): Cell + { + return $cell; + } +} From 1f89ae48fd1ecf53fa0d3a35b53fa5e736945606 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Thu, 6 Mar 2025 06:12:24 +0000 Subject: [PATCH 08/20] Apply fixes from StyleCI --- tests/Column/Base/RendererContainerTest.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/Column/Base/RendererContainerTest.php b/tests/Column/Base/RendererContainerTest.php index 23d4cc337..7f4408ae3 100644 --- a/tests/Column/Base/RendererContainerTest.php +++ b/tests/Column/Base/RendererContainerTest.php @@ -6,13 +6,7 @@ use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; -use Yiisoft\Yii\DataView\Column\Base\Cell; -use Yiisoft\Yii\DataView\Column\Base\DataContext; -use Yiisoft\Yii\DataView\Column\Base\GlobalContext; -use Yiisoft\Yii\DataView\Column\Base\HeaderContext; use Yiisoft\Yii\DataView\Column\Base\RendererContainer; -use Yiisoft\Yii\DataView\Column\ColumnInterface; -use Yiisoft\Yii\DataView\Column\ColumnRendererInterface; use Yiisoft\Yii\DataView\Tests\Support\TestRenderer; /** @@ -71,4 +65,3 @@ public function testAddConfigsMergesExistingConfig(): void $this->assertSame('second', $instance->getOption()); } } - From bcca665897c4067162e30bfe0c06f36db163de9b Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 6 Mar 2025 10:11:53 +0300 Subject: [PATCH 09/20] Cleanup diff --git c/tests/Column/Base/RendererContainerTest.php i/tests/Column/Base/RendererContainerTest.php index 7f4408a..bb06371 100644 --- c/tests/Column/Base/RendererContainerTest.php +++ i/tests/Column/Base/RendererContainerTest.php @@ -6,6 +6,7 @@ namespace Yiisoft\Yii\DataView\Tests\Column\Base; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use RuntimeException; use Yiisoft\Yii\DataView\Column\Base\RendererContainer; use Yiisoft\Yii\DataView\Tests\Support\TestRenderer; @@ -15,20 +16,19 @@ use Yiisoft\Yii\DataView\Tests\Support\TestRenderer; final class RendererContainerTest extends TestCase { private TestRenderer $renderer; - private ContainerInterface $container; private RendererContainer $rendererContainer; protected function setUp(): void { $this->renderer = new TestRenderer(); - $this->container = $this->createMock(ContainerInterface::class); - $this->container + $container = $this->createMock(ContainerInterface::class); + $container ->method('get') ->willReturnCallback(fn(string $class) => match ($class) { TestRenderer::class => $this->renderer, - default => throw new \RuntimeException("Unexpected class: $class"), + default => throw new RuntimeException("Unexpected class: $class"), }); - $this->rendererContainer = new RendererContainer($this->container); + $this->rendererContainer = new RendererContainer($container); } public function testGetCreatesNewInstance(): void @@ -50,6 +50,7 @@ final class RendererContainerTest extends TestCase TestRenderer::class => ['value' => 'custom'], ]); + /** @var TestRenderer $instance */ $instance = $container->get(TestRenderer::class); $this->assertSame('custom', $instance->getValue()); } @@ -60,8 +61,10 @@ final class RendererContainerTest extends TestCase ->addConfigs([TestRenderer::class => ['value' => 'first']]) ->addConfigs([TestRenderer::class => ['option' => 'second']]); + /** @var TestRenderer $instance */ $instance = $container->get(TestRenderer::class); $this->assertSame('first', $instance->getValue()); $this->assertSame('second', $instance->getOption()); } } + diff --git c/tests/Column/DataColumnRendererTest.php i/tests/Column/DataColumnRendererTest.php index f3a2765..45d54d9 100644 --- c/tests/Column/DataColumnRendererTest.php +++ i/tests/Column/DataColumnRendererTest.php @@ -4,12 +4,14 @@ declare(strict_types=1); namespace Yiisoft\Yii\DataView\Tests\Column; +use DateTime; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Yiisoft\Data\Reader\Iterable\IterableDataReader; use Yiisoft\Data\Reader\Sort; use Yiisoft\Di\Container; use Yiisoft\Di\ContainerConfig; +use Yiisoft\Validator\Result; use Yiisoft\Validator\Validator; use Yiisoft\Yii\DataView\Column\Base\Cell; use Yiisoft\Yii\DataView\Column\Base\DataContext; @@ -19,10 +21,12 @@ use Yiisoft\Yii\DataView\Column\Base\FilterContext; use Yiisoft\Yii\DataView\Column\Base\MakeFilterContext; use Yiisoft\Yii\DataView\Column\DataColumn; use Yiisoft\Yii\DataView\Column\DataColumnRenderer; +use Yiisoft\Yii\DataView\Filter\Factory\LikeFilterFactory; use Yiisoft\Yii\DataView\Tests\Support\Mock; use Yiisoft\Yii\DataView\Tests\Support\TestTrait; use Yiisoft\Yii\DataView\UrlConfig; use Yiisoft\Validator\Rule\Number; +use Yiisoft\Yii\DataView\UrlParameterProviderInterface; final class DataColumnRendererTest extends TestCase { @@ -178,7 +182,7 @@ final class DataColumnRendererTest extends TestCase public function testRenderBodyWithDateTime(): void { - $date = new \DateTime('2025-03-06 02:00:22'); + $date = new DateTime('2025-03-06 02:00:22'); $column = new DataColumn('created_at', dateTimeFormat: 'Y-m-d'); $cell = new Cell(); $data = ['id' => 1, 'created_at' => $date]; @@ -236,7 +240,7 @@ final class DataColumnRendererTest extends TestCase ); $cell = new Cell(); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return 'active'; @@ -245,7 +249,7 @@ final class DataColumnRendererTest extends TestCase $context = new FilterContext( 'filter-form', - new \Yiisoft\Validator\Result(), + new Result(), 'invalid', ['class' => 'error-container'], $urlParameterProvider @@ -268,10 +272,10 @@ final class DataColumnRendererTest extends TestCase { $column = new DataColumn( 'name', - filterFactory: \Yiisoft\Yii\DataView\Filter\Factory\LikeFilterFactory::class + filterFactory: LikeFilterFactory::class ); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -284,7 +288,7 @@ final class DataColumnRendererTest extends TestCase }; $context = new MakeFilterContext( - new \Yiisoft\Validator\Result(), + new Result(), $urlParameterProvider ); @@ -304,7 +308,7 @@ final class DataColumnRendererTest extends TestCase filterValidation: [new Number()] ); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -317,7 +321,7 @@ final class DataColumnRendererTest extends TestCase }; $context = new MakeFilterContext( - new \Yiisoft\Validator\Result(), + new Result(), $urlParameterProvider ); @@ -338,7 +342,7 @@ final class DataColumnRendererTest extends TestCase filterEmpty: true ); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -351,7 +355,7 @@ final class DataColumnRendererTest extends TestCase }; $context = new MakeFilterContext( - new \Yiisoft\Validator\Result(), + new Result(), $urlParameterProvider ); --- tests/Column/Base/RendererContainerTest.php | 13 ++++++----- tests/Column/DataColumnRendererTest.php | 24 ++++++++++++--------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/tests/Column/Base/RendererContainerTest.php b/tests/Column/Base/RendererContainerTest.php index 7f4408ae3..bb0637129 100644 --- a/tests/Column/Base/RendererContainerTest.php +++ b/tests/Column/Base/RendererContainerTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use RuntimeException; use Yiisoft\Yii\DataView\Column\Base\RendererContainer; use Yiisoft\Yii\DataView\Tests\Support\TestRenderer; @@ -15,20 +16,19 @@ final class RendererContainerTest extends TestCase { private TestRenderer $renderer; - private ContainerInterface $container; private RendererContainer $rendererContainer; protected function setUp(): void { $this->renderer = new TestRenderer(); - $this->container = $this->createMock(ContainerInterface::class); - $this->container + $container = $this->createMock(ContainerInterface::class); + $container ->method('get') ->willReturnCallback(fn(string $class) => match ($class) { TestRenderer::class => $this->renderer, - default => throw new \RuntimeException("Unexpected class: $class"), + default => throw new RuntimeException("Unexpected class: $class"), }); - $this->rendererContainer = new RendererContainer($this->container); + $this->rendererContainer = new RendererContainer($container); } public function testGetCreatesNewInstance(): void @@ -50,6 +50,7 @@ public function testAddConfigsCreatesNewInstanceWithConfig(): void TestRenderer::class => ['value' => 'custom'], ]); + /** @var TestRenderer $instance */ $instance = $container->get(TestRenderer::class); $this->assertSame('custom', $instance->getValue()); } @@ -60,8 +61,10 @@ public function testAddConfigsMergesExistingConfig(): void ->addConfigs([TestRenderer::class => ['value' => 'first']]) ->addConfigs([TestRenderer::class => ['option' => 'second']]); + /** @var TestRenderer $instance */ $instance = $container->get(TestRenderer::class); $this->assertSame('first', $instance->getValue()); $this->assertSame('second', $instance->getOption()); } } + diff --git a/tests/Column/DataColumnRendererTest.php b/tests/Column/DataColumnRendererTest.php index f3a2765e8..45d54d9c2 100644 --- a/tests/Column/DataColumnRendererTest.php +++ b/tests/Column/DataColumnRendererTest.php @@ -4,12 +4,14 @@ namespace Yiisoft\Yii\DataView\Tests\Column; +use DateTime; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Yiisoft\Data\Reader\Iterable\IterableDataReader; use Yiisoft\Data\Reader\Sort; use Yiisoft\Di\Container; use Yiisoft\Di\ContainerConfig; +use Yiisoft\Validator\Result; use Yiisoft\Validator\Validator; use Yiisoft\Yii\DataView\Column\Base\Cell; use Yiisoft\Yii\DataView\Column\Base\DataContext; @@ -19,10 +21,12 @@ use Yiisoft\Yii\DataView\Column\Base\MakeFilterContext; use Yiisoft\Yii\DataView\Column\DataColumn; use Yiisoft\Yii\DataView\Column\DataColumnRenderer; +use Yiisoft\Yii\DataView\Filter\Factory\LikeFilterFactory; use Yiisoft\Yii\DataView\Tests\Support\Mock; use Yiisoft\Yii\DataView\Tests\Support\TestTrait; use Yiisoft\Yii\DataView\UrlConfig; use Yiisoft\Validator\Rule\Number; +use Yiisoft\Yii\DataView\UrlParameterProviderInterface; final class DataColumnRendererTest extends TestCase { @@ -178,7 +182,7 @@ public function testRenderBodyWithCustomContentCallback(): void public function testRenderBodyWithDateTime(): void { - $date = new \DateTime('2025-03-06 02:00:22'); + $date = new DateTime('2025-03-06 02:00:22'); $column = new DataColumn('created_at', dateTimeFormat: 'Y-m-d'); $cell = new Cell(); $data = ['id' => 1, 'created_at' => $date]; @@ -236,7 +240,7 @@ public function testRenderFilterWithDropdown(): void ); $cell = new Cell(); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return 'active'; @@ -245,7 +249,7 @@ public function get(string $name, int $type): ?string $context = new FilterContext( 'filter-form', - new \Yiisoft\Validator\Result(), + new Result(), 'invalid', ['class' => 'error-container'], $urlParameterProvider @@ -268,10 +272,10 @@ public function testMakeFilterWithCustomFactory(): void { $column = new DataColumn( 'name', - filterFactory: \Yiisoft\Yii\DataView\Filter\Factory\LikeFilterFactory::class + filterFactory: LikeFilterFactory::class ); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -284,7 +288,7 @@ public function get(string $name, int $type): ?string }; $context = new MakeFilterContext( - new \Yiisoft\Validator\Result(), + new Result(), $urlParameterProvider ); @@ -304,7 +308,7 @@ public function testMakeFilterWithValidation(): void filterValidation: [new Number()] ); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -317,7 +321,7 @@ public function get(string $name, int $type): ?string }; $context = new MakeFilterContext( - new \Yiisoft\Validator\Result(), + new Result(), $urlParameterProvider ); @@ -338,7 +342,7 @@ public function testMakeFilterWithEmptyValue(): void filterEmpty: true ); - $urlParameterProvider = new class () implements \Yiisoft\Yii\DataView\UrlParameterProviderInterface { + $urlParameterProvider = new class () implements UrlParameterProviderInterface { public function get(string $name, int $type): ?string { return match ($name) { @@ -351,7 +355,7 @@ public function get(string $name, int $type): ?string }; $context = new MakeFilterContext( - new \Yiisoft\Validator\Result(), + new Result(), $urlParameterProvider ); From ff5f489b6ad2766390bf1a736b68026ef86c5235 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 11:24:54 +0300 Subject: [PATCH 10/20] More tests --- tests/Column/RadioColumnRendererTest.php | 255 +++++++++++ tests/Pagination/KeysetPaginationTest.php | 514 ++++++++++++++++++++++ 2 files changed, 769 insertions(+) create mode 100644 tests/Column/RadioColumnRendererTest.php diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php new file mode 100644 index 000000000..b7068696c --- /dev/null +++ b/tests/Column/RadioColumnRendererTest.php @@ -0,0 +1,255 @@ +dataReader = new IterableDataReader([ + ['id' => 1, 'name' => 'John', 'age' => 20], + ['id' => 2, 'name' => 'Mary', 'age' => 21], + ]); + } + + public function testRenderColumn(): void + { + $column = new RadioColumn( + columnAttributes: ['class' => 'test-column'] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderColumn($column, $cell, $context); + + $this->assertSame(['class' => 'test-column'], $result->getAttributes()); + } + + public function testRenderHeaderWithNullHeader(): void + { + $column = new RadioColumn(); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new HeaderContext( + originalSort: null, + sort: null, + orderProperties: [], + sortableHeaderClass: '', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: '', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: '', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: '', + sortableLinkDescClass: '', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderHeader($column, $cell, $context); + + $this->assertNull($result); + } + + public function testRenderHeaderWithCustomHeader(): void + { + $column = new RadioColumn( + header: 'Select', + headerAttributes: ['class' => 'header-class'] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new HeaderContext( + originalSort: null, + sort: null, + orderProperties: [], + sortableHeaderClass: '', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: '', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: '', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: '', + sortableLinkDescClass: '', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderHeader($column, $cell, $context); + + $this->assertNotNull($result); + $this->assertSame('Select', $result->getContent()[0]); + $this->assertArrayHasKey('class', $result->getAttributes()); + $this->assertSame('header-class', $result->getAttributes()['class']); + } + + public function testRenderBodyWithDefaultSettings(): void + { + $column = new RadioColumn(); + $cell = new Cell(); + $data = ['id' => 1, 'name' => 'John', 'age' => 20]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('radio-selection', (string)$content[0]); + $this->assertStringContainsString('value="1"', (string)$content[0]); + } + + public function testRenderBodyWithCustomInputAttributes(): void + { + $column = new RadioColumn( + inputAttributes: [ + 'name' => 'custom-radio', + 'value' => 'custom-value', + 'class' => 'radio-class', + ] + ); + $cell = new Cell(); + $data = ['id' => 1, 'name' => 'John', 'age' => 20]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="custom-radio"', (string)$content[0]); + $this->assertStringContainsString('value="custom-value"', (string)$content[0]); + $this->assertStringContainsString('class="radio-class"', (string)$content[0]); + } + + public function testRenderBodyWithCustomContent(): void + { + $column = new RadioColumn( + content: static fn($input, $context) => Html::div($input)->class('custom-wrapper') + ); + $cell = new Cell(); + $data = ['id' => 1, 'name' => 'John', 'age' => 20]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('
', (string)$content[0]); + $this->assertStringContainsString('radio-selection', (string)$content[0]); + } + + public function testRenderFooterWithContent(): void + { + $column = new RadioColumn( + footer: 'Footer content' + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderFooter($column, $cell, $context); + + $this->assertSame('Footer content', $result->getContent()[0]); + } + + public function testRenderFooterWithoutContent(): void + { + $column = new RadioColumn(); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderFooter($column, $cell, $context); + + $this->assertEmpty($result->getContent()); + } +} diff --git a/tests/Pagination/KeysetPaginationTest.php b/tests/Pagination/KeysetPaginationTest.php index 86a15043d..10673a6d9 100644 --- a/tests/Pagination/KeysetPaginationTest.php +++ b/tests/Pagination/KeysetPaginationTest.php @@ -4,17 +4,22 @@ namespace Yiisoft\Yii\DataView\Tests\Pagination; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use Yiisoft\Data\Paginator\KeysetPaginator; use Yiisoft\Data\Paginator\PageToken; +use Yiisoft\Data\Paginator\PaginatorInterface; use Yiisoft\Definitions\Exception\CircularReferenceException; use Yiisoft\Definitions\Exception\InvalidConfigException; use Yiisoft\Definitions\Exception\NotInstantiableException; use Yiisoft\Factory\NotFoundException; use Yiisoft\Yii\DataView\Column\DataColumn; use Yiisoft\Yii\DataView\Pagination\PaginatorNotSetException; +use Yiisoft\Yii\DataView\Pagination\PaginatorNotSupportedException; use Yiisoft\Yii\DataView\GridView; use Yiisoft\Yii\DataView\Pagination\KeysetPagination; use Yiisoft\Yii\DataView\Tests\Support\Assert; +use Yiisoft\Yii\DataView\Tests\Support\Mock; use Yiisoft\Yii\DataView\Tests\Support\TestTrait; final class KeysetPaginationTest extends TestCase @@ -365,4 +370,513 @@ public function testNotSetPaginator(): void $this->expectExceptionMessage('Failed to create widget because "paginator" is not set.'); Assert::invokeMethod($pagination, 'getPaginator'); } + + public function testPaginatorNotSupportedException(): void + { + $this->expectException(PaginatorNotSupportedException::class); + // Use a partial message match since the actual class name of the mock will vary + $this->expectExceptionMessageMatches('/Paginator ".*" is not supported\./'); + + /** @var PaginatorInterface $nonKeysetPaginator */ + $nonKeysetPaginator = $this->createMock(PaginatorInterface::class); + KeysetPagination::widget()->withPaginator($nonKeysetPaginator); + } + + public function testContainerTagWithEmptyString(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Tag name cannot be empty.'); + + KeysetPagination::widget()->containerTag(''); + } + + public function testListTagWithEmptyString(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Tag name cannot be empty.'); + + KeysetPagination::widget()->listTag(''); + } + + public function testItemTagWithEmptyString(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Tag name cannot be empty.'); + + KeysetPagination::widget()->itemTag(''); + } + + public function testCustomContainerAttributes(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+ +
+ HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->containerAttributes(['class' => 'custom-nav', 'id' => 'pagination-nav']) + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } + + public function testCustomListTagAndAttributes(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+ + + HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->listTag('ul') + ->listAttributes(['class' => 'pagination']) + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } + + public function testCustomItemTagAndAttributes(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+ + + HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->itemTag('li') + ->itemAttributes(['class' => 'page-item']) + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } + + public function testDisabledItemAndLinkClasses(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+ + + HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->itemTag('li') + ->itemAttributes(['class' => 'page-item']) + ->disabledItemClass('disabled') + ->disabledLinkClass('disabled') + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } + + public function testCustomLinkAttributes(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+ + + HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->linkAttributes(['class' => 'page-link']) + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } + + public function testCustomContainerTag(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+
+ + +
+ + HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->containerTag('div') + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } + + public function testNoContainerTag(): void + { + $keysetPaginator = $this->createKeysetPaginator($this->data, 5); + + Assert::equalsWithoutLE( + << + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameDescription
1name1description1
2name2description2
3name3description3
4name4description4
5name5description5
+ + + + HTML, + GridView::widget() + ->columns( + new DataColumn('id'), + new DataColumn('name'), + new DataColumn('description'), + ) + ->id('w1-grid') + ->dataReader($keysetPaginator) + ->paginationWidget( + KeysetPagination::widget() + ->withPaginator($keysetPaginator) + ->containerTag(null) + ) + ->layout('{items}' . PHP_EOL . '{pager}') + ->render(), + ); + } } From 30ced90ba6908fc4ea2c2625c0f9be931fc4018d Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 10 Mar 2025 08:25:21 +0000 Subject: [PATCH 11/20] Apply fixes from StyleCI --- tests/Column/Base/RendererContainerTest.php | 1 - tests/Column/RadioColumnRendererTest.php | 1 - tests/Pagination/KeysetPaginationTest.php | 9 ++++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/Column/Base/RendererContainerTest.php b/tests/Column/Base/RendererContainerTest.php index bb0637129..fa4116148 100644 --- a/tests/Column/Base/RendererContainerTest.php +++ b/tests/Column/Base/RendererContainerTest.php @@ -67,4 +67,3 @@ public function testAddConfigsMergesExistingConfig(): void $this->assertSame('second', $instance->getOption()); } } - diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index b7068696c..ba243068a 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -4,7 +4,6 @@ namespace Yiisoft\Yii\DataView\Tests\Column; -use Closure; use PHPUnit\Framework\TestCase; use Yiisoft\Data\Reader\Iterable\IterableDataReader; use Yiisoft\Html\Html; diff --git a/tests/Pagination/KeysetPaginationTest.php b/tests/Pagination/KeysetPaginationTest.php index 10673a6d9..bd60f97da 100644 --- a/tests/Pagination/KeysetPaginationTest.php +++ b/tests/Pagination/KeysetPaginationTest.php @@ -6,7 +6,6 @@ use InvalidArgumentException; use PHPUnit\Framework\TestCase; -use Yiisoft\Data\Paginator\KeysetPaginator; use Yiisoft\Data\Paginator\PageToken; use Yiisoft\Data\Paginator\PaginatorInterface; use Yiisoft\Definitions\Exception\CircularReferenceException; @@ -376,7 +375,7 @@ public function testPaginatorNotSupportedException(): void $this->expectException(PaginatorNotSupportedException::class); // Use a partial message match since the actual class name of the mock will vary $this->expectExceptionMessageMatches('/Paginator ".*" is not supported\./'); - + /** @var PaginatorInterface $nonKeysetPaginator */ $nonKeysetPaginator = $this->createMock(PaginatorInterface::class); KeysetPagination::widget()->withPaginator($nonKeysetPaginator); @@ -386,7 +385,7 @@ public function testContainerTagWithEmptyString(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Tag name cannot be empty.'); - + KeysetPagination::widget()->containerTag(''); } @@ -394,7 +393,7 @@ public function testListTagWithEmptyString(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Tag name cannot be empty.'); - + KeysetPagination::widget()->listTag(''); } @@ -402,7 +401,7 @@ public function testItemTagWithEmptyString(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Tag name cannot be empty.'); - + KeysetPagination::widget()->itemTag(''); } From 517697322dd8a0125340fbe90aafbf2ac5b56ab8 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 14:53:17 +0300 Subject: [PATCH 12/20] More --- tests/Column/DataColumnRendererTest.php | 443 ++++++++++++++++++++++++ 1 file changed, 443 insertions(+) diff --git a/tests/Column/DataColumnRendererTest.php b/tests/Column/DataColumnRendererTest.php index 45d54d9c2..d32ff7aa4 100644 --- a/tests/Column/DataColumnRendererTest.php +++ b/tests/Column/DataColumnRendererTest.php @@ -367,4 +367,447 @@ public function get(string $name, int $type): ?string $result = $renderer->makeFilter($column, $context); $this->assertNull($result); } + + public function testRenderHeaderWithoutProperty(): void + { + $column = new DataColumn(header: 'Custom Header'); + $cell = new Cell(); + $translator = Mock::translator('en'); + $sort = Sort::any(); + + $context = new HeaderContext( + originalSort: $sort, + sort: $sort, + orderProperties: [], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderHeader($column, $cell, $context); + $this->assertEquals('Custom Header', $result->getContent()[0]); + } + + public function testRenderHeaderWithoutHeaderAndProperty(): void + { + $column = new DataColumn(); + $cell = new Cell(); + $translator = Mock::translator('en'); + $sort = Sort::any(); + + $context = new HeaderContext( + originalSort: $sort, + sort: $sort, + orderProperties: [], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderHeader($column, $cell, $context); + $this->assertEquals('', $result->getContent()[0]); + } + + public function testRenderBodyWithNullContent(): void + { + $column = new DataColumn(); + $cell = new Cell(); + $data = ['id' => 1, 'name' => null]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderBody($column, $cell, $context); + $this->assertEquals('', $result->getContent()[0]); + } + + public function testRenderFooterWithContent(): void + { + $column = new DataColumn(footer: 'Total: 100'); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderFooter($column, $cell, $context); + $this->assertEquals('Total: 100', $result->getContent()[0]); + } + + public function testRenderFooterWithoutContent(): void + { + $column = new DataColumn(); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderFooter($column, $cell, $context); + $this->assertEmpty($result->getContent()); + } + + public function testRenderFilterWithoutProperty(): void + { + $column = new DataColumn(); + $cell = new Cell(); + + $urlParameterProvider = new class () implements UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return null; + } + }; + + $context = new FilterContext( + 'filter-form', + new Result(), + 'invalid', + ['class' => 'error-container'], + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderFilter($column, $cell, $context); + $this->assertNull($result); + } + + public function testRenderFilterWithFilterDisabled(): void + { + $column = new DataColumn('name', filter: false); + $cell = new Cell(); + + $urlParameterProvider = new class () implements UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return null; + } + }; + + $context = new FilterContext( + 'filter-form', + new Result(), + 'invalid', + ['class' => 'error-container'], + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderFilter($column, $cell, $context); + $this->assertNull($result); + } + + public function testMakeFilterWithNeverEmptyCallback(): void + { + $column = new DataColumn( + 'status', + filterEmpty: false + ); + + $urlParameterProvider = new class () implements UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return 'test'; + } + }; + + $context = new MakeFilterContext( + new Result(), + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->makeFilter($column, $context); + $this->assertNotNull($result); + } + + public function testMakeFilterWithCustomEmptyCallback(): void + { + $column = new DataColumn( + 'status', + filterEmpty: static fn (mixed $value): bool => $value === 'empty' + ); + + $urlParameterProvider = new class () implements UrlParameterProviderInterface { + public function get(string $name, int $type): ?string + { + return 'empty'; + } + }; + + $context = new MakeFilterContext( + new Result(), + $urlParameterProvider + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->makeFilter($column, $context); + $this->assertNull($result); + } + + public function testRenderHeaderWithSortingDisabled(): void + { + $column = new DataColumn('test', withSorting: false); + $cell = new Cell(); + $translator = Mock::translator('en'); + $sort = Sort::any(); + + $context = new HeaderContext( + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '↑', + sortableHeaderAppend: '↓', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderHeader($column, $cell, $context); + $content = $result->getContent()[0]; + $this->assertEquals('Test', $content); + $this->assertArrayNotHasKey('class', $result->getAttributes()); + } + + public function testRenderHeaderWithSorting(): void + { + $column = new DataColumn('test', withSorting: true); + $cell = new Cell(); + $translator = Mock::translator('en'); + $sort = Sort::only(['test']); + + $context = new HeaderContext( + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '↑', + sortableHeaderAppend: '↓', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderHeader($column, $cell, $context); + $content = $result->getContent()[0]; + $this->assertStringContainsString('Test', $content); + $this->assertStringContainsString('↑', $content); + $this->assertStringContainsString('↓', $content); + $this->assertStringContainsString('sortable', $result->getAttributes()['class']); + } + + public function testRenderHeaderWithAscendingSort(): void + { + $column = new DataColumn('test', withSorting: true); + $cell = new Cell(); + $translator = Mock::translator('en'); + $sort = Sort::only(['test'])->withOrder(['test' => 'asc']); + + $context = new HeaderContext( + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '↑', + sortableHeaderAppend: '↓', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '↑', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderHeader($column, $cell, $context); + $content = $result->getContent()[0]; + $this->assertStringContainsString('Test', $content); + $this->assertStringContainsString('↑', $content); + $this->assertStringNotContainsString('↓', $content); + $this->assertStringContainsString('asc', $result->getAttributes()['class']); + } + + public function testRenderHeaderWithDescendingSort(): void + { + $column = new DataColumn('test', withSorting: true); + $cell = new Cell(); + $translator = Mock::translator('en'); + $sort = Sort::only(['test'])->withOrder(['test' => 'desc']); + + $context = new HeaderContext( + originalSort: $sort, + sort: $sort, + orderProperties: ['test' => 'test'], + sortableHeaderClass: 'sortable', + sortableHeaderPrepend: '↑', + sortableHeaderAppend: '↓', + sortableHeaderAscClass: 'asc', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: 'desc', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '↓', + sortableLinkAttributes: [], + sortableLinkAscClass: 'asc-link', + sortableLinkDescClass: 'desc-link', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new DataColumnRenderer( + $this->filterFactoryContainer, + new Validator() + ); + + $result = $renderer->renderHeader($column, $cell, $context); + $content = $result->getContent()[0]; + $this->assertStringContainsString('Test', $content); + $this->assertStringNotContainsString('↑', $content); + $this->assertStringContainsString('↓', $content); + $this->assertStringContainsString('desc', $result->getAttributes()['class']); + } } From 6354d3becd62b4976bd5abbabc78e8fa89f2fb35 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 15:13:17 +0300 Subject: [PATCH 13/20] More --- tests/Column/RadioColumnRendererTest.php | 115 ++++++++++++++++++++++- 1 file changed, 110 insertions(+), 5 deletions(-) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index ba243068a..1b7652c51 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -89,11 +89,11 @@ public function testRenderHeaderWithNullHeader(): void $this->assertNull($result); } - public function testRenderHeaderWithCustomHeader(): void + public function testRenderHeaderWithCustomAttributes(): void { $column = new RadioColumn( header: 'Select', - headerAttributes: ['class' => 'header-class'] + headerAttributes: ['class' => 'header-class', 'data-test' => 'value'] ); $cell = new Cell(); $translator = Mock::translator('en'); @@ -130,6 +130,8 @@ public function testRenderHeaderWithCustomHeader(): void $this->assertSame('Select', $result->getContent()[0]); $this->assertArrayHasKey('class', $result->getAttributes()); $this->assertSame('header-class', $result->getAttributes()['class']); + $this->assertArrayHasKey('data-test', $result->getAttributes()); + $this->assertSame('value', $result->getAttributes()['data-test']); } public function testRenderBodyWithDefaultSettings(): void @@ -185,10 +187,12 @@ public function testRenderBodyWithCustomInputAttributes(): void $this->assertStringContainsString('class="radio-class"', (string)$content[0]); } - public function testRenderBodyWithCustomContent(): void + public function testRenderBodyWithCustomContentAndAttributes(): void { $column = new RadioColumn( - content: static fn($input, $context) => Html::div($input)->class('custom-wrapper') + content: static fn($input) => Html::div($input)->class('custom-wrapper'), + bodyAttributes: ['class' => 'body-class', 'data-index' => '1'], + inputAttributes: ['class' => 'input-class', 'data-test' => 'value'] ); $cell = new Cell(); $data = ['id' => 1, 'name' => 'John', 'age' => 20]; @@ -207,7 +211,12 @@ public function testRenderBodyWithCustomContent(): void $content = $result->getContent(); $this->assertNotEmpty($content); $this->assertStringContainsString('
', (string)$content[0]); - $this->assertStringContainsString('radio-selection', (string)$content[0]); + $this->assertStringContainsString('class="input-class"', (string)$content[0]); + $this->assertStringContainsString('data-test="value"', (string)$content[0]); + $this->assertArrayHasKey('class', $result->getAttributes()); + $this->assertSame('body-class', $result->getAttributes()['class']); + $this->assertArrayHasKey('data-index', $result->getAttributes()); + $this->assertSame('1', $result->getAttributes()['data-index']); } public function testRenderFooterWithContent(): void @@ -251,4 +260,100 @@ public function testRenderFooterWithoutContent(): void $this->assertEmpty($result->getContent()); } + + public function testRenderBodyWithCustomContentAndEmptyAttributes(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div($input)->class('custom-wrapper'), + bodyAttributes: [], + inputAttributes: [] + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('
', (string)$content[0]); + $this->assertEmpty($result->getAttributes()); + } + + public function testRenderBodyWithCustomName(): void + { + $column = new RadioColumn( + inputAttributes: ['name' => 'custom-selection'] + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="custom-selection"', (string)$content[0]); + } + + public function testRenderBodyWithInvisibleColumn(): void + { + $column = new RadioColumn(visible: false); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('type="radio"', (string)$content[0]); + } + + public function testRenderColumnWithInvisibleColumn(): void + { + $column = new RadioColumn( + columnAttributes: ['class' => 'test-column'], + visible: false + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderColumn($column, $cell, $context); + + $this->assertSame(['class' => 'test-column'], $result->getAttributes()); + } } From 4b12f09adc44e1ea25f2bf36640ec2c3c00ea6dc Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 15:28:13 +0300 Subject: [PATCH 14/20] More --- tests/Column/RadioColumnRendererTest.php | 321 +++++++++++++++++++++++ 1 file changed, 321 insertions(+) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index 1b7652c51..17594570c 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -356,4 +356,325 @@ public function testRenderColumnWithInvisibleColumn(): void $this->assertSame(['class' => 'test-column'], $result->getAttributes()); } + + public function testRenderBodyWithDefaultNameAndValue(): void + { + $column = new RadioColumn(); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 'test-key', + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="radio-selection"', (string)$content[0]); + $this->assertStringContainsString('value="test-key"', (string)$content[0]); + } + + public function testRenderBodyWithCustomValue(): void + { + $column = new RadioColumn( + inputAttributes: ['value' => 'custom-value'] + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 'test-key', + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('value="custom-value"', (string)$content[0]); + } + + public function testRenderHeaderWithEmptyAttributes(): void + { + $column = new RadioColumn( + header: 'Test Header', + headerAttributes: [] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new HeaderContext( + originalSort: null, + sort: null, + orderProperties: [], + sortableHeaderClass: '', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: '', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: '', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: '', + sortableLinkDescClass: '', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderHeader($column, $cell, $context); + + $this->assertNotNull($result); + $this->assertSame('Test Header', $result->getContent()[0]); + $this->assertEmpty($result->getAttributes()); + } + + public function testRenderColumnWithMultipleAttributes(): void + { + $column = new RadioColumn( + columnAttributes: [ + 'class' => 'test-column', + 'data-role' => 'radio-column', + 'data-index' => '1', + ] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderColumn($column, $cell, $context); + + $this->assertSame( + [ + 'class' => 'test-column', + 'data-role' => 'radio-column', + 'data-index' => '1', + ], + $result->getAttributes() + ); + } + + public function testRenderHeaderWithHtmlSpecialChars(): void + { + $column = new RadioColumn( + header: '', + headerAttributes: ['class' => 'header-class'] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new HeaderContext( + originalSort: null, + sort: null, + orderProperties: [], + sortableHeaderClass: '', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: '', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: '', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: '', + sortableLinkDescClass: '', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderHeader($column, $cell, $context); + + $this->assertNotNull($result); + $this->assertSame('', $result->getContent()[0]); + $this->assertSame(['class' => 'header-class'], $result->getAttributes()); + } + + public function testRenderFooterWithColumnAttributes(): void + { + $column = new RadioColumn( + footer: 'Total', + columnAttributes: ['class' => 'column-class'] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderFooter($column, $cell, $context); + + $this->assertSame('Total', $result->getContent()[0]); + } + + public function testRenderBodyWithRealWorldData(): void + { + $column = new RadioColumn( + bodyAttributes: ['class' => 'selection-column'], + inputAttributes: [ + 'name' => 'user-selection', + 'class' => 'user-radio', + 'form' => 'user-form', + ] + ); + $cell = new Cell(); + $data = [ + 'id' => 42, + 'username' => 'john.doe', + 'email' => 'john@example.com', + ]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 42, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="user-selection"', (string)$content[0]); + $this->assertStringContainsString('class="user-radio"', (string)$content[0]); + $this->assertStringContainsString('form="user-form"', (string)$content[0]); + $this->assertStringContainsString('value="42"', (string)$content[0]); + $this->assertSame(['class' => 'selection-column'], $result->getAttributes()); + } + + public function testRenderFooterWithHtmlContent(): void + { + $column = new RadioColumn( + footer: 'Total: 42' + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new GlobalContext( + dataReader: $this->dataReader, + pathArguments: [], + queryParameters: [], + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderFooter($column, $cell, $context); + + $this->assertSame('Total: 42', $result->getContent()[0]); + } + + public function testRenderHeaderWithAttributesButNoContent(): void + { + $column = new RadioColumn( + headerAttributes: ['class' => 'header-class'] + ); + $cell = new Cell(); + $translator = Mock::translator('en'); + + $context = new HeaderContext( + originalSort: null, + sort: null, + orderProperties: [], + sortableHeaderClass: '', + sortableHeaderPrepend: '', + sortableHeaderAppend: '', + sortableHeaderAscClass: '', + sortableHeaderAscPrepend: '', + sortableHeaderAscAppend: '', + sortableHeaderDescClass: '', + sortableHeaderDescPrepend: '', + sortableHeaderDescAppend: '', + sortableLinkAttributes: [], + sortableLinkAscClass: '', + sortableLinkDescClass: '', + pageToken: null, + pageSize: 10, + multiSort: false, + urlConfig: new UrlConfig(), + urlCreator: null, + translator: $translator, + translationCategory: 'test' + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderHeader($column, $cell, $context); + + $this->assertNull($result); + } + + public function testRenderBodyWithCustomHtmlContent(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('input-group') + ->content( + Html::label() + ->content( + $input, + Html::span('*')->class('required'), + 'Select user' + ) + ) + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('
', (string)$content[0]); + $this->assertStringContainsString('Select user', (string)$content[0]); + $this->assertStringContainsString('*', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } } From 54855c3754053a17278085dc3eca454110faec77 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 15:41:42 +0300 Subject: [PATCH 15/20] FIx --- tests/Column/RadioColumnRendererTest.php | 83 ++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index 17594570c..ae38488a7 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -677,4 +677,87 @@ public function testRenderBodyWithCustomHtmlContent(): void $this->assertStringContainsString('*', (string)$content[0]); $this->assertFalse($result->shouldEncode()); } + + public function testRenderBodyWithCustomLabelAndAttributes(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::label($input, 'Select item') + ->class('form-label') + ->attribute('data-testid', 'radio-label'), + bodyAttributes: ['class' => 'radio-cell'], + inputAttributes: [ + 'class' => 'form-radio', + 'data-testid' => 'radio-input', + ] + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('class="form-label"', (string)$content[0]); + $this->assertStringContainsString('data-testid="radio-label"', (string)$content[0]); + $this->assertStringContainsString('class="form-radio"', (string)$content[0]); + $this->assertStringContainsString('data-testid="radio-input"', (string)$content[0]); + $this->assertSame(['class' => 'radio-cell'], $result->getAttributes()); + } + + public function testRenderBodyWithCheckedInput(): void + { + $column = new RadioColumn( + inputAttributes: ['checked' => true] + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString(' checked>', (string)$content[0]); + } + + public function testRenderBodyWithDisabledInput(): void + { + $column = new RadioColumn( + inputAttributes: ['disabled' => true] + ); + $cell = new Cell(); + $data = ['id' => 1]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString(' disabled>', (string)$content[0]); + } } From 863d31cad487ca7ff636553d8e428ebbd36adfe4 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 15:51:12 +0300 Subject: [PATCH 16/20] Fix --- tests/Column/RadioColumnRendererTest.php | 213 +++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index ae38488a7..cdc5b7de0 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -760,4 +760,217 @@ public function testRenderBodyWithDisabledInput(): void $this->assertNotEmpty($content); $this->assertStringContainsString(' disabled>', (string)$content[0]); } + + public function testRenderBodyWithCustomInputName(): void + { + $column = new RadioColumn( + name: 'selection' + ); + $cell = new Cell(); + $data = ['id' => 42, 'name' => 'test']; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="selection"', (string)$content[0]); + } + + public function testRenderBodyWithCustomContent(): void + { + $column = new RadioColumn( + content: static fn($input) => $input . ' Custom label' + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('Custom label', (string)$content[0]); + } + + public function testRenderBodyWithEmptyName(): void + { + $column = new RadioColumn( + name: '' + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name ', (string)$content[0]); + $this->assertStringContainsString('value="1"', (string)$content[0]); + } + + public function testRenderBodyWithMultipleAttributes(): void + { + $column = new RadioColumn( + name: 'selection', + inputAttributes: [ + 'class' => 'form-check-input', + 'data-testid' => 'radio-input', + 'required' => true + ], + bodyAttributes: ['class' => 'form-check'] + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('class="form-check-input"', (string)$content[0]); + $this->assertStringContainsString('data-testid="radio-input"', (string)$content[0]); + $this->assertStringContainsString(' required>', (string)$content[0]); + $this->assertSame(['class' => 'form-check'], $result->getAttributes()); + } + + public function testRenderBodyWithEmptyContentClosure(): void + { + $column = new RadioColumn( + content: static fn() => '' + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertSame('', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithContextInContentClosure(): void + { + $column = new RadioColumn( + content: static fn($input, $context) => (string)$input . ' Item ' . $context->index + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 5 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertStringContainsString('Item 5', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithAriaLabelAttribute(): void + { + $column = new RadioColumn( + content: static fn($input) => (string)$input, + inputAttributes: ['aria-label' => 'Select item'] + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertStringContainsString('aria-label="Select item"', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithComplexContent(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check') + ->content( + $input, + Html::div() + ->class('help-text') + ->content('Select one option') + ) + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('class="form-check"', (string)$content[0]); + $this->assertStringContainsString('class="help-text"', (string)$content[0]); + $this->assertStringContainsString('Select one option', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } } From 4569668d463409ca66d2965f21fe171aa27d5a90 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 10 Mar 2025 12:51:23 +0000 Subject: [PATCH 17/20] Apply fixes from StyleCI --- tests/Column/RadioColumnRendererTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index cdc5b7de0..246febe69 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -841,7 +841,7 @@ public function testRenderBodyWithMultipleAttributes(): void inputAttributes: [ 'class' => 'form-check-input', 'data-testid' => 'radio-input', - 'required' => true + 'required' => true, ], bodyAttributes: ['class' => 'form-check'] ); From d54dbb5e62982eb021ee1a0d53ee4694ff9f211f Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 10 Mar 2025 16:21:40 +0300 Subject: [PATCH 18/20] More tests --- tests/Column/RadioColumnRendererTest.php | 298 ++++++++++++++++++++++- 1 file changed, 289 insertions(+), 9 deletions(-) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index 246febe69..9bdcf2e29 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -809,14 +809,12 @@ public function testRenderBodyWithCustomContent(): void $this->assertStringContainsString('Custom label', (string)$content[0]); } - public function testRenderBodyWithEmptyName(): void + public function testDefaultNameIsUsedWhenNotProvided(): void { - $column = new RadioColumn( - name: '' - ); + // Arrange + $column = new RadioColumn(); $cell = new Cell(); $data = ['id' => 42]; - $context = new DataContext( preparedDataReader: $this->dataReader, column: $column, @@ -824,14 +822,14 @@ public function testRenderBodyWithEmptyName(): void key: 1, index: 0 ); - $renderer = new RadioColumnRenderer(); + + // Act $result = $renderer->renderBody($column, $cell, $context); + // Assert $content = $result->getContent(); - $this->assertNotEmpty($content); - $this->assertStringContainsString('name ', (string)$content[0]); - $this->assertStringContainsString('value="1"', (string)$content[0]); + $this->assertStringContainsString('name="radio-selection"', (string)$content[0]); } public function testRenderBodyWithMultipleAttributes(): void @@ -973,4 +971,286 @@ public function testRenderBodyWithComplexContent(): void $this->assertStringContainsString('Select one option', (string)$content[0]); $this->assertFalse($result->shouldEncode()); } + + public function testRenderBodyWithBootstrapFormCheck(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content('Option 1') + ), + inputAttributes: ['class' => 'form-check-input'] + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('class="form-check"', (string)$content[0]); + $this->assertStringContainsString('class="form-check-input"', (string)$content[0]); + $this->assertStringContainsString('class="form-check-label"', (string)$content[0]); + $this->assertStringContainsString('Option 1', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithInlineFormCheck(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check form-check-inline') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content('Option 1') + ), + inputAttributes: ['class' => 'form-check-input'] + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('class="form-check form-check-inline"', (string)$content[0]); + $this->assertStringContainsString('class="form-check-input"', (string)$content[0]); + $this->assertStringContainsString('class="form-check-label"', (string)$content[0]); + $this->assertStringContainsString('Option 1', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithDataAttributes(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check') + ->attribute('data-bs-toggle', 'tooltip') + ->attribute('title', 'Select this option') + ->content($input), + inputAttributes: [ + 'class' => 'form-check-input', + 'data-bs-target' => '#target', + 'data-bs-action' => 'select' + ] + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('data-bs-toggle="tooltip"', (string)$content[0]); + $this->assertStringContainsString('title="Select this option"', (string)$content[0]); + $this->assertStringContainsString('data-bs-target="#target"', (string)$content[0]); + $this->assertStringContainsString('data-bs-action="select"', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithCustomValueAndChecked(): void + { + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input), + inputAttributes: [ + 'value' => '42_custom', + 'checked' => true, + ] + ); + $cell = new Cell(); + $data = ['id' => 42]; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('value="42_custom"', (string)$content[0]); + $this->assertStringContainsString('checked', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testEmptyNameAttributeIsPreserved(): void + { + // Arrange + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input), + inputAttributes: [ + 'name' => '', + ] + ); + $cell = new Cell(); + $data = ['id' => 42]; + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + $renderer = new RadioColumnRenderer(); + + // Act + $result = $renderer->renderBody($column, $cell, $context); + + // Assert + $content = $result->getContent(); + $this->assertStringContainsString('name value="1"', (string)$content[0]); + } + + public function testEmptyValueAttributeIsPreserved(): void + { + // Arrange + $column = new RadioColumn( + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input), + inputAttributes: [ + 'value' => '', + ] + ); + $cell = new Cell(); + $data = ['id' => 42]; + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + $renderer = new RadioColumnRenderer(); + + // Act + $result = $renderer->renderBody($column, $cell, $context); + + // Assert + $content = $result->getContent(); + $this->assertStringContainsString('name="radio-selection" value', (string)$content[0]); + } + + public function testRenderBodyWithActiveStatus(): void + { + $column = new RadioColumn( + name: 'status', + content: static fn($input, $context) => Html::div() + ->class('form-check') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content($context->data['status']) + ), + inputAttributes: [ + 'class' => 'form-check-input', + 'value' => 'active', + 'checked' => true + ] + ); + + $cell = new Cell(); + $data = ['id' => 42, 'status' => 'active']; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 1, + index: 0 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="status"', (string)$content[0]); + $this->assertStringContainsString('value="active"', (string)$content[0]); + $this->assertStringContainsString('checked', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testRenderBodyWithInactiveStatus(): void + { + $column = new RadioColumn( + name: 'status', + content: static fn($input, $context) => Html::div() + ->class('form-check') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content($context->data['status']) + ), + inputAttributes: [ + 'class' => 'form-check-input', + 'value' => 'inactive' + ] + ); + + $cell = new Cell(); + $data = ['id' => 43, 'status' => 'inactive']; + + $context = new DataContext( + preparedDataReader: $this->dataReader, + column: $column, + data: $data, + key: 2, + index: 1 + ); + + $renderer = new RadioColumnRenderer(); + $result = $renderer->renderBody($column, $cell, $context); + + $content = $result->getContent(); + $this->assertNotEmpty($content); + $this->assertStringContainsString('name="status"', (string)$content[0]); + $this->assertStringContainsString('value="inactive"', (string)$content[0]); + $this->assertStringNotContainsString('checked', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } } From dfb75b28b8a6a30a63127f7b18a504032281e1ad Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 10 Mar 2025 13:22:55 +0000 Subject: [PATCH 19/20] Apply fixes from StyleCI --- tests/Column/RadioColumnRendererTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index 9bdcf2e29..e39b19949 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -1055,7 +1055,7 @@ public function testRenderBodyWithDataAttributes(): void inputAttributes: [ 'class' => 'form-check-input', 'data-bs-target' => '#target', - 'data-bs-action' => 'select' + 'data-bs-action' => 'select', ] ); $cell = new Cell(); @@ -1188,7 +1188,7 @@ public function testRenderBodyWithActiveStatus(): void inputAttributes: [ 'class' => 'form-check-input', 'value' => 'active', - 'checked' => true + 'checked' => true, ] ); @@ -1228,7 +1228,7 @@ public function testRenderBodyWithInactiveStatus(): void ), inputAttributes: [ 'class' => 'form-check-input', - 'value' => 'inactive' + 'value' => 'inactive', ] ); From 4ba5a8ee24970230b5488266aa1d8a60d3fdf1ce Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 12 Mar 2025 01:15:51 +0300 Subject: [PATCH 20/20] Cleanup --- tests/Column/RadioColumnRendererTest.php | 90 +++++++++++------------ tests/Pagination/KeysetPaginationTest.php | 1 - 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php index e39b19949..f36847bd8 100644 --- a/tests/Column/RadioColumnRendererTest.php +++ b/tests/Column/RadioColumnRendererTest.php @@ -190,9 +190,9 @@ public function testRenderBodyWithCustomInputAttributes(): void public function testRenderBodyWithCustomContentAndAttributes(): void { $column = new RadioColumn( - content: static fn($input) => Html::div($input)->class('custom-wrapper'), bodyAttributes: ['class' => 'body-class', 'data-index' => '1'], - inputAttributes: ['class' => 'input-class', 'data-test' => 'value'] + inputAttributes: ['class' => 'input-class', 'data-test' => 'value'], + content: static fn($input) => Html::div($input)->class('custom-wrapper') ); $cell = new Cell(); $data = ['id' => 1, 'name' => 'John', 'age' => 20]; @@ -264,9 +264,9 @@ public function testRenderFooterWithoutContent(): void public function testRenderBodyWithCustomContentAndEmptyAttributes(): void { $column = new RadioColumn( - content: static fn($input) => Html::div($input)->class('custom-wrapper'), bodyAttributes: [], - inputAttributes: [] + inputAttributes: [], + content: static fn($input) => Html::div($input)->class('custom-wrapper') ); $cell = new Cell(); $data = ['id' => 1]; @@ -681,14 +681,14 @@ public function testRenderBodyWithCustomHtmlContent(): void public function testRenderBodyWithCustomLabelAndAttributes(): void { $column = new RadioColumn( - content: static fn($input) => Html::label($input, 'Select item') - ->class('form-label') - ->attribute('data-testid', 'radio-label'), bodyAttributes: ['class' => 'radio-cell'], inputAttributes: [ 'class' => 'form-radio', 'data-testid' => 'radio-input', - ] + ], + content: static fn($input) => Html::label($input, 'Select item') + ->class('form-label') + ->attribute('data-testid', 'radio-label') ); $cell = new Cell(); $data = ['id' => 1]; @@ -835,13 +835,13 @@ public function testDefaultNameIsUsedWhenNotProvided(): void public function testRenderBodyWithMultipleAttributes(): void { $column = new RadioColumn( - name: 'selection', + bodyAttributes: ['class' => 'form-check'], inputAttributes: [ 'class' => 'form-check-input', 'data-testid' => 'radio-input', 'required' => true, ], - bodyAttributes: ['class' => 'form-check'] + name: 'selection' ); $cell = new Cell(); $data = ['id' => 42]; @@ -916,8 +916,8 @@ public function testRenderBodyWithContextInContentClosure(): void public function testRenderBodyWithAriaLabelAttribute(): void { $column = new RadioColumn( - content: static fn($input) => (string)$input, - inputAttributes: ['aria-label' => 'Select item'] + inputAttributes: ['aria-label' => 'Select item'], + content: static fn($input) => (string)$input ); $cell = new Cell(); $data = ['id' => 42]; @@ -975,6 +975,7 @@ public function testRenderBodyWithComplexContent(): void public function testRenderBodyWithBootstrapFormCheck(): void { $column = new RadioColumn( + inputAttributes: ['class' => 'form-check-input'], content: static fn($input) => Html::div() ->class('form-check') ->content( @@ -982,8 +983,7 @@ public function testRenderBodyWithBootstrapFormCheck(): void Html::label() ->class('form-check-label') ->content('Option 1') - ), - inputAttributes: ['class' => 'form-check-input'] + ) ); $cell = new Cell(); $data = ['id' => 42]; @@ -1011,6 +1011,7 @@ public function testRenderBodyWithBootstrapFormCheck(): void public function testRenderBodyWithInlineFormCheck(): void { $column = new RadioColumn( + inputAttributes: ['class' => 'form-check-input'], content: static fn($input) => Html::div() ->class('form-check form-check-inline') ->content( @@ -1018,8 +1019,7 @@ public function testRenderBodyWithInlineFormCheck(): void Html::label() ->class('form-check-label') ->content('Option 1') - ), - inputAttributes: ['class' => 'form-check-input'] + ) ); $cell = new Cell(); $data = ['id' => 42]; @@ -1047,16 +1047,16 @@ public function testRenderBodyWithInlineFormCheck(): void public function testRenderBodyWithDataAttributes(): void { $column = new RadioColumn( - content: static fn($input) => Html::div() - ->class('form-check') - ->attribute('data-bs-toggle', 'tooltip') - ->attribute('title', 'Select this option') - ->content($input), inputAttributes: [ 'class' => 'form-check-input', 'data-bs-target' => '#target', 'data-bs-action' => 'select', - ] + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->attribute('data-bs-toggle', 'tooltip') + ->attribute('title', 'Select this option') + ->content($input) ); $cell = new Cell(); $data = ['id' => 42]; @@ -1084,13 +1084,13 @@ public function testRenderBodyWithDataAttributes(): void public function testRenderBodyWithCustomValueAndChecked(): void { $column = new RadioColumn( - content: static fn($input) => Html::div() - ->class('form-check') - ->content($input), inputAttributes: [ 'value' => '42_custom', 'checked' => true, - ] + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input) ); $cell = new Cell(); $data = ['id' => 42]; @@ -1117,12 +1117,12 @@ public function testEmptyNameAttributeIsPreserved(): void { // Arrange $column = new RadioColumn( - content: static fn($input) => Html::div() - ->class('form-check') - ->content($input), inputAttributes: [ 'name' => '', - ] + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input) ); $cell = new Cell(); $data = ['id' => 42]; @@ -1147,12 +1147,12 @@ public function testEmptyValueAttributeIsPreserved(): void { // Arrange $column = new RadioColumn( - content: static fn($input) => Html::div() - ->class('form-check') - ->content($input), inputAttributes: [ 'value' => '', - ] + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input) ); $cell = new Cell(); $data = ['id' => 42]; @@ -1176,6 +1176,11 @@ public function testEmptyValueAttributeIsPreserved(): void public function testRenderBodyWithActiveStatus(): void { $column = new RadioColumn( + inputAttributes: [ + 'class' => 'form-check-input', + 'value' => 'active', + 'checked' => true, + ], name: 'status', content: static fn($input, $context) => Html::div() ->class('form-check') @@ -1184,12 +1189,7 @@ public function testRenderBodyWithActiveStatus(): void Html::label() ->class('form-check-label') ->content($context->data['status']) - ), - inputAttributes: [ - 'class' => 'form-check-input', - 'value' => 'active', - 'checked' => true, - ] + ) ); $cell = new Cell(); @@ -1217,6 +1217,10 @@ public function testRenderBodyWithActiveStatus(): void public function testRenderBodyWithInactiveStatus(): void { $column = new RadioColumn( + inputAttributes: [ + 'class' => 'form-check-input', + 'value' => 'inactive', + ], name: 'status', content: static fn($input, $context) => Html::div() ->class('form-check') @@ -1225,11 +1229,7 @@ public function testRenderBodyWithInactiveStatus(): void Html::label() ->class('form-check-label') ->content($context->data['status']) - ), - inputAttributes: [ - 'class' => 'form-check-input', - 'value' => 'inactive', - ] + ) ); $cell = new Cell(); diff --git a/tests/Pagination/KeysetPaginationTest.php b/tests/Pagination/KeysetPaginationTest.php index bd60f97da..e20e9b777 100644 --- a/tests/Pagination/KeysetPaginationTest.php +++ b/tests/Pagination/KeysetPaginationTest.php @@ -18,7 +18,6 @@ use Yiisoft\Yii\DataView\GridView; use Yiisoft\Yii\DataView\Pagination\KeysetPagination; use Yiisoft\Yii\DataView\Tests\Support\Assert; -use Yiisoft\Yii\DataView\Tests\Support\Mock; use Yiisoft\Yii\DataView\Tests\Support\TestTrait; final class KeysetPaginationTest extends TestCase