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']); + } } diff --git a/tests/Column/RadioColumnRendererTest.php b/tests/Column/RadioColumnRendererTest.php new file mode 100644 index 000000000..f36847bd8 --- /dev/null +++ b/tests/Column/RadioColumnRendererTest.php @@ -0,0 +1,1256 @@ +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 testRenderHeaderWithCustomAttributes(): void + { + $column = new RadioColumn( + header: 'Select', + headerAttributes: ['class' => 'header-class', 'data-test' => 'value'] + ); + $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']); + $this->assertArrayHasKey('data-test', $result->getAttributes()); + $this->assertSame('value', $result->getAttributes()['data-test']); + } + + 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 testRenderBodyWithCustomContentAndAttributes(): void + { + $column = new RadioColumn( + bodyAttributes: ['class' => 'body-class', 'data-index' => '1'], + 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]; + + $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('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 + { + $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()); + } + + public function testRenderBodyWithCustomContentAndEmptyAttributes(): void + { + $column = new RadioColumn( + bodyAttributes: [], + inputAttributes: [], + content: static fn($input) => Html::div($input)->class('custom-wrapper') + ); + $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()); + } + + 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()); + } + + public function testRenderBodyWithCustomLabelAndAttributes(): void + { + $column = new RadioColumn( + 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]; + + $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]); + } + + 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 testDefaultNameIsUsedWhenNotProvided(): void + { + // Arrange + $column = new RadioColumn(); + $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"', (string)$content[0]); + } + + public function testRenderBodyWithMultipleAttributes(): void + { + $column = new RadioColumn( + bodyAttributes: ['class' => 'form-check'], + inputAttributes: [ + 'class' => 'form-check-input', + 'data-testid' => 'radio-input', + 'required' => true, + ], + name: 'selection' + ); + $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( + inputAttributes: ['aria-label' => 'Select item'], + content: static fn($input) => (string)$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->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()); + } + + public function testRenderBodyWithBootstrapFormCheck(): void + { + $column = new RadioColumn( + inputAttributes: ['class' => 'form-check-input'], + content: static fn($input) => Html::div() + ->class('form-check') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content('Option 1') + ) + ); + $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( + inputAttributes: ['class' => 'form-check-input'], + content: static fn($input) => Html::div() + ->class('form-check form-check-inline') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content('Option 1') + ) + ); + $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( + 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]; + + $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( + inputAttributes: [ + 'value' => '42_custom', + 'checked' => true, + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->content($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('value="42_custom"', (string)$content[0]); + $this->assertStringContainsString('checked', (string)$content[0]); + $this->assertFalse($result->shouldEncode()); + } + + public function testEmptyNameAttributeIsPreserved(): void + { + // Arrange + $column = new RadioColumn( + inputAttributes: [ + 'name' => '', + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input) + ); + $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( + inputAttributes: [ + 'value' => '', + ], + content: static fn($input) => Html::div() + ->class('form-check') + ->content($input) + ); + $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( + inputAttributes: [ + 'class' => 'form-check-input', + 'value' => 'active', + 'checked' => true, + ], + name: 'status', + content: static fn($input, $context) => Html::div() + ->class('form-check') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content($context->data['status']) + ) + ); + + $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( + inputAttributes: [ + 'class' => 'form-check-input', + 'value' => 'inactive', + ], + name: 'status', + content: static fn($input, $context) => Html::div() + ->class('form-check') + ->content( + $input, + Html::label() + ->class('form-check-label') + ->content($context->data['status']) + ) + ); + + $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()); + } +} diff --git a/tests/Pagination/KeysetPaginationTest.php b/tests/Pagination/KeysetPaginationTest.php index 86a15043d..e20e9b777 100644 --- a/tests/Pagination/KeysetPaginationTest.php +++ b/tests/Pagination/KeysetPaginationTest.php @@ -4,14 +4,17 @@ namespace Yiisoft\Yii\DataView\Tests\Pagination; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; 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; @@ -365,4 +368,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(), + ); + } }