* @group grid */ class GridViewTest extends TestCase { protected function setUp(): void { parent::setUp(); $this->mockApplication([ 'components' => [ 'assetManager' => [ 'bundles' => [ 'yii\grid\GridViewAsset' => false, 'yii\web\JqueryAsset' => false, ], ], ], ]); } /** * @return array */ public static function emptyDataProvider(): array { return [ [null, 'No results found.'], ['Empty', 'Empty'], // https://github.com/yiisoft/yii2/issues/13352 [false, ''], ]; } /** * @dataProvider emptyDataProvider * @param mixed $emptyText * @param string $expectedText * @throws Exception */ public function testEmpty($emptyText, $expectedText): void { $html = GridView::widget([ 'id' => 'grid', 'dataProvider' => new ArrayDataProvider(['allModels' => []]), 'showHeader' => false, 'emptyText' => $emptyText, 'options' => [], 'tableOptions' => [], 'view' => new View(), 'filterUrl' => '/', ]); $html = preg_replace("/\r|\n/", '', $html); if ($expectedText) { $emptyRowHtml = "
{$expectedText}
"; } else { $emptyRowHtml = ''; } $expectedHtml = "
{$emptyRowHtml}
"; $this->assertEquals($expectedHtml, $html); } public function testGuessColumns(): void { $row = ['id' => 1, 'name' => 'Name1', 'value' => 'Value1', 'description' => 'Description1']; $grid = new GridView([ 'dataProvider' => new ArrayDataProvider( [ 'allModels' => [ $row, ], ] ), ]); $columns = $grid->columns; $this->assertCount(count($row), $columns); foreach ($columns as $index => $column) { $this->assertInstanceOf(DataColumn::class, $column); $this->assertArrayHasKey($column->attribute, $row); } $row = array_merge($row, ['relation' => ['id' => 1, 'name' => 'RelationName']]); $row = array_merge($row, ['otherRelation' => (object) $row['relation']]); $grid = new GridView([ 'dataProvider' => new ArrayDataProvider( [ 'allModels' => [ $row, ], ] ), ]); $columns = $grid->columns; $this->assertCount(count($row) - 2, $columns); foreach ($columns as $index => $column) { $this->assertInstanceOf(DataColumn::class, $column); $this->assertArrayHasKey($column->attribute, $row); $this->assertNotEquals('relation', $column->attribute); $this->assertNotEquals('otherRelation', $column->attribute); } } /** * @throws Exception */ public function testFooter(): void { $config = [ 'id' => 'grid', 'dataProvider' => new ArrayDataProvider(['allModels' => []]), 'showHeader' => false, 'showFooter' => true, 'options' => [], 'tableOptions' => [], 'view' => new View(), 'filterUrl' => '/', ]; $html = GridView::widget($config); $html = preg_replace("/\r|\n/", '', $html); $this->assertTrue(preg_match('/<\/tfoot>/', $html) === 1); // Place footer after body $config['placeFooterAfterBody'] = true; $html = GridView::widget($config); $html = preg_replace("/\r|\n/", '', $html); $this->assertTrue(preg_match('/<\/tbody>/', $html) === 1); } public function testHeaderLabels(): void { // Ensure GridView does not call Model::generateAttributeLabel() to generate labels unless the labels are explicitly used. $this->mockApplication([ 'components' => [ 'db' => [ 'class' => Connection::class, 'dsn' => 'sqlite::memory:', ], ], ]); NoAutoLabels::$db = Yii::$app->getDb(); Yii::$app->getDb()->createCommand()->createTable(NoAutoLabels::tableName(), ['attr1' => 'int', 'attr2' => 'int'])->execute(); $urlManager = new UrlManager([ 'baseUrl' => '/', 'scriptUrl' => '/index.php', ]); $grid = new GridView([ 'dataProvider' => new ActiveDataProvider([ 'query' => NoAutoLabels::find(), ]), 'columns' => [ 'attr1', 'attr2:text:Label for attr2', ], ]); // NoAutoLabels::generateAttributeLabel() should not be called. $grid->dataProvider->setSort([ 'route' => '/', 'urlManager' => $urlManager, ]); $grid->renderTableHeader(); // NoAutoLabels::generateAttributeLabel() should not be called. $grid->dataProvider->setSort([ 'route' => '/', 'urlManager' => $urlManager, 'attributes' => ['attr1', 'attr2'], ]); $grid->renderTableHeader(); // If NoAutoLabels::generateAttributeLabel() has not been called no exception will be thrown meaning this test passed successfully. $this->assertTrue(true); } public function testFilterSelector(): void { $this->mockWebApplication( [ 'components' => [ 'assetManager' => [ 'bundles' => false, ], 'request' => [ 'scriptFile' => __DIR__ . '/baseUrl/index.php', 'scriptUrl' => '/baseUrl/index.php', 'class' => 'yii\web\Request', 'cookieValidationKey' => '123', 'hostInfo' => 'http://example.com/', 'url' => '/base/index.php&r=site%2Fcurrent&id=42', ], 'urlManager' => [ 'class' => 'yii\web\UrlManager', 'baseUrl' => '/base', 'scriptUrl' => '/base/index.php', 'hostInfo' => 'http://example.com/', ], ], ] ); $view = Yii::$app->getView(); // use renderAjax so the javascript gets baked into the HTML $html = $view->renderAjax( '@yiiunit/data/views/widgets/GridView/gridview.php', [ 'options' => [ 'dataProvider' => new ArrayDataProvider(['allModels' => []]), 'id' => 'test_grid_view', 'filterSelector' => 'foobar', ] ] ); $this->assertStringContainsString( '"filterSelector":"#test_grid_view-filters input, #test_grid_view-filters select, foobar"', $html ); $html = $view->renderAjax( '@yiiunit/data/views/widgets/GridView/gridview.php', [ 'options' => [ 'dataProvider' => new ArrayDataProvider(['allModels' => []]), 'id' => 'test_grid_view', 'filterSelector' => 'foobar', 'overrideFilterSelector' => true ] ] ); $this->assertStringNotContainsString( '#test_grid_view-filters input, #test_grid_view-filters select', $html ); $this->assertStringContainsString( '"filterSelector":"foobar"', $html ); $html = $view->renderAjax( '@yiiunit/data/views/widgets/GridView/gridview.php', [ 'options' => [ 'dataProvider' => new ArrayDataProvider(['allModels' => []]), 'id' => 'test_grid_view', 'filterSelector' => static fn($widgetId, $filterId) => "$widgetId foo $filterId bar", ] ] ); $this->assertStringContainsString( '"filterSelector":"#test_grid_view-filters input, #test_grid_view-filters select, test_grid_view foo test_grid_view-filters bar"', $html ); $html = $view->renderAjax( '@yiiunit/data/views/widgets/GridView/gridview.php', [ 'options' => [ 'dataProvider' => new ArrayDataProvider(['allModels' => []]), 'id' => 'test_grid_view', 'filterSelector' => static fn($widgetId, $filterId) => "$widgetId foo $filterId bar", 'overrideFilterSelector' => true ] ] ); $this->assertStringNotContainsString( '#test_grid_view-filters input, #test_grid_view-filters select', $html ); $this->assertStringContainsString( '"filterSelector":"test_grid_view foo test_grid_view-filters bar"', $html ); } }