Initial commit,修正
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\base\DynamicModel;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\bootstrap5\Accordion;
|
||||
use yii\widgets\ActiveForm;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class AccordionTest extends TestCase
|
||||
{
|
||||
public function testRender()
|
||||
{
|
||||
Accordion::$counter = 0;
|
||||
$output = Accordion::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Collapsible Group Item #1',
|
||||
'content' => [
|
||||
'test content1',
|
||||
'test content2'
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => 'Collapsible Group Item #2',
|
||||
'content' => 'Das ist das Haus vom Nikolaus',
|
||||
'contentOptions' => [
|
||||
'class' => 'testContentOptions'
|
||||
],
|
||||
'options' => [
|
||||
'class' => 'testClass',
|
||||
'id' => 'testId'
|
||||
],
|
||||
'footer' => 'Footer'
|
||||
],
|
||||
[
|
||||
'label' => '<h1>Collapsible Group Item #3</h1>',
|
||||
'content' => [
|
||||
'<h2>test content1</h2>',
|
||||
'<h2>test content2</h2>'
|
||||
],
|
||||
'contentOptions' => [
|
||||
'class' => 'testContentOptions2'
|
||||
],
|
||||
'options' => [
|
||||
'class' => 'testClass2',
|
||||
'id' => 'testId2'
|
||||
],
|
||||
'encode' => false,
|
||||
'footer' => 'Footer2'
|
||||
],
|
||||
[
|
||||
'label' => '<h1>Collapsible Group Item #4</h1>',
|
||||
'content' => [
|
||||
'<h2>test content1</h2>',
|
||||
'<h2>test content2</h2>'
|
||||
],
|
||||
'contentOptions' => [
|
||||
'class' => 'testContentOptions3'
|
||||
],
|
||||
'options' => [
|
||||
'class' => 'testClass3',
|
||||
'id' => 'testId3'
|
||||
],
|
||||
'encode' => true,
|
||||
'footer' => 'Footer3'
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEqualsWithoutLE(<<<HTML
|
||||
<div id="w0" class="accordion">
|
||||
<div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Collapsible Group Item #1</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">test content1</li>
|
||||
<li class="list-group-item">test content2</li>
|
||||
</ul>
|
||||
|
||||
</div></div>
|
||||
<div id="testId" class="testClass accordion-item"><div id="w0-collapse1-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w2" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse1" aria-expanded="false" aria-controls="w0-collapse1">Collapsible Group Item #2</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse1" class="testContentOptions collapse" aria-labelledby="w0-collapse1-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body">Das ist das Haus vom Nikolaus</div>
|
||||
|
||||
<div class="accordion-footer">Footer</div>
|
||||
</div></div>
|
||||
<div id="testId2" class="testClass2 accordion-item"><div id="w0-collapse2-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w3" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse2" aria-expanded="false" aria-controls="w0-collapse2"><h1>Collapsible Group Item #3</h1></button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse2" class="testContentOptions2 collapse" aria-labelledby="w0-collapse2-heading" data-bs-parent="#w0">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><h2>test content1</h2></li>
|
||||
<li class="list-group-item"><h2>test content2</h2></li>
|
||||
</ul>
|
||||
|
||||
<div class="accordion-footer">Footer2</div>
|
||||
</div></div>
|
||||
<div id="testId3" class="testClass3 accordion-item"><div id="w0-collapse3-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w4" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse3" aria-expanded="false" aria-controls="w0-collapse3"><h1>Collapsible Group Item #4</h1></button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse3" class="testContentOptions3 collapse" aria-labelledby="w0-collapse3-heading" data-bs-parent="#w0">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><h2>test content1</h2></li>
|
||||
<li class="list-group-item"><h2>test content2</h2></li>
|
||||
</ul>
|
||||
|
||||
<div class="accordion-footer">Footer3</div>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
HTML
|
||||
, $output);
|
||||
}
|
||||
|
||||
public function testLabelKeys()
|
||||
{
|
||||
ob_start();
|
||||
$form = ActiveForm::begin(['action' => '/something']);
|
||||
ActiveForm::end();
|
||||
ob_end_clean();
|
||||
|
||||
Accordion::$counter = 0;
|
||||
$output = Accordion::widget([
|
||||
'items' => [
|
||||
'Item1' => 'Content1',
|
||||
'Item2' => [
|
||||
'content' => 'Content2',
|
||||
],
|
||||
[
|
||||
'label' => 'Item3',
|
||||
'content' => 'Content3',
|
||||
],
|
||||
'FormField' => $form->field(new DynamicModel(['test']), 'test', ['template' => '{input}']),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEqualsWithoutLE(<<<HTML
|
||||
<div id="w0" class="accordion">
|
||||
<div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Item1</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body">Content1</div>
|
||||
|
||||
</div></div>
|
||||
<div class="accordion-item"><div id="w0-collapse1-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w2" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse1" aria-expanded="false" aria-controls="w0-collapse1">Item2</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse1" class="collapse" aria-labelledby="w0-collapse1-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body">Content2</div>
|
||||
|
||||
</div></div>
|
||||
<div class="accordion-item"><div id="w0-collapse2-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w3" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse2" aria-expanded="false" aria-controls="w0-collapse2">Item3</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse2" class="collapse" aria-labelledby="w0-collapse2-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body">Content3</div>
|
||||
|
||||
</div></div>
|
||||
<div class="accordion-item"><div id="w0-collapse3-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w4" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse3" aria-expanded="false" aria-controls="w0-collapse3">FormField</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse3" class="collapse" aria-labelledby="w0-collapse3-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body"><div class="form-group field-dynamicmodel-test">
|
||||
<input type="text" id="dynamicmodel-test" class="form-control" name="DynamicModel[test]">
|
||||
</div></div>
|
||||
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
HTML
|
||||
, $output);
|
||||
}
|
||||
|
||||
public function testExpandOptions()
|
||||
{
|
||||
Accordion::$counter = 0;
|
||||
$output = Accordion::widget([
|
||||
'items' => [
|
||||
'Item1' => 'Content1',
|
||||
'Item2' => [
|
||||
'content' => 'Content2',
|
||||
'expand' => true,
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEqualsWithoutLE(<<<HTML
|
||||
<div id="w0" class="accordion">
|
||||
<div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="false" aria-controls="w0-collapse0">Item1</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse0" class="collapse" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body">Content1</div>
|
||||
|
||||
</div></div>
|
||||
<div class="accordion-item"><div id="w0-collapse1-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w2" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse1" aria-expanded="true" aria-controls="w0-collapse1">Item2</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse1" class="collapse show" aria-labelledby="w0-collapse1-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body">Content2</div>
|
||||
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
HTML
|
||||
, $output);
|
||||
}
|
||||
|
||||
public function invalidItemsProvider()
|
||||
{
|
||||
return [
|
||||
[['content']], // only content without label key
|
||||
[[[]]], // only content array without label
|
||||
[[['content' => 'test']]], // only content array without label
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidItemsProvider
|
||||
* @expectedException \yii\base\InvalidConfigException
|
||||
*/
|
||||
public function testMissingLabel($items)
|
||||
{
|
||||
Accordion::widget([
|
||||
'items' => $items,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2/issues/8357
|
||||
*/
|
||||
public function testRenderObject()
|
||||
{
|
||||
$template = ['template' => '{input}'];
|
||||
ob_start();
|
||||
$form = ActiveForm::begin(['action' => '/something']);
|
||||
ActiveForm::end();
|
||||
ob_end_clean();
|
||||
$model = new data\Singer;
|
||||
|
||||
Accordion::$counter = 0;
|
||||
$output = Accordion::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Collapsible Group Item #1',
|
||||
'content' => $form->field($model, 'firstName', $template)
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEqualsWithoutLE(<<<HTML
|
||||
<div id="w0" class="accordion">
|
||||
<div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Collapsible Group Item #1</button>
|
||||
</h5></div>
|
||||
<div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
|
||||
<div class="accordion-body"><div class="form-group field-singer-firstname">
|
||||
<input type="text" id="singer-firstname" class="form-control" name="Singer[firstName]">
|
||||
</div></div>
|
||||
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
HTML
|
||||
, $output);
|
||||
}
|
||||
|
||||
public function testAutoCloseItems()
|
||||
{
|
||||
$items = [
|
||||
[
|
||||
'label' => 'Item 1',
|
||||
'content' => 'Content 1',
|
||||
],
|
||||
[
|
||||
'label' => 'Item 2',
|
||||
'content' => 'Content 2',
|
||||
],
|
||||
];
|
||||
|
||||
$output = Accordion::widget([
|
||||
'items' => $items
|
||||
]);
|
||||
$this->assertContains('data-bs-parent="', $output);
|
||||
$output = Accordion::widget([
|
||||
'autoCloseItems' => false,
|
||||
'items' => $items
|
||||
]);
|
||||
$this->assertNotContains('data-bs-parent="', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testItemToggleTag()
|
||||
{
|
||||
$items = [
|
||||
[
|
||||
'label' => 'Item 1',
|
||||
'content' => 'Content 1',
|
||||
],
|
||||
[
|
||||
'label' => 'Item 2',
|
||||
'content' => 'Content 2',
|
||||
],
|
||||
];
|
||||
|
||||
Accordion::$counter = 0;
|
||||
|
||||
$output = Accordion::widget([
|
||||
'items' => $items,
|
||||
'itemToggleOptions' => [
|
||||
'tag' => 'a',
|
||||
'class' => 'custom-toggle',
|
||||
],
|
||||
]);
|
||||
$this->assertContains('<h5 class="mb-0"><a type="button" class="custom-toggle" href="#w0-collapse0" ', $output);
|
||||
$this->assertNotContains('<button', $output);
|
||||
|
||||
$output = Accordion::widget([
|
||||
'items' => $items,
|
||||
'itemToggleOptions' => [
|
||||
'tag' => 'a',
|
||||
'class' => ['widget' => 'custom-toggle'],
|
||||
],
|
||||
]);
|
||||
$this->assertContains('<h5 class="mb-0"><a type="button" class="custom-toggle" href="#w1-collapse0" ', $output);
|
||||
$this->assertNotContains('collapse-toggle', $output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use Yii;
|
||||
use yii\base\DynamicModel;
|
||||
use yii\bootstrap5\ActiveField;
|
||||
use yii\bootstrap5\ActiveForm;
|
||||
use yii\bootstrap5\Html;
|
||||
use yii\helpers\UnsetArrayValue;
|
||||
|
||||
class ActiveFieldDefaultFormCheckTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ActiveField
|
||||
*/
|
||||
private $_activeField;
|
||||
/**
|
||||
* @var DynamicModel
|
||||
*/
|
||||
private $_helperModel;
|
||||
/**
|
||||
* @var ActiveForm
|
||||
*/
|
||||
private $_helperForm;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $_attributeName = 'attributeName';
|
||||
|
||||
public function testDefaultCheckboxByConfig()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$this->_activeField->inline = true;
|
||||
$html = $this->_activeField->checkbox()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1">
|
||||
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testDefaultRadioByConfig()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$this->_activeField->inline = true;
|
||||
$html = $this->_activeField->radio()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1">
|
||||
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testDefaultCheckboxListByConfig()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$html = $this->_activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check">
|
||||
<input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testDefaultRadioListByConfig()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$html = $this->_activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check">
|
||||
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testHorizontalLayout()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new DynamicModel(['attributeName', 'checkbox', 'gridRadios']);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_HORIZONTAL
|
||||
]);
|
||||
echo $form->field($model, 'attributeName');
|
||||
echo $form->field($model, 'checkbox')->checkbox(['wrapperOptions' => ['class' => ['widget' => new UnsetArrayValue()]]]);
|
||||
echo $form->field($model, 'gridRadios')->radioList([
|
||||
'option1' => 'First radio',
|
||||
'option2' => 'Second radio',
|
||||
'option3' => 'Third radio'
|
||||
]);
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 row field-dynamicmodel-attributename">
|
||||
<label class="col-sm-2 col-form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
|
||||
<div class="invalid-feedback "></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected2 = <<<HTML
|
||||
<div class="mb-3 row field-dynamicmodel-checkbox">
|
||||
<div class="col-sm-10 offset-sm-2">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[checkbox]" value="0"><input type="checkbox" id="dynamicmodel-checkbox" class="form-check-input" name="DynamicModel[checkbox]" value="1">
|
||||
<label class="form-check-label" for="dynamicmodel-checkbox">Checkbox</label>
|
||||
<div class="invalid-feedback "></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected3 = <<<HTML
|
||||
<div class="mb-3 row field-dynamicmodel-gridradios">
|
||||
<label class="col-sm-2 col-form-label">Grid Radios</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="hidden" name="DynamicModel[gridRadios]" value=""><div id="dynamicmodel-gridradios" role="radiogroup"><div class="form-check">
|
||||
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[gridRadios]" value="option1">
|
||||
<label class="form-check-label" for="i0">First radio</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i1" class="form-check-input" name="DynamicModel[gridRadios]" value="option2">
|
||||
<label class="form-check-label" for="i1">Second radio</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i2" class="form-check-input" name="DynamicModel[gridRadios]" value="option3">
|
||||
<label class="form-check-label" for="i2">Third radio</label>
|
||||
<div class="invalid-feedback "></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
$this->assertContainsWithoutLE($expected2, $out);
|
||||
$this->assertContainsWithoutLE($expected3, $out);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
// dirty way to have Request object not throwing exception when running testHomeLinkNull()
|
||||
$_SERVER['SCRIPT_FILENAME'] = 'index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = 'index.php';
|
||||
|
||||
$this->mockWebApplication([
|
||||
'container' => [
|
||||
'definitions' => [
|
||||
'yii\bootstrap5\ActiveField' => [
|
||||
'checkTemplate' => "<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>",
|
||||
'radioTemplate' => "<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>",
|
||||
'checkHorizontalTemplate' => "{beginWrapper}\n<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}",
|
||||
'radioHorizontalTemplate' => "{beginWrapper}\n<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}",
|
||||
'checkOptions' => [
|
||||
'class' => ['widget' => 'form-check-input'],
|
||||
'labelOptions' => [
|
||||
'class' => ['widget' => 'form-check-label']
|
||||
],
|
||||
'wrapperOptions' => [
|
||||
'class' => ['widget' => 'form-check']
|
||||
]
|
||||
],
|
||||
'radioOptions' => [
|
||||
'class' => ['widget' => 'form-check-input'],
|
||||
'labelOptions' => [
|
||||
'class' => ['widget' => 'form-check-label']
|
||||
],
|
||||
'wrapperOptions' => [
|
||||
'class' => ['widget' => 'form-check']
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->_helperModel = new DynamicModel(['attributeName']);
|
||||
ob_start();
|
||||
$this->_helperForm = ActiveForm::begin(['action' => '/something']);
|
||||
ActiveForm::end();
|
||||
ob_end_clean();
|
||||
|
||||
$this->_activeField = Yii::createObject([
|
||||
'class' => 'yii\bootstrap5\ActiveField',
|
||||
'form' => $this->_helperForm
|
||||
]);
|
||||
$this->_activeField->model = $this->_helperModel;
|
||||
$this->_activeField->attribute = $this->_attributeName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\base\DynamicModel;
|
||||
use yii\bootstrap5\ActiveField;
|
||||
use yii\bootstrap5\ActiveForm;
|
||||
use yii\bootstrap5\Html;
|
||||
|
||||
class ActiveFieldTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ActiveField
|
||||
*/
|
||||
private $activeField;
|
||||
/**
|
||||
* @var DynamicModel
|
||||
*/
|
||||
private $helperModel;
|
||||
/**
|
||||
* @var ActiveForm
|
||||
*/
|
||||
private $helperForm;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $attributeName = 'attributeName';
|
||||
|
||||
public function testFileInput()
|
||||
{
|
||||
$html = $this->activeField->fileInput()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><input type="file" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testRangeInput()
|
||||
{
|
||||
$html = $this->activeField->rangeInput()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<input type="range" id="dynamicmodel-attributename" class="form-range" name="DynamicModel[attributeName]">
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testColorInput()
|
||||
{
|
||||
$html = $this->activeField->colorInput()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<input type="color" id="dynamicmodel-attributename" class="form-control form-control-color" name="DynamicModel[attributeName]">
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testRadioList()
|
||||
{
|
||||
$html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check">
|
||||
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
// Tests :
|
||||
|
||||
public function testRadioError()
|
||||
{
|
||||
$this->helperModel->addError($this->attributeName, 'Test print error message');
|
||||
$html = $this->activeField->radio()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="form-check-input is-invalid" name="DynamicModel[attributeName]" value="1" aria-invalid="true">
|
||||
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="invalid-feedback">Test print error message</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testRadioListError()
|
||||
{
|
||||
$this->helperModel->addError($this->attributeName, 'Test print error message');
|
||||
$html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" class="is-invalid" role="radiogroup" aria-invalid="true"><div class="form-check">
|
||||
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback">Test print error message</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testCheckboxList()
|
||||
{
|
||||
$html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check">
|
||||
<input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test checkbox
|
||||
*/
|
||||
public function testCheckboxSwitch()
|
||||
{
|
||||
$html = $this->activeField->checkbox(['switch' => true])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<div class="form-check form-switch">
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1" role="switch">
|
||||
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testCheckboxError()
|
||||
{
|
||||
$this->helperModel->addError($this->attributeName, 'Test print error message');
|
||||
$html = $this->activeField->checkbox()->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="form-check-input is-invalid" name="DynamicModel[attributeName]" value="1" aria-invalid="true">
|
||||
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="invalid-feedback">Test print error message</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testCheckboxListError()
|
||||
{
|
||||
$this->helperModel->addError($this->attributeName, 'Test print error message');
|
||||
$html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" class="is-invalid" aria-invalid="true"><div class="form-check">
|
||||
<input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback">Test print error message</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testRadioListInline()
|
||||
{
|
||||
$this->activeField->inline = true;
|
||||
$html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check form-check-inline">
|
||||
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-check-inline">
|
||||
<input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testCheckboxListInline()
|
||||
{
|
||||
$this->activeField->inline = true;
|
||||
$html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label">Attribute Name</label>
|
||||
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check form-check-inline">
|
||||
<input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
|
||||
<label class="form-check-label" for="i0">name1</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-check-inline">
|
||||
<input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
|
||||
<label class="form-check-label" for="i1">name2</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/81
|
||||
*/
|
||||
public function testRadioListItemOptions()
|
||||
{
|
||||
$content = $this->activeField->radioList([1 => 'name1', 2 => 'name2'], [
|
||||
'itemOptions' => [
|
||||
'data-attribute' => 'test'
|
||||
]
|
||||
])->render();
|
||||
|
||||
$this->assertContains('data-attribute="test"', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/81
|
||||
*/
|
||||
public function testCheckboxListItemOptions()
|
||||
{
|
||||
$content = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'], [
|
||||
'itemOptions' => [
|
||||
'data-attribute' => 'test'
|
||||
]
|
||||
])->render();
|
||||
|
||||
$this->assertContains('data-attribute="test"', $content);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
// dirty way to have Request object not throwing exception when running testHomeLinkNull()
|
||||
$_SERVER['SCRIPT_FILENAME'] = "index.php";
|
||||
$_SERVER['SCRIPT_NAME'] = "index.php";
|
||||
parent::setUp();
|
||||
|
||||
Html::$counter = 0;
|
||||
|
||||
$this->helperModel = new DynamicModel(['attributeName']);
|
||||
ob_start();
|
||||
$this->helperForm = ActiveForm::begin(['action' => '/something']);
|
||||
ActiveForm::end();
|
||||
ob_end_clean();
|
||||
|
||||
$this->activeField = new ActiveField(['form' => $this->helperForm]);
|
||||
$this->activeField->model = $this->helperModel;
|
||||
$this->activeField->attribute = $this->attributeName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\base\DynamicModel;
|
||||
use yii\bootstrap5\ActiveForm;
|
||||
use yii\bootstrap5\Html;
|
||||
use yiiunit\extensions\bootstrap5\data\User;
|
||||
|
||||
/**
|
||||
* Tests for ActiveForm widget
|
||||
*
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ActiveFormTest extends TestCase
|
||||
{
|
||||
|
||||
public function testDefaultLayout()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new DynamicModel(['attributeName', 'radios']);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_DEFAULT
|
||||
]);
|
||||
echo $form->field($model, 'attributeName');
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testHorizontalLayout()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new DynamicModel(['attributeName', 'checkbox', 'gridRadios']);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_HORIZONTAL
|
||||
]);
|
||||
echo $form->field($model, 'attributeName');
|
||||
echo $form->field($model, 'checkbox')->checkbox();
|
||||
echo $form->field($model, 'gridRadios')->radioList([
|
||||
'option1' => 'First radio',
|
||||
'option2' => 'Second radio',
|
||||
'option3' => 'Third radio'
|
||||
]);
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 row field-dynamicmodel-attributename">
|
||||
<label class="col-sm-2 col-form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
|
||||
<div class="invalid-feedback "></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected2 = <<<HTML
|
||||
<div class="mb-3 row field-dynamicmodel-checkbox">
|
||||
<div class="col-sm-10 offset-sm-2">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[checkbox]" value="0"><input type="checkbox" id="dynamicmodel-checkbox" class="form-check-input" name="DynamicModel[checkbox]" value="1">
|
||||
<label class="form-check-label" for="dynamicmodel-checkbox">Checkbox</label>
|
||||
<div class="invalid-feedback "></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected3 = <<<HTML
|
||||
<div class="mb-3 row field-dynamicmodel-gridradios">
|
||||
<label class="col-sm-2 col-form-label">Grid Radios</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="hidden" name="DynamicModel[gridRadios]" value=""><div id="dynamicmodel-gridradios" role="radiogroup"><div class="form-check">
|
||||
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[gridRadios]" value="option1">
|
||||
<label class="form-check-label" for="i0">First radio</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i1" class="form-check-input" name="DynamicModel[gridRadios]" value="option2">
|
||||
<label class="form-check-label" for="i1">Second radio</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="radio" id="i2" class="form-check-input" name="DynamicModel[gridRadios]" value="option3">
|
||||
<label class="form-check-label" for="i2">Third radio</label>
|
||||
<div class="invalid-feedback "></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
$this->assertContainsWithoutLE($expected2, $out);
|
||||
$this->assertContainsWithoutLE($expected3, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testHorizontalLayoutTemplateOverride()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new DynamicModel(['checkboxName']);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_HORIZONTAL
|
||||
]);
|
||||
echo $form->field($model, 'checkboxName')->checkbox(['template' => "<div class=\"form-check offset-lg-1 col-lg-3\">\n{input}\n{label}\n</div>\n<div class=\"col-lg-8\">{error}</div>"]);
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="form-check offset-lg-1 col-lg-3">
|
||||
<input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="form-check-input" name="DynamicModel[checkboxName]" value="1">
|
||||
<label class="form-check-label" for="dynamicmodel-checkboxname">Checkbox Name</label>
|
||||
</div>
|
||||
<div class="col-lg-8"><div class="invalid-feedback "></div></div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testInlineLayout()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new DynamicModel(['attributeName', 'selectName', 'checkboxName']);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_INLINE
|
||||
]);
|
||||
echo $form->field($model, 'attributeName');
|
||||
echo $form->field($model, 'selectName')->listBox([
|
||||
'1' => 'One',
|
||||
'2' => 'Two',
|
||||
'3' => 'Three'
|
||||
]);
|
||||
echo $form->field($model, 'checkboxName')->checkbox();
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-attributename">
|
||||
<label class="form-label visually-hidden" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]" placeholder="Attribute Name">
|
||||
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$expected2 = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-selectname">
|
||||
<label class="form-label" for="dynamicmodel-selectname">Select Name</label>
|
||||
<input type="hidden" name="DynamicModel[selectName]" value=""><select id="dynamicmodel-selectname" class="form-select" name="DynamicModel[selectName]" size="4" placeholder>
|
||||
<option value="1">One</option>
|
||||
<option value="2">Two</option>
|
||||
<option value="3">Three</option>
|
||||
</select>
|
||||
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$expected3 = <<<HTML
|
||||
<div class="mb-3 field-dynamicmodel-checkboxname">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="form-check-input" name="DynamicModel[checkboxName]" value="1">
|
||||
<label class="visually-hidden form-check-label" for="dynamicmodel-checkboxname">Checkbox Name</label>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE('<form id="w0" class="form-inline"', $out);
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
$this->assertContainsWithoutLE($expected2, $out);
|
||||
$this->assertContainsWithoutLE($expected3, $out);
|
||||
}
|
||||
|
||||
public function testFloatingLayout()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new DynamicModel(['attributeName', 'selectName', 'checkboxName']);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_FLOATING
|
||||
]);
|
||||
echo $form->field($model, 'attributeName');
|
||||
echo $form->field($model, 'selectName')->listBox([
|
||||
'1' => 'One',
|
||||
'2' => 'Two',
|
||||
'3' => 'Three'
|
||||
]);
|
||||
echo $form->field($model, 'checkboxName')->checkbox();
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="form-floating mt-3 field-dynamicmodel-attributename">
|
||||
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]" placeholder="Attribute Name">
|
||||
<label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$expected2 = <<<HTML
|
||||
<div class="form-floating mt-3 field-dynamicmodel-selectname">
|
||||
<input type="hidden" name="DynamicModel[selectName]" value=""><select id="dynamicmodel-selectname" class="form-select" name="DynamicModel[selectName]" size="4" placeholder>
|
||||
<option value="1">One</option>
|
||||
<option value="2">Two</option>
|
||||
<option value="3">Three</option>
|
||||
</select>
|
||||
<label class="form-label" for="dynamicmodel-selectname">Select Name</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$expected3 = <<<HTML
|
||||
<div class="form-floating mt-3 field-dynamicmodel-checkboxname">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="form-check-input" name="DynamicModel[checkboxName]" value="1">
|
||||
<label class="form-check-label" for="dynamicmodel-checkboxname">Checkbox Name</label>
|
||||
<div class="invalid-feedback"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE('<form id="w0"', $out);
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
$this->assertContainsWithoutLE($expected2, $out);
|
||||
$this->assertContainsWithoutLE($expected3, $out);
|
||||
}
|
||||
|
||||
public function testHintRendering()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new User();
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_DEFAULT
|
||||
]);
|
||||
echo $form->field($model, 'firstName');
|
||||
echo $form->field($model, 'lastName');
|
||||
echo $form->field($model, 'username');
|
||||
echo $form->field($model, 'password')->passwordInput();
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 field-user-firstname">
|
||||
<label class="form-label" for="user-firstname">First Name</label>
|
||||
<input type="text" id="user-firstname" class="form-control" name="User[firstName]">
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected2 = <<<HTML
|
||||
<div class="mb-3 field-user-lastname">
|
||||
<label class="form-label" for="user-lastname">Last Name</label>
|
||||
<input type="text" id="user-lastname" class="form-control" name="User[lastName]">
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected3 = <<<HTML
|
||||
<div class="mb-3 field-user-username required">
|
||||
<label class="form-label" for="user-username">Username</label>
|
||||
<input type="text" id="user-username" class="form-control" name="User[username]" aria-required="true">
|
||||
<div class="form-text text-muted">Your username must be at least 4 characters long</div>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected4 = <<<HTML
|
||||
<div class="mb-3 field-user-password required">
|
||||
<label class="form-label" for="user-password">Password</label>
|
||||
<input type="password" id="user-password" class="form-control" name="User[password]" aria-required="true">
|
||||
<div class="form-text text-muted">Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.</div>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
$this->assertContainsWithoutLE($expected2, $out);
|
||||
$this->assertContainsWithoutLE($expected3, $out);
|
||||
$this->assertContainsWithoutLE($expected4, $out);
|
||||
}
|
||||
|
||||
public function testStaticControlRendering()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new User();
|
||||
$model->setAttributes([
|
||||
'id' => 1,
|
||||
'firstName' => 'John',
|
||||
'lastName' => 'Doe'
|
||||
]);
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_DEFAULT
|
||||
]);
|
||||
echo $form->field($model, 'id')->staticControl();
|
||||
echo $form->field($model, 'firstName')->staticControl();
|
||||
echo $form->field($model, 'lastName')->staticControl();
|
||||
echo $form->field($model, 'username')->staticControl();
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 field-user-id">
|
||||
<label class="form-label" for="user-id">Id</label>
|
||||
<input type="text" class="form-control-plaintext" value="1" readonly>
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$expected2 = <<<HTML
|
||||
<div class="mb-3 field-user-firstname">
|
||||
<label class="form-label" for="user-firstname">First Name</label>
|
||||
<input type="text" class="form-control-plaintext" value="John" readonly>
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
$expected3 = <<<HTML
|
||||
<div class="mb-3 field-user-lastname">
|
||||
<label class="form-label" for="user-lastname">Last Name</label>
|
||||
<input type="text" class="form-control-plaintext" value="Doe" readonly>
|
||||
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
$this->assertContainsWithoutLE($expected2, $out);
|
||||
$this->assertContainsWithoutLE($expected3, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes #128
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/128
|
||||
*/
|
||||
public function testInputTemplate()
|
||||
{
|
||||
$model = new User();
|
||||
$model->validate();
|
||||
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$form = ActiveForm::begin();
|
||||
echo $form->field($model, 'username', ['inputTemplate' => '{input}']);
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div class="mb-3 field-user-username required">
|
||||
<label class="form-label" for="user-username">Username</label>
|
||||
<input type="text" id="user-username" class="form-control is-invalid" name="User[username]" aria-required="true" aria-invalid="true">
|
||||
<div class="form-text text-muted">Your username must be at least 4 characters long</div>
|
||||
<div class="invalid-feedback">Username cannot be blank.</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertContainsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes #196
|
||||
*/
|
||||
public function testFormNoRoleAttribute()
|
||||
{
|
||||
$form = ActiveForm::widget();
|
||||
|
||||
$this->assertNotContains('role="form"', $form);
|
||||
}
|
||||
|
||||
public function testErrorSummaryRendering()
|
||||
{
|
||||
ActiveForm::$counter = 0;
|
||||
ob_start();
|
||||
$model = new User();
|
||||
$model->validate();
|
||||
$form = ActiveForm::begin([
|
||||
'action' => '/some-action',
|
||||
'layout' => ActiveForm::LAYOUT_DEFAULT
|
||||
]);
|
||||
echo $form->errorSummary($model);
|
||||
ActiveForm::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
|
||||
$this->assertContainsWithoutLE('<div class="alert alert-danger"', $out);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
// dirty way to have Request object not throwing exception when running testFormNoRoleAttribute()
|
||||
$_SERVER['REQUEST_URI'] = "index.php";
|
||||
|
||||
parent::setUp();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Alert;
|
||||
|
||||
/**
|
||||
* Tests for Alert widget
|
||||
*
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class AlertTest extends TestCase
|
||||
{
|
||||
public function testNormalAlert()
|
||||
{
|
||||
Alert::$counter = 0;
|
||||
$html = Alert::widget([
|
||||
'body' => '<strong>Holy guacamole!</strong> You should check in on some of those fields below.',
|
||||
'options' => [
|
||||
'class' => ['alert-warning']
|
||||
]
|
||||
]);
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div id="w0" class="alert-warning alert alert-dismissible" role="alert">
|
||||
|
||||
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testDismissibleAlert()
|
||||
{
|
||||
Alert::$counter = 0;
|
||||
$html = Alert::widget([
|
||||
'body' => "Message1",
|
||||
]);
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div id="w0" class="alert alert-dismissible" role="alert">
|
||||
|
||||
Message1
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/11
|
||||
*/
|
||||
public function testDismissibleAlertCustomButton()
|
||||
{
|
||||
Alert::$counter = 0;
|
||||
$html = Alert::widget([
|
||||
'body' => "Low Blow: Bob Loblaw's Law Blog Lobs Law Bomb",
|
||||
'options' => ['class' => 'alert-warning'],
|
||||
'closeButton' => [
|
||||
'label' => 'Dismiss',
|
||||
'tag' => 'a',
|
||||
'class' => ['widget' => 'btn btn-outline-warning'],
|
||||
'style' => [
|
||||
'position' => 'absolute',
|
||||
'top' => '.5rem',
|
||||
'right' => '.5rem'
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div id="w0" class="alert-warning alert alert-dismissible" role="alert">
|
||||
|
||||
Low Blow: Bob Loblaw's Law Blog Lobs Law Bomb
|
||||
<a class="btn btn-outline-warning" data-bs-dismiss="alert" aria-label="Close" style="position: absolute; top: .5rem; right: .5rem;">Dismiss</a>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Breadcrumbs;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class BreadcrumbsTest extends TestCase
|
||||
{
|
||||
public function testRender()
|
||||
{
|
||||
Breadcrumbs::$counter = 0;
|
||||
$out = Breadcrumbs::widget([
|
||||
'homeLink' => ['label' => 'Home', 'url' => '#'],
|
||||
'links' => [
|
||||
['label' => 'Library', 'url' => '#'],
|
||||
['label' => 'Data']
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<nav aria-label="breadcrumb"><ol id="w0" class="breadcrumb"><li class="breadcrumb-item"><a href="#">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="#">Library</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Data</li>
|
||||
</ol></nav>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testRenderWithoutHomeLink()
|
||||
{
|
||||
Breadcrumbs::$counter = 0;
|
||||
$out = Breadcrumbs::widget([
|
||||
'homeLink' => false,
|
||||
'links' => [
|
||||
['label' => 'Library', 'url' => '#'],
|
||||
['label' => 'Data']
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<nav aria-label="breadcrumb"><ol id="w0" class="breadcrumb"><li class="breadcrumb-item"><a href="#">Library</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Data</li>
|
||||
</ol></nav>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\ButtonDropdown;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ButtonDropdownTest extends TestCase
|
||||
{
|
||||
public function testContainerOptions()
|
||||
{
|
||||
$containerClass = 'testClass';
|
||||
|
||||
ButtonDropdown::$counter = 0;
|
||||
$out = ButtonDropdown::widget([
|
||||
'direction' => ButtonDropdown::DIRECTION_UP,
|
||||
'options' => [
|
||||
'class' => $containerClass,
|
||||
],
|
||||
'label' => 'Action',
|
||||
'dropdown' => [
|
||||
'items' => [
|
||||
['label' => 'DropdownA', 'url' => '/'],
|
||||
['label' => 'DropdownB', 'url' => '#'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertContains("$containerClass dropup btn-group", $out);
|
||||
}
|
||||
|
||||
public function testDirection()
|
||||
{
|
||||
ButtonDropdown::$counter = 0;
|
||||
$out = ButtonDropdown::widget([
|
||||
'direction' => ButtonDropdown::DIRECTION_LEFT,
|
||||
'label' => 'Action',
|
||||
'dropdown' => [
|
||||
'items' => [
|
||||
['label' => 'ItemA', 'url' => '#'],
|
||||
['label' => 'ItemB', 'url' => '#'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<div id="w0" class="dropleft btn-group"><button id="w0-button" class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Action</button>
|
||||
|
||||
<div id="w1" class="dropdown-menu"><a class="dropdown-item" href="#">ItemA</a>
|
||||
<a class="dropdown-item" href="#">ItemB</a></div></div>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testSplit()
|
||||
{
|
||||
ButtonDropdown::$counter = 0;
|
||||
$out = ButtonDropdown::widget([
|
||||
'direction' => ButtonDropdown::DIRECTION_DOWN,
|
||||
'label' => 'Split dropdown',
|
||||
'split' => true,
|
||||
'dropdown' => [
|
||||
'items' => [
|
||||
['label' => 'ItemA', 'url' => '#'],
|
||||
['label' => 'ItemB', 'url' => '#']
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<div id="w0" class="dropdown btn-group"><button id="w1" class="btn">Split dropdown</button>
|
||||
<button id="w0-button" class="btn dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>
|
||||
<div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">ItemA</a>
|
||||
<a class="dropdown-item" href="#">ItemB</a></div></div>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Button;
|
||||
use yii\bootstrap5\ButtonGroup;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ButtonGroupTest extends TestCase
|
||||
{
|
||||
public function testContainerOptions()
|
||||
{
|
||||
ButtonGroup::$counter = 0;
|
||||
$out = ButtonGroup::widget([
|
||||
'buttons' => [
|
||||
['label' => 'button-A'],
|
||||
['label' => 'button-B', 'visible' => true],
|
||||
['label' => 'button-C', 'visible' => false],
|
||||
Button::widget(['label' => 'button-D']),
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w1" class="btn-group" role="group"><button type="button" id="w2" class="btn">button-A</button>
|
||||
<button type="button" id="w3" class="btn">button-B</button>
|
||||
<button id="w0" class="btn">button-D</button></div>
|
||||
HTML;
|
||||
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
|
||||
use yii\bootstrap5\ButtonGroup;
|
||||
use yii\bootstrap5\ButtonToolbar;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ButtonToolbarTest extends TestCase
|
||||
{
|
||||
public function testContainerOptions()
|
||||
{
|
||||
ButtonToolbar::$counter = 0;
|
||||
$out = ButtonToolbar::widget([
|
||||
'options' => [
|
||||
'aria-label' => 'Toolbar with button groups'
|
||||
],
|
||||
'buttonGroups' => [
|
||||
ButtonGroup::widget([
|
||||
'options' => [
|
||||
'aria-label' => 'First group',
|
||||
'class' => ['mr-2']
|
||||
],
|
||||
'buttons' => [
|
||||
['label' => '1'],
|
||||
['label' => '2'],
|
||||
['label' => '3'],
|
||||
['label' => '4']
|
||||
]
|
||||
]),
|
||||
[
|
||||
'options' => [
|
||||
'aria-label' => 'Second group'
|
||||
],
|
||||
'buttons' => [
|
||||
['label' => '5'],
|
||||
['label' => '6'],
|
||||
['label' => '7']
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w5" class="btn-toolbar" aria-label="Toolbar with button groups" role="toolbar"><div id="w0" class="mr-2 btn-group" aria-label="First group" role="group"><button type="button" id="w1" class="btn">1</button>
|
||||
<button type="button" id="w2" class="btn">2</button>
|
||||
<button type="button" id="w3" class="btn">3</button>
|
||||
<button type="button" id="w4" class="btn">4</button></div>
|
||||
<div id="w6" class="btn-group" aria-label="Second group" role="group"><button type="button" id="w7" class="btn">5</button>
|
||||
<button type="button" id="w8" class="btn">6</button>
|
||||
<button type="button" id="w9" class="btn">7</button></div></div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testAdditionalContent()
|
||||
{
|
||||
ButtonToolbar::$counter = 0;
|
||||
$addHtml = <<<HTML
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text" id="btnGroupAddon">@</div>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="Input group example" aria-label="Input group example" aria-describedby="btnGroupAddon">
|
||||
</div>
|
||||
HTML;
|
||||
$out = ButtonToolbar::widget([
|
||||
'options' => [
|
||||
'aria-label' => 'Toolbar with button groups'
|
||||
],
|
||||
'buttonGroups' => [
|
||||
[
|
||||
'options' => [
|
||||
'aria-label' => 'First group',
|
||||
'class' => ['mr-2']
|
||||
],
|
||||
'buttons' => [
|
||||
['label' => '1'],
|
||||
['label' => '2'],
|
||||
['label' => '3'],
|
||||
['label' => '4']
|
||||
]
|
||||
],
|
||||
$addHtml
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="btn-toolbar" aria-label="Toolbar with button groups" role="toolbar"><div id="w1" class="mr-2 btn-group" aria-label="First group" role="group"><button type="button" id="w2" class="btn">1</button>
|
||||
<button type="button" id="w3" class="btn">2</button>
|
||||
<button type="button" id="w4" class="btn">3</button>
|
||||
<button type="button" id="w5" class="btn">4</button></div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text" id="btnGroupAddon">@</div>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="Input group example" aria-label="Input group example" aria-describedby="btnGroupAddon">
|
||||
</div></div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
|
||||
use yii\bootstrap5\Carousel;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class CarouselTest extends TestCase
|
||||
{
|
||||
function testContainerOptions()
|
||||
{
|
||||
Carousel::$counter = 0;
|
||||
$out = Carousel::widget([
|
||||
'items' => [
|
||||
[
|
||||
'content' => '<img src="https://via.placeholder.com/800x400?text=First+slide" class="d-block w-100">',
|
||||
'caption' => '<h5>First slide label</h5><p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>',
|
||||
'captionOptions' => [
|
||||
'class' => ['d-none', 'd-md-block']
|
||||
]
|
||||
],
|
||||
[
|
||||
'content' => '<img src="https://via.placeholder.com/800x400?text=Second+slide" class="d-block w-100">',
|
||||
'caption' => '<h5>Second slide label</h5><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>',
|
||||
'captionOptions' => [
|
||||
'class' => ['d-none', 'd-md-block']
|
||||
]
|
||||
],
|
||||
[
|
||||
'content' => '<img src="https://via.placeholder.com/800x400?text=Third+slide" class="d-block w-100">',
|
||||
'caption' => '<h5>Third slide label</h5><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>',
|
||||
'captionOptions' => [
|
||||
'class' => ['d-none', 'd-md-block']
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="carousel slide" data-bs-ride="carousel">
|
||||
<div class="carousel-indicators"><button type="button" class="active" data-bs-target="#w0" data-bs-slide-to="0" aria-current="true"></button>
|
||||
<button type="button" data-bs-target="#w0" data-bs-slide-to="1"></button>
|
||||
<button type="button" data-bs-target="#w0" data-bs-slide-to="2"></button></div>
|
||||
<div class="carousel-inner"><div class="carousel-item active"><img src="https://via.placeholder.com/800x400?text=First+slide" class="d-block w-100">
|
||||
<div class="d-none d-md-block carousel-caption"><h5>First slide label</h5><p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p></div></div>
|
||||
<div class="carousel-item"><img src="https://via.placeholder.com/800x400?text=Second+slide" class="d-block w-100">
|
||||
<div class="d-none d-md-block carousel-caption"><h5>Second slide label</h5><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p></div></div>
|
||||
<div class="carousel-item"><img src="https://via.placeholder.com/800x400?text=Third+slide" class="d-block w-100">
|
||||
<div class="d-none d-md-block carousel-caption"><h5>Third slide label</h5><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p></div></div></div>
|
||||
<button type="button" class="carousel-control-prev" data-bs-target="#w0" data-bs-slide="prev"><span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span></button>
|
||||
<button type="button" class="carousel-control-next" data-bs-target="#w0" data-bs-slide="next"><span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span></button>
|
||||
</div>
|
||||
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testCrossfade()
|
||||
{
|
||||
Carousel::$counter = 0;
|
||||
$out = Carousel::widget([
|
||||
'crossfade' => true,
|
||||
'items' => [
|
||||
[
|
||||
'content' => '<img src="https://via.placeholder.com/800x400?text=First+slide" class="d-block w-100">',
|
||||
'caption' => '<h5>First slide label</h5><p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p>',
|
||||
'captionOptions' => [
|
||||
'class' => ['d-none', 'd-md-block']
|
||||
]
|
||||
],
|
||||
[
|
||||
'content' => '<img src="https://via.placeholder.com/800x400?text=Second+slide" class="d-block w-100">',
|
||||
'caption' => '<h5>Second slide label</h5><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>',
|
||||
'captionOptions' => [
|
||||
'class' => ['d-none', 'd-md-block']
|
||||
]
|
||||
],
|
||||
[
|
||||
'content' => '<img src="https://via.placeholder.com/800x400?text=Third+slide" class="d-block w-100">',
|
||||
'caption' => '<h5>Third slide label</h5><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p>',
|
||||
'captionOptions' => [
|
||||
'class' => ['d-none', 'd-md-block']
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertContains('class="carousel slide carousel-fade"', $out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Dropdown;
|
||||
|
||||
/**
|
||||
* Tests for Dropdown widget
|
||||
*
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class DropdownTest extends TestCase
|
||||
{
|
||||
public function testIds()
|
||||
{
|
||||
Dropdown::$counter = 0;
|
||||
$out = Dropdown::widget(
|
||||
[
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1'
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'url' => '#test',
|
||||
'items' => [
|
||||
['label' => 'Page2'],
|
||||
['label' => 'Page3'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'visible' => false,
|
||||
'items' => [
|
||||
['label' => 'Page4', 'content' => 'Page4'],
|
||||
['label' => 'Page5', 'content' => 'Page5'],
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<div id="w0" class="dropdown-menu"><h6 class="dropdown-header">Page1</h6>
|
||||
<div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" href="#test" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown1</a>
|
||||
<div id="w1" class="dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page2</h6>
|
||||
<h6 class="dropdown-header">Page3</h6></div>
|
||||
</div></div>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testSubMenuOptions()
|
||||
{
|
||||
Dropdown::$counter = 0;
|
||||
$out = Dropdown::widget(
|
||||
[
|
||||
'submenuOptions' => [
|
||||
'class' => 'submenu-list',
|
||||
],
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page1', 'content' => 'Page2'],
|
||||
['label' => 'Page2', 'content' => 'Page3'],
|
||||
]
|
||||
],
|
||||
'-',
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'items' => [
|
||||
['label' => 'Page3', 'content' => 'Page4'],
|
||||
['label' => 'Page4', 'content' => 'Page5'],
|
||||
],
|
||||
'submenuOptions' => [
|
||||
'class' => 'submenu-override',
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown1</a>
|
||||
<div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6>
|
||||
<h6 class="dropdown-header">Page2</h6></div>
|
||||
</div>
|
||||
<hr class="dropdown-divider">
|
||||
<div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown2</a>
|
||||
<div id="w2" class="submenu-override dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page3</h6>
|
||||
<h6 class="dropdown-header">Page4</h6></div>
|
||||
</div></div>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testActive()
|
||||
{
|
||||
Dropdown::$counter = 0;
|
||||
$out = Dropdown::widget(
|
||||
[
|
||||
'submenuOptions' => [
|
||||
'class' => 'submenu-list',
|
||||
],
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page1', 'content' => 'Page2'],
|
||||
['label' => 'Page2', 'content' => 'Page3'],
|
||||
]
|
||||
],
|
||||
'-',
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'items' => [
|
||||
['label' => 'Page3', 'content' => 'Page3', 'url' => '/', 'active' => true],
|
||||
['label' => 'Page4', 'content' => 'Page4'],
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown1</a>
|
||||
<div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6>
|
||||
<h6 class="dropdown-header">Page2</h6></div>
|
||||
</div>
|
||||
<hr class="dropdown-divider">
|
||||
<div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown2</a>
|
||||
<div id="w2" class="submenu-list dropdown-submenu dropdown-menu"><a class="dropdown-item active" href="/" aria-current="true">Page3</a>
|
||||
<h6 class="dropdown-header">Page4</h6></div>
|
||||
</div></div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testDisabled()
|
||||
{
|
||||
Dropdown::$counter = 0;
|
||||
$out = Dropdown::widget(
|
||||
[
|
||||
'submenuOptions' => [
|
||||
'class' => 'submenu-list',
|
||||
],
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page1', 'content' => 'Page2'],
|
||||
['label' => 'Page2', 'content' => 'Page3'],
|
||||
],
|
||||
'disabled' => true
|
||||
],
|
||||
'-',
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'items' => [
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
['label' => 'Page4', 'content' => 'Page4'],
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item disabled dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" aria-disabled="true" role="button" tabindex="-1">Dropdown1</a>
|
||||
<div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6>
|
||||
<h6 class="dropdown-header">Page2</h6></div>
|
||||
</div>
|
||||
<hr class="dropdown-divider">
|
||||
<div class="dropdown" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown2</a>
|
||||
<div id="w2" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page3</h6>
|
||||
<h6 class="dropdown-header">Page4</h6></div>
|
||||
</div></div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testForms()
|
||||
{
|
||||
Dropdown::$counter = 0;
|
||||
$form = <<<HTML
|
||||
<form class="px-4 py-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="exampleDropdownFormEmail1">Email address</label>
|
||||
<input type="email" class="form-control" id="exampleDropdownFormEmail1" placeholder="email@example.com">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="exampleDropdownFormPassword1">Password</label>
|
||||
<input type="password" class="form-control" id="exampleDropdownFormPassword1" placeholder="Password">
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="dropdownCheck">
|
||||
<label class="form-check-label" for="dropdownCheck">
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Sign in</button>
|
||||
</form>
|
||||
HTML;
|
||||
|
||||
$out = Dropdown::widget([
|
||||
'items' => [
|
||||
$form,
|
||||
'-',
|
||||
['label' => 'New around here? Sign up', 'url' => '#'],
|
||||
['label' => 'Forgot password?', 'url' => '#']
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="dropdown-menu"><form class="px-4 py-3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="exampleDropdownFormEmail1">Email address</label>
|
||||
<input type="email" class="form-control" id="exampleDropdownFormEmail1" placeholder="email@example.com">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="exampleDropdownFormPassword1">Password</label>
|
||||
<input type="password" class="form-control" id="exampleDropdownFormPassword1" placeholder="Password">
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="dropdownCheck">
|
||||
<label class="form-check-label" for="dropdownCheck">
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Sign in</button>
|
||||
</form>
|
||||
<hr class="dropdown-divider">
|
||||
<a class="dropdown-item" href="#">New around here? Sign up</a>
|
||||
<a class="dropdown-item" href="#">Forgot password?</a></div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\base\DynamicModel;
|
||||
use yii\bootstrap5\Html;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class HtmlTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function dataProviderStaticControl()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'foo',
|
||||
[],
|
||||
'<input type="text" class="form-control-plaintext" value="foo" readonly>'
|
||||
],
|
||||
[
|
||||
'<html>',
|
||||
[],
|
||||
'<input type="text" class="form-control-plaintext" value="<html>" readonly>'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderStaticControl
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $options
|
||||
* @param string $expectedHtml
|
||||
*/
|
||||
public function testStaticControl($value, array $options, $expectedHtml)
|
||||
{
|
||||
$this->assertEquals($expectedHtml, Html::staticControl($value, $options));
|
||||
}
|
||||
|
||||
public function testRadioList()
|
||||
{
|
||||
$this->assertEquals('<div></div>', Html::radioList('test'));
|
||||
|
||||
$dataItems = [
|
||||
'value1' => 'text1',
|
||||
'value2' => 'text2',
|
||||
];
|
||||
|
||||
Html::$counter = 0;
|
||||
|
||||
$expected = <<<'EOD'
|
||||
<div><div class="form-check"><input type="radio" id="i0" class="form-check-input" name="test" value="value1">
|
||||
<label class="form-check-label" for="i0">text1</label></div>
|
||||
<div class="form-check"><input type="radio" id="i1" class="form-check-input" name="test" value="value2" checked>
|
||||
<label class="form-check-label" for="i1">text2</label></div></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::radioList('test', ['value2'], $dataItems));
|
||||
|
||||
Html::$counter = 0;
|
||||
$expected = <<<'EOD'
|
||||
<div>0<label>text1 <input type="radio" name="test" value="value1"></label>
|
||||
1<label>text2 <input type="radio" name="test" value="value2" checked></label></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::radioList('test', ['value2'], $dataItems, [
|
||||
'item' => function ($index, $label, $name, $checked, $value) {
|
||||
return $index . Html::label($label . ' ' . Html::radio($name, $checked, ['value' => $value]));
|
||||
},
|
||||
]));
|
||||
|
||||
Html::$counter = 0;
|
||||
$expected = <<<'EOD'
|
||||
<div><div class="form-check"><input type="radio" id="i0" class="form-check-input" name="test" value="value">
|
||||
<label class="form-check-label" for="i0">label&</label></div></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::radioList('test', [], ['value' => 'label&']));
|
||||
|
||||
Html::$counter = 0;
|
||||
$expected = <<<'EOD'
|
||||
<div><div class="form-check"><input type="radio" id="i0" class="form-check-input" name="test" value="value">
|
||||
<label class="form-check-label" for="i0">label&</label></div></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::radioList('test', [], ['value' => 'label&'], ['encode' => false]));
|
||||
}
|
||||
|
||||
public function testCheckboxList()
|
||||
{
|
||||
$this->assertEquals('<div></div>', Html::checkboxList('test'));
|
||||
|
||||
$dataItems = [
|
||||
'value1' => 'text1',
|
||||
'value2' => 'text2',
|
||||
];
|
||||
|
||||
Html::$counter = 0;
|
||||
|
||||
$expected = <<<'EOD'
|
||||
<div><div class="form-check"><input type="checkbox" id="i0" class="form-check-input" name="test[]" value="value1">
|
||||
<label class="form-check-label" for="i0">text1</label></div>
|
||||
<div class="form-check"><input type="checkbox" id="i1" class="form-check-input" name="test[]" value="value2" checked>
|
||||
<label class="form-check-label" for="i1">text2</label></div></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', ['value2'], $dataItems));
|
||||
|
||||
|
||||
Html::$counter = 0;
|
||||
$expected = <<<'EOD'
|
||||
<div>0<label>text1 <input type="checkbox" name="test[]" value="value1"></label>
|
||||
1<label>text2 <input type="checkbox" name="test[]" value="value2" checked></label></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', ['value2'], $dataItems, [
|
||||
'item' => function ($index, $label, $name, $checked, $value) {
|
||||
return $index . Html::label($label . ' ' . Html::checkbox($name, $checked, ['value' => $value]));
|
||||
},
|
||||
]));
|
||||
|
||||
Html::$counter = 0;
|
||||
$expected = <<<'EOD'
|
||||
<div><div class="form-check"><input type="checkbox" id="i0" class="form-check-input" name="test[]" value="value" checked>
|
||||
<label class="form-check-label" for="i0">label&</label></div></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', 'value', ['value' => 'label&']));
|
||||
|
||||
Html::$counter = 0;
|
||||
$expected = <<<'EOD'
|
||||
<div><div class="form-check"><input type="checkbox" id="i0" class="form-check-input" name="test[]" value="value" checked>
|
||||
<label class="form-check-label" for="i0">label&</label></div></div>
|
||||
EOD;
|
||||
$this->assertEqualsWithoutLE($expected, Html::checkboxList('test', 'value', ['value' => 'label&'], ['encode' => false]));
|
||||
}
|
||||
|
||||
public function testError()
|
||||
{
|
||||
$model = new DynamicModel();
|
||||
$model->addError('foo', 'Some error message.');
|
||||
|
||||
$this->assertEquals('<div class="invalid-feedback">Some error message.</div>', Html::error($model, 'foo'));
|
||||
$this->assertEquals('<div class="custom-class">Some error message.</div>', Html::error($model, 'foo', ['class' => 'custom-class']));
|
||||
$this->assertEquals('<div>Some error message.</div>', Html::error($model, 'foo', ['class' => null]));
|
||||
$this->assertEquals('<p class="invalid-feedback">Some error message.</p>', Html::error($model, 'foo', ['tag' => 'p']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\LinkPager;
|
||||
use yii\data\Pagination;
|
||||
use yii\helpers\ReplaceArrayValue;
|
||||
use yii\helpers\StringHelper;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class LinkPagerTest extends TestCase
|
||||
{
|
||||
public function testFirstLastPageLabels()
|
||||
{
|
||||
$pagination = $this->getPagination(5);
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $pagination,
|
||||
'firstPageLabel' => true,
|
||||
'lastPageLabel' => true,
|
||||
]);
|
||||
$this->assertContains('<li class="page-item first"><a class="page-link" href="/?r=test&page=1" data-page="0">1</a></li>', $output);
|
||||
$this->assertContains('<li class="page-item last"><a class="page-link" href="/?r=test&page=25" data-page="24">25</a></li>', $output);
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $pagination,
|
||||
'firstPageLabel' => 'First',
|
||||
'lastPageLabel' => 'Last',
|
||||
]);
|
||||
$this->assertContains('<li class="page-item first"><a class="page-link" href="/?r=test&page=1" data-page="0">First</a></li>', $output);
|
||||
$this->assertContains('<li class="page-item last"><a class="page-link" href="/?r=test&page=25" data-page="24">Last</a></li>', $output);
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $pagination,
|
||||
'firstPageLabel' => false,
|
||||
'lastPageLabel' => false,
|
||||
]);
|
||||
$this->assertNotContains('<li class="page-item first">', $output);
|
||||
$this->assertNotContains('<li class="page-item last">', $output);
|
||||
}
|
||||
|
||||
public function testDisabledPageElementOptions()
|
||||
{
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $this->getPagination(0),
|
||||
'disabledListItemSubTagOptions' => ['class' => ['foo-bar']],
|
||||
]);
|
||||
$this->assertContains('<li class="page-item prev disabled"><a class="page-link foo-bar"', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testOverrideDisabledPageElementOptions()
|
||||
{
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $this->getPagination(0),
|
||||
'disabledListItemSubTagOptions' => ['class' => new ReplaceArrayValue(['foo-bar'])],
|
||||
]);
|
||||
$this->assertContains('<li class="page-item prev disabled"><a class="foo-bar"', $output);
|
||||
}
|
||||
|
||||
public function testDisableCurrentPageButton()
|
||||
{
|
||||
$pagination = $this->getPagination(5);
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $pagination,
|
||||
'disableCurrentPageButton' => false,
|
||||
]);
|
||||
$this->assertContains('<li class="page-item active" aria-current="page"><a class="page-link" href="/?r=test&page=6" data-page="5">6</a></li>', $output);
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $pagination,
|
||||
'disableCurrentPageButton' => true,
|
||||
]);
|
||||
$this->assertContains('<li class="page-item active disabled" aria-current="page"><a class="page-link" href="/?r=test&page=6" data-page="5" tabindex="-1">6</a></li>', $output);
|
||||
}
|
||||
|
||||
public function testOptionsWithTagOption()
|
||||
{
|
||||
LinkPager::$counter = 0;
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $this->getPagination(5),
|
||||
'options' => [
|
||||
'tag' => 'div',
|
||||
],
|
||||
]);
|
||||
$this->assertTrue(StringHelper::startsWith($output, '<div id="w0">'));
|
||||
$this->assertTrue(StringHelper::endsWith($output, '</div>'));
|
||||
}
|
||||
|
||||
public function testLinkWrapOptions()
|
||||
{
|
||||
$output = LinkPager::widget([
|
||||
'pagination' => $this->getPagination(1),
|
||||
'linkContainerOptions' => [
|
||||
'tag' => 'div',
|
||||
'class' => 'my-class',
|
||||
],
|
||||
]);
|
||||
$this->assertContains(
|
||||
'<div class="my-class page-item"><a class="page-link" href="/?r=test&page=3" data-page="2">3</a></div>',
|
||||
$output
|
||||
);
|
||||
$this->assertContains(
|
||||
'<div class="my-class page-item active" aria-current="page"><a class="page-link" href="/?r=test&page=2" data-page="1">2</a></div>',
|
||||
$output
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2/issues/15536
|
||||
*/
|
||||
public function testShouldTriggerInitEvent()
|
||||
{
|
||||
$initTriggered = false;
|
||||
LinkPager::widget([
|
||||
'pagination' => $this->getPagination(1),
|
||||
'on init' => function () use (&$initTriggered) {
|
||||
$initTriggered = true;
|
||||
}
|
||||
]);
|
||||
$this->assertTrue($initTriggered);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockWebApplication([
|
||||
'components' => [
|
||||
'urlManager' => [
|
||||
'scriptUrl' => '/',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pagination.
|
||||
* @param int $page
|
||||
* @return Pagination
|
||||
*/
|
||||
private function getPagination($page)
|
||||
{
|
||||
$pagination = new Pagination();
|
||||
$pagination->setPage($page);
|
||||
$pagination->totalCount = 500;
|
||||
$pagination->route = 'test';
|
||||
|
||||
return $pagination;
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Html;
|
||||
use yii\bootstrap5\Modal;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ModalTest extends TestCase
|
||||
{
|
||||
public function testBodyOptions()
|
||||
{
|
||||
Modal::$counter = 0;
|
||||
$out = Modal::widget([
|
||||
'closeButton' => false,
|
||||
'bodyOptions' => ['class' => 'modal-body test', 'style' => 'text-align:center;']
|
||||
]);
|
||||
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-body test" style="text-align:center;">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testContainerOptions()
|
||||
{
|
||||
Modal::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
Modal::begin([
|
||||
'title' => 'Modal title',
|
||||
'footer' => Html::button('Close', [
|
||||
'type' => 'button',
|
||||
'class' => ['btn', 'btn-secondary'],
|
||||
'data' => [
|
||||
'bs-dismiss' => 'modal'
|
||||
]
|
||||
]) . "\n" . Html::button('Save changes', [
|
||||
'type' => 'button',
|
||||
'class' => ['btn', 'btn-primary']
|
||||
])
|
||||
]);
|
||||
echo '<p>Woohoo, you\'re reading this text in a modal!</p>';
|
||||
Modal::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="modal fade" tabindex="-1" aria-hidden="true" aria-labelledby="w0-label">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 id="w0-label" class="modal-title">Modal title</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Woohoo, you're reading this text in a modal!</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testTriggerButton()
|
||||
{
|
||||
Modal::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
Modal::begin([
|
||||
'toggleButton' => [
|
||||
'class' => ['btn', 'btn-primary'],
|
||||
'label' => 'Launch demo modal'
|
||||
],
|
||||
'title' => 'Modal title',
|
||||
'footer' => Html::button('Close', [
|
||||
'type' => 'button',
|
||||
'class' => ['btn', 'btn-secondary']
|
||||
]) . "\n" . Html::button('Save changes', [
|
||||
'type' => 'button',
|
||||
'class' => ['btn', 'btn-primary']
|
||||
])
|
||||
]);
|
||||
echo '<p>Woohoo, you\'re reading this text in a modal!</p>';
|
||||
Modal::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$this->assertContains(
|
||||
'<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#w0">Launch demo modal</button>',
|
||||
$out
|
||||
);
|
||||
}
|
||||
|
||||
public function testDialogOptions()
|
||||
{
|
||||
Modal::$counter = 0;
|
||||
$out = Modal::widget([
|
||||
'closeButton' => false,
|
||||
'dialogOptions' => ['class' => 'test', 'style' => 'text-align:center;']
|
||||
]);
|
||||
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
|
||||
<div class="test modal-dialog" style="text-align:center;">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testCenterVertical()
|
||||
{
|
||||
Modal::$counter = 0;
|
||||
$out = Modal::widget([
|
||||
'closeButton' => false,
|
||||
'centerVertical' => true
|
||||
]);
|
||||
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testScrollable()
|
||||
{
|
||||
Modal::$counter = 0;
|
||||
$out = Modal::widget([
|
||||
'closeButton' => false,
|
||||
'scrollable' => true
|
||||
]);
|
||||
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Nav;
|
||||
use yii\bootstrap5\NavBar;
|
||||
use yii\bootstrap5\Offcanvas;
|
||||
|
||||
/**
|
||||
* Tests for NavBar widget
|
||||
*
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class NavBarTest extends TestCase
|
||||
{
|
||||
public function testRender()
|
||||
{
|
||||
NavBar::$counter = 0;
|
||||
|
||||
$out = NavBar::widget([
|
||||
'brandLabel' => 'My Company',
|
||||
'brandUrl' => '/',
|
||||
'options' => [
|
||||
'class' => 'navbar-inverse navbar-static-top navbar-frontend',
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<nav id="w0" class="navbar-inverse navbar-static-top navbar-frontend navbar">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">My Company</a>
|
||||
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#w0-collapse" aria-controls="w0-collapse" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
|
||||
<div id="w0-collapse" class="collapse navbar-collapse">
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testBrandImage()
|
||||
{
|
||||
$out = NavBar::widget([
|
||||
'brandImage' => '/images/test.jpg',
|
||||
'brandUrl' => '/',
|
||||
]);
|
||||
|
||||
$this->assertContains('<a class="navbar-brand" href="/"><img src="/images/test.jpg" alt=""></a>', $out);
|
||||
}
|
||||
|
||||
public function testBrandImageOptions()
|
||||
{
|
||||
$out = NavBar::widget([
|
||||
'brandImage' => '/images/test.jpg',
|
||||
'brandImageOptions' => ['alt' => 'test image'],
|
||||
'brandUrl' => '/',
|
||||
]);
|
||||
|
||||
$this->assertContains('<a class="navbar-brand" href="/"><img src="/images/test.jpg" alt="test image"></a>', $out);
|
||||
}
|
||||
|
||||
public function testBrandLink()
|
||||
{
|
||||
$out = NavBar::widget([
|
||||
'brandLabel' => 'Yii Framework',
|
||||
'brandUrl' => false,
|
||||
]);
|
||||
|
||||
$this->assertContains('<a class="navbar-brand" href="/index.php">Yii Framework</a>', $out);
|
||||
}
|
||||
|
||||
public function testBrandSpan()
|
||||
{
|
||||
$out = NavBar::widget([
|
||||
'brandLabel' => 'Yii Framework',
|
||||
'brandUrl' => null,
|
||||
]);
|
||||
|
||||
$this->assertContains('<span class="navbar-brand">Yii Framework</span>', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testNavAndForm()
|
||||
{
|
||||
|
||||
NavBar::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
NavBar::begin([
|
||||
'brandLabel' => 'My Company',
|
||||
'brandUrl' => '/',
|
||||
'options' => [
|
||||
],
|
||||
]);
|
||||
echo Nav::widget([
|
||||
'options' => [
|
||||
'class' => ['mr-auto']
|
||||
],
|
||||
'items' => [
|
||||
['label' => 'Home', 'url' => '#'],
|
||||
['label' => 'Link', 'url' => '#'],
|
||||
['label' => 'Dropdown', 'items' => [
|
||||
['label' => 'Action', 'url' => '#'],
|
||||
['label' => 'Another action', 'url' => '#'],
|
||||
'-',
|
||||
['label' => 'Something else here', 'url' => '#'],
|
||||
]]
|
||||
]
|
||||
]);
|
||||
echo <<<HTML
|
||||
<form class="form-inline my-2 my-lg-0">
|
||||
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
|
||||
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||
</form>
|
||||
HTML;
|
||||
NavBar::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<nav id="w0" class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">My Company</a>
|
||||
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#w0-collapse" aria-controls="w0-collapse" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
|
||||
<div id="w0-collapse" class="collapse navbar-collapse">
|
||||
<ul id="w1" class="mr-auto nav"><li class="nav-item"><a class="nav-link" href="#">Home</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown</a><div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">Action</a>
|
||||
<a class="dropdown-item" href="#">Another action</a>
|
||||
<hr class="dropdown-divider">
|
||||
<a class="dropdown-item" href="#">Something else here</a></div></li></ul><form class="form-inline my-2 my-lg-0">
|
||||
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
|
||||
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||
</form></div>
|
||||
</div>
|
||||
</nav>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testOffcanvasNavigation()
|
||||
{
|
||||
NavBar::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
NavBar::begin([
|
||||
'brandLabel' => 'Offcanvas navbar',
|
||||
'brandUrl' => ['/'],
|
||||
'options' => [
|
||||
'class' => ['navbar', 'navbar-light', 'bg-light', 'fixed-top']
|
||||
],
|
||||
'innerContainerOptions' => [
|
||||
'class' => ['container-fluid']
|
||||
],
|
||||
'collapseOptions' => false,
|
||||
'offcanvasOptions' => [
|
||||
'title' => 'Offcanvas',
|
||||
'placement' => Offcanvas::PLACEMENT_END
|
||||
]
|
||||
]);
|
||||
echo Nav::widget([
|
||||
'options' => [
|
||||
'class' => ['navbar-nav']
|
||||
],
|
||||
'items' => [
|
||||
['label' => 'Home', 'url' => '#'],
|
||||
['label' => 'Link', 'url' => '#'],
|
||||
['label' => 'Dropdown', 'items' => [
|
||||
['label' => 'Action', 'url' => '#'],
|
||||
['label' => 'Another action', 'url' => '#'],
|
||||
'-',
|
||||
['label' => 'Something else here', 'url' => '#'],
|
||||
]]
|
||||
]
|
||||
]);
|
||||
NavBar::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<nav id="w0" class="navbar navbar-light bg-light fixed-top">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/index.php?r=">Offcanvas navbar</a>
|
||||
<button type="button" class="navbar-toggler" data-bs-toggle="offcanvas" data-bs-target="#w0-offcanvas" aria-controls="w0-offcanvas" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
|
||||
|
||||
<div id="w0-offcanvas" class="offcanvas offcanvas-end" tabindex="-1" data-bs-backdrop="true" data-bs-scroll="false" aria-labelledby="w0-offcanvas-label">
|
||||
<div class="offcanvas-header">
|
||||
<h5 id="w0-offcanvas-label" class="offcanvas-title">Offcanvas</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<ul id="w1" class="navbar-nav nav"><li class="nav-item"><a class="nav-link" href="#">Home</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown</a><div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">Action</a>
|
||||
<a class="dropdown-item" href="#">Another action</a>
|
||||
<hr class="dropdown-divider">
|
||||
<a class="dropdown-item" href="#">Something else here</a></div></li></ul>
|
||||
</div>
|
||||
</div></div>
|
||||
</nav>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testNoCollapse()
|
||||
{
|
||||
NavBar::$counter = 0;
|
||||
|
||||
$out = NavBar::widget([
|
||||
'brandLabel' => 'My Company',
|
||||
'brandUrl' => '/',
|
||||
'collapseOptions' => false,
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<nav id="w0" class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">My Company</a>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
+369
@@ -0,0 +1,369 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Nav;
|
||||
|
||||
/**
|
||||
* Tests for Nav widget
|
||||
*
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class NavTest extends TestCase
|
||||
{
|
||||
public function testIds()
|
||||
{
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget(
|
||||
[
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2'],
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'visible' => false,
|
||||
'items' => [
|
||||
['label' => 'Page4', 'content' => 'Page4'],
|
||||
['label' => 'Page5', 'content' => 'Page5'],
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown1</a><div id="w1" class="dropdown-menu"><h6 class="dropdown-header">Page2</h6>
|
||||
<h6 class="dropdown-header">Page3</h6></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testRenderDropdownWithDropdownOptions()
|
||||
{
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget(
|
||||
[
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'dropdownOptions' => ['class' => 'test', 'data-id' => 't1', 'id' => 'test1'],
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2'],
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'visible' => false,
|
||||
'items' => [
|
||||
['label' => 'Page4', 'content' => 'Page4'],
|
||||
['label' => 'Page5', 'content' => 'Page5'],
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown1</a><div id="test1" class="test dropdown-menu" data-id="t1"><h6 class="dropdown-header">Page2</h6>
|
||||
<h6 class="dropdown-header">Page3</h6></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testEmptyItems()
|
||||
{
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'items' => null,
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2'],
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
],
|
||||
],
|
||||
[
|
||||
'label' => 'Page4',
|
||||
'items' => [],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown1</a><div id="w1" class="dropdown-menu"><h6 class="dropdown-header">Page2</h6>
|
||||
<h6 class="dropdown-header">Page3</h6></div></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#">Page4</a></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testActive()
|
||||
{
|
||||
$this->mockAction('site', 'users');
|
||||
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Main',
|
||||
'url' => ['site/index'],
|
||||
],
|
||||
[
|
||||
'label' => 'Admin',
|
||||
'items' => [
|
||||
['label' => 'Users', 'url' => ['site/users']],
|
||||
['label' => 'Roles', 'url' => ['site/roles']],
|
||||
['label' => 'Statuses', 'url' => ['site/statuses']]
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="/base/index.php?r=site%2Findex">Main</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Admin</a><div id="w1" class="dropdown-menu"><a class="dropdown-item active" href="/base/index.php?r=site%2Fusers" aria-current="true">Users</a>
|
||||
<a class="dropdown-item" href="/base/index.php?r=site%2Froles">Roles</a>
|
||||
<a class="dropdown-item" href="/base/index.php?r=site%2Fstatuses">Statuses</a></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
$this->removeMockedAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/162
|
||||
*/
|
||||
public function testExplicitActive()
|
||||
{
|
||||
$this->mockAction('site', 'index');
|
||||
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'activateItems' => false,
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Item1',
|
||||
'active' => true,
|
||||
],
|
||||
[
|
||||
'label' => 'Item2',
|
||||
'url' => ['site/index'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/base/index.php?r=site%2Findex">Item2</a></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
$this->removeMockedAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/162
|
||||
*/
|
||||
public function testImplicitActive()
|
||||
{
|
||||
$this->mockAction('site', 'index');
|
||||
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Item1',
|
||||
'active' => true,
|
||||
],
|
||||
[
|
||||
'label' => 'Item2',
|
||||
'url' => ['site/index'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link active" href="#">Item1</a></li>
|
||||
<li class="nav-item"><a class="nav-link active" href="/base/index.php?r=site%2Findex">Item2</a></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
$this->removeMockedAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/162
|
||||
*/
|
||||
public function testExplicitActiveSubitems()
|
||||
{
|
||||
$this->mockAction('site', 'index');
|
||||
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'activateItems' => false,
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Item1',
|
||||
],
|
||||
[
|
||||
'label' => 'Item2',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2', 'url' => ['site/index']],
|
||||
['label' => 'Page3', 'content' => 'Page3', 'active' => true],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item" href="/base/index.php?r=site%2Findex">Page2</a>
|
||||
<h6 class="dropdown-header">Page3</h6></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
$this->removeMockedAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/162
|
||||
*/
|
||||
public function testImplicitActiveSubitems()
|
||||
{
|
||||
$this->mockAction('site', 'index');
|
||||
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Item1',
|
||||
],
|
||||
[
|
||||
'label' => 'Item2',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2', 'url' => ['site/index']],
|
||||
['label' => 'Page3', 'content' => 'Page3', 'active' => true],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item active" href="/base/index.php?r=site%2Findex" aria-current="true">Page2</a>
|
||||
<h6 class="dropdown-header">Page3</h6></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
$this->removeMockedAction();
|
||||
}
|
||||
|
||||
public function testDisabled()
|
||||
{
|
||||
$this->mockAction('site', 'index');
|
||||
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Item1',
|
||||
'disabled' => true
|
||||
],
|
||||
[
|
||||
'label' => 'Item2',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2', 'url' => ['site/index'], 'disabled' => true],
|
||||
['label' => 'Page3', 'content' => 'Page3', 'active' => true],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Item1</a></li>
|
||||
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item disabled" href="/base/index.php?r=site%2Findex" tabindex="-1" aria-disabled="true">Page2</a>
|
||||
<h6 class="dropdown-header">Page3</h6></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
$this->removeMockedAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/96
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap/issues/157
|
||||
*/
|
||||
public function testDeepActivateParents()
|
||||
{
|
||||
Nav::$counter = 0;
|
||||
$out = Nav::widget([
|
||||
'activateParents' => true,
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Dropdown',
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Sub-dropdown',
|
||||
'items' => [
|
||||
['label' => 'Page', 'content' => 'Page', 'active' => true],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<EXPECTED
|
||||
<ul id="w0" class="nav"><li class="dropdown nav-item"><a class="dropdown-toggle nav-link active" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown</a><div id="w1" class="dropdown-menu"><div class="dropdown active" aria-expanded="false">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Sub-dropdown</a>
|
||||
<div id="w2" class="dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page</h6></div>
|
||||
</div></div></li></ul>
|
||||
EXPECTED;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->mockWebApplication([
|
||||
'components' => [
|
||||
'request' => [
|
||||
'class' => 'yii\web\Request',
|
||||
'scriptUrl' => '/base/index.php',
|
||||
'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/',
|
||||
]
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Offcanvas;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class OffcanvasTest extends TestCase
|
||||
{
|
||||
public function testBodyOptions()
|
||||
{
|
||||
Offcanvas::$counter = 0;
|
||||
$out = Offcanvas::widget([
|
||||
'closeButton' => false,
|
||||
'bodyOptions' => ['class' => 'offcanvas-body test', 'style' => ['text-align' => 'center']]
|
||||
]);
|
||||
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="offcanvas offcanvas-start" tabindex="-1" data-bs-backdrop="true" data-bs-scroll="false">
|
||||
|
||||
<div class="offcanvas-body test" style="text-align: center;">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testOptions()
|
||||
{
|
||||
Offcanvas::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
Offcanvas::begin([
|
||||
'title' => 'Offcanvas title',
|
||||
'headerOptions' => [
|
||||
'data-test' => 'Test'
|
||||
],
|
||||
'titleOptions' => [
|
||||
'tag' => 'h2'
|
||||
],
|
||||
'placement' => Offcanvas::PLACEMENT_END,
|
||||
'backdrop' => false,
|
||||
'scrolling' => true,
|
||||
'closeButton' => false
|
||||
]);
|
||||
echo '<p>Woohoo, you\'re reading this text in an offcanvas!</p>';
|
||||
Offcanvas::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
|
||||
<div id="w0" class="offcanvas offcanvas-end" tabindex="-1" data-bs-backdrop="false" data-bs-scroll="true" aria-labelledby="w0-label">
|
||||
<div class="offcanvas-header" data-test="Test">
|
||||
<h2 id="w0-label" class="offcanvas-title">Offcanvas title</h2>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<p>Woohoo, you're reading this text in an offcanvas!</p>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testTriggerButton()
|
||||
{
|
||||
Offcanvas::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
Offcanvas::begin([
|
||||
'toggleButton' => [
|
||||
'class' => ['btn', 'btn-primary'],
|
||||
'label' => 'Launch demo offcanvas'
|
||||
],
|
||||
'title' => 'Offcanvas title',
|
||||
]);
|
||||
echo '<p>Woohoo, you\'re reading this text in an offcanvas!</p>';
|
||||
Offcanvas::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$this->assertContains(
|
||||
'<button type="button" class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#w0" aria-controls="w0">Launch demo offcanvas</button>',
|
||||
$out
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use PHPUnit\Framework\Constraint\IsType;
|
||||
use Yii;
|
||||
use yii\bootstrap5\Html;
|
||||
use yii\bootstrap5\Popover;
|
||||
use yii\web\View;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class PopoverTest extends TestCase
|
||||
{
|
||||
public function testButtonRender()
|
||||
{
|
||||
Popover::$counter = 0;
|
||||
$out = Popover::widget(['toggleButton' => ['class' => ['btn', 'btn-primary']]]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<button type="button" id="w0" class="btn btn-primary">Show</button>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testClientOptions()
|
||||
{
|
||||
Popover::$counter = 0;
|
||||
Popover::widget([
|
||||
'headerOptions' => ['class' => ['test-header']],
|
||||
'placement' => Popover::PLACEMENT_BOTTOM,
|
||||
'title' => 'Test Popover'
|
||||
]);
|
||||
|
||||
$js = Yii::$app->view->js[View::POS_READY];
|
||||
|
||||
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
|
||||
$options = array_shift($js);
|
||||
|
||||
$this->assertContainsWithoutLE("(new bootstrap.Popover('#w0', {", $options);
|
||||
$this->assertContainsWithoutLE("id=\u0022w0-popover\u0022", $options);
|
||||
$this->assertContainsWithoutLE("class=\u0022test-header popover-header\u0022", $options);
|
||||
$this->assertContainsWithoutLE('"placement":"bottom"', $options);
|
||||
$this->assertContainsWithoutLE('"title":"Test Popover"', $options);
|
||||
}
|
||||
|
||||
public function testContent()
|
||||
{
|
||||
Popover::$counter = 0;
|
||||
Popover::begin([]);
|
||||
echo Html::tag('span', 'Test content', ['class' => ['test-content']]);
|
||||
Popover::end();
|
||||
|
||||
$js = Yii::$app->view->js[View::POS_READY];
|
||||
|
||||
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
|
||||
$options = array_shift($js);
|
||||
|
||||
$this->assertContainsWithoutLE('"content":"\u003Cspan class=\u0022test-content\u0022\u003ETest content\u003C\/span\u003E"', $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
|
||||
use yii\bootstrap5\Progress;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ProgressTest extends TestCase
|
||||
{
|
||||
public function testSimpleRender()
|
||||
{
|
||||
Progress::$counter = 0;
|
||||
$out = Progress::widget([
|
||||
'label' => 'Progress',
|
||||
'percent' => 25,
|
||||
'barOptions' => ['class' => 'bg-warning']
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="progress">
|
||||
<div class="bg-warning progress-bar" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%;">Progress</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testRender()
|
||||
{
|
||||
Progress::$counter = 0;
|
||||
$out = Progress::widget([
|
||||
'bars' => [
|
||||
['label' => 'Progress', 'percent' => 25]
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%;">Progress</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testMultiple()
|
||||
{
|
||||
Progress::$counter = 0;
|
||||
$out = Progress::widget([
|
||||
'bars' => [
|
||||
['label' => '', 'percent' => 15],
|
||||
['label' => '', 'percent' => 30, 'options' => ['class' => ['bg-success']]],
|
||||
['label' => '', 'percent' => 20, 'options' => ['class' => ['bg-info']]]
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100" style="width: 15%;"></div>
|
||||
<div class="bg-success progress-bar" role="progressbar" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100" style="width: 30%;"></div>
|
||||
<div class="bg-info progress-bar" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%;"></div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/121
|
||||
*/
|
||||
public function testRussianLocaleRendering()
|
||||
{
|
||||
$this->mockWebApplication([
|
||||
'language' => 'ru-RU',
|
||||
'sourceLanguage' => 'en-US',
|
||||
]);
|
||||
|
||||
Progress::$counter = 0;
|
||||
$out = Progress::widget([
|
||||
'bars' => [
|
||||
['label' => 'Progress', 'percent' => 25]
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%;">Progress</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Tabs;
|
||||
use yii\helpers\Html;
|
||||
|
||||
/**
|
||||
* Tests for Tabs widget
|
||||
*
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class TabsTest extends TestCase
|
||||
{
|
||||
public function testRoleTablist()
|
||||
{
|
||||
Tabs::$counter = 0;
|
||||
$out = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
],
|
||||
[
|
||||
'label' => 'Page2',
|
||||
'content' => 'Page2',
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertContainsWithoutLE('<ul id="w0" class="nav nav-tabs" role="tablist">', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each tab should have a corresponding unique ID
|
||||
*
|
||||
* @see https://github.com/yiisoft/yii2/issues/6150
|
||||
*/
|
||||
public function testIds()
|
||||
{
|
||||
Tabs::$counter = 0;
|
||||
$out = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2'],
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown2',
|
||||
'items' => [
|
||||
['label' => 'Page4', 'content' => 'Page4'],
|
||||
['label' => 'Page5', 'content' => 'Page5'],
|
||||
]
|
||||
],
|
||||
[
|
||||
'label' => $extAnchor1 = 'External link',
|
||||
'url' => $extUrl1 = ['//other/route'],
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown3',
|
||||
'items' => [
|
||||
[
|
||||
'label' => $extAnchor2 = 'External Dropdown Link',
|
||||
'url' => $extUrl2 = ['//other/dropdown/route']
|
||||
],
|
||||
]
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$page1 = 'w0-tab0';
|
||||
$page2 = 'w0-dd1-tab0';
|
||||
$page3 = 'w0-dd1-tab1';
|
||||
$page4 = 'w0-dd2-tab0';
|
||||
$page5 = 'w0-dd2-tab1';
|
||||
|
||||
$shouldContain = [
|
||||
'w0', // nav widget container
|
||||
"#$page1", // Page1
|
||||
|
||||
'w1', // Dropdown1
|
||||
"$page2", // Page2
|
||||
"$page3", // Page3
|
||||
|
||||
|
||||
'w2', // Dropdown2
|
||||
"#$page4", // Page4
|
||||
"#$page5", // Page5
|
||||
|
||||
'w3', // Dropdown3
|
||||
|
||||
// containers
|
||||
"id=\"$page1\"",
|
||||
"id=\"$page2\"",
|
||||
"id=\"$page3\"",
|
||||
"id=\"$page4\"",
|
||||
"id=\"$page5\"",
|
||||
Html::a($extAnchor1, $extUrl1, ['class' => 'nav-link']),
|
||||
Html::a($extAnchor2, $extUrl2, [/*'tabindex' => -1, */
|
||||
'class' => 'dropdown-item'
|
||||
]),
|
||||
];
|
||||
|
||||
foreach ($shouldContain as $string) {
|
||||
$this->assertContainsWithoutLE($string, $out);
|
||||
}
|
||||
}
|
||||
|
||||
public function testVisible()
|
||||
{
|
||||
Tabs::$counter = 0;
|
||||
$html = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
],
|
||||
[
|
||||
'label' => 'InvisiblePage',
|
||||
'content' => 'Invisible Page Content',
|
||||
'visible' => false
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2'],
|
||||
['label' => 'InvisibleItem', 'content' => 'Invisible Item Content', 'visible' => false],
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
['label' => 'External Link', 'url' => ['//other/dropdown/route']],
|
||||
['label' => 'Invisible External Link', 'url' => ['//other/dropdown/route'], 'visible' => false],
|
||||
]
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertNotContains('InvisiblePage', $html);
|
||||
$this->assertNotContains('Invisible Page Content', $html);
|
||||
$this->assertNotContains('InvisibleItem', $html);
|
||||
$this->assertNotContains('Invisible Item Content', $html);
|
||||
$this->assertNotContains('Invisible External Link', $html);
|
||||
}
|
||||
|
||||
public function testDisabled()
|
||||
{
|
||||
Tabs::$counter = 0;
|
||||
$html = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
'disabled' => true
|
||||
],
|
||||
[
|
||||
'label' => 'Page2',
|
||||
'content' => 'Page2',
|
||||
],
|
||||
[
|
||||
'label' => 'DisabledPage',
|
||||
'content' => 'Disabled Page Content',
|
||||
'disabled' => true
|
||||
],
|
||||
[
|
||||
'label' => 'Dropdown1',
|
||||
'items' => [
|
||||
['label' => 'Page2', 'content' => 'Page2'],
|
||||
['label' => 'DisabledItem', 'content' => 'Disabled Item Content', 'disabled' => true],
|
||||
['label' => 'Page3', 'content' => 'Page3'],
|
||||
['label' => 'External Link', 'url' => ['//other/dropdown/route']],
|
||||
['label' => 'Disabled External Link', 'url' => ['//other/dropdown/route'], 'disabled' => true],
|
||||
]
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertContains(
|
||||
'<li class="nav-item"><a class="nav-link disabled" href="#w0-tab0" data-bs-toggle="tab" role="tab" aria-controls="w0-tab0" aria-disabled="true" tabindex="-1">Page1</a></li>',
|
||||
$html
|
||||
);
|
||||
$this->assertContains(
|
||||
'<li class="nav-item"><a class="nav-link active" href="#w0-tab1" data-bs-toggle="tab" role="tab" aria-controls="w0-tab1" aria-selected="true">Page2</a></li>',
|
||||
$html
|
||||
);
|
||||
$this->assertContains(
|
||||
'<li class="nav-item"><a class="nav-link disabled" href="#w0-tab2" data-bs-toggle="tab" role="tab" aria-controls="w0-tab2" aria-disabled="true" tabindex="-1">DisabledPage</a></li>',
|
||||
$html
|
||||
);
|
||||
$this->assertContains(
|
||||
'<a class="dropdown-item disabled" href="#w0-dd3-tab1" data-bs-toggle="tab" role="tab" aria-controls="w0-dd3-tab1" aria-disabled="true" tabindex="-1">DisabledItem</a>',
|
||||
$html
|
||||
);
|
||||
$this->assertContains(
|
||||
'<a class="dropdown-item disabled" href="/index.php?r=other%2Fdropdown%2Froute" tabindex="-1" aria-disabled="true">Disabled External Link</a>',
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
public function testItem()
|
||||
{
|
||||
$checkTag = 'article';
|
||||
|
||||
$out = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1',
|
||||
],
|
||||
[
|
||||
'label' => 'Page2',
|
||||
'content' => 'Page2',
|
||||
],
|
||||
],
|
||||
'itemOptions' => ['tag' => $checkTag],
|
||||
'renderTabContent' => true,
|
||||
]);
|
||||
|
||||
$this->assertContains('<' . $checkTag, $out);
|
||||
}
|
||||
|
||||
public function testTabContentOptions()
|
||||
{
|
||||
$checkAttribute = "test_attribute";
|
||||
$checkValue = "check_attribute";
|
||||
|
||||
$out = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Page1',
|
||||
'content' => 'Page1'
|
||||
]
|
||||
],
|
||||
'tabContentOptions' => [
|
||||
$checkAttribute => $checkValue
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertContains($checkAttribute . '=', $out);
|
||||
$this->assertContains($checkValue, $out);
|
||||
}
|
||||
|
||||
public function testActivateFirstVisibleTab()
|
||||
{
|
||||
$html = Tabs::widget([
|
||||
'id' => 'mytab',
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Tab 1',
|
||||
'content' => 'some content',
|
||||
'visible' => false
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 2',
|
||||
'content' => 'some content',
|
||||
'disabled' => true
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 3',
|
||||
'content' => 'some content'
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 4',
|
||||
'content' => 'some content'
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertNotContains(
|
||||
'<li class="nav-item"><a class="nav-link active" href="#mytab-tab0" data-bs-toggle="tab" role="tab" aria-controls="mytab-tab0" aria-selected="true">Tab 1</a></li>',
|
||||
$html
|
||||
);
|
||||
$this->assertNotContains(
|
||||
'<li class="nav-item"><a class="nav-link active" href="#mytab-tab1" data-bs-toggle="tab" role="tab" aria-controls="mytab-tab1" aria-selected="true">Tab 2</a></li>',
|
||||
$html
|
||||
);
|
||||
$this->assertContains(
|
||||
'<li class="nav-item"><a class="nav-link active" href="#mytab-tab2" data-bs-toggle="tab" role="tab" aria-controls="mytab-tab2" aria-selected="true">Tab 3</a></li>',
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
public function testActivateTab()
|
||||
{
|
||||
$html = Tabs::widget([
|
||||
'id' => 'mytab',
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Tab 1',
|
||||
'content' => 'some content',
|
||||
'visible' => false
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 2',
|
||||
'content' => 'some content'
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 3',
|
||||
'content' => 'some content',
|
||||
'active' => true
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 4',
|
||||
'content' => 'some content'
|
||||
]
|
||||
]
|
||||
]);
|
||||
$this->assertContains(
|
||||
'<li class="nav-item"><a class="nav-link active" href="#mytab-tab2" data-bs-toggle="tab" role="tab" aria-controls="mytab-tab2" aria-selected="true">Tab 3</a></li>',
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
public function testTabLabelEncoding()
|
||||
{
|
||||
$html = Tabs::widget([
|
||||
'encodeLabels' => false,
|
||||
'id' => 'mytab',
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Tab 1<span>encoded</span>',
|
||||
'content' => 'some content',
|
||||
'encode' => true,
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 2<span>not encoded</span>',
|
||||
'content' => 'some content',
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 3<span>not encoded too</span>',
|
||||
'content' => 'some content',
|
||||
],
|
||||
]
|
||||
]);
|
||||
$this->assertContains('<span>encoded</span>', $html);
|
||||
$this->assertContains('<span>not encoded</span>', $html);
|
||||
$this->assertContains('<span>not encoded too</span>', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/108#issuecomment-465219339
|
||||
*/
|
||||
public function testIdRendering()
|
||||
{
|
||||
Tabs::$counter = 0;
|
||||
$html = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'options' => ['id' => 'pane1'],
|
||||
'label' => 'Tab 1',
|
||||
'content' => '<div>Content 1</div>',
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 2',
|
||||
'content' => '<div>Content 2</div>',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<ul id="w0" class="nav nav-tabs" role="tablist"><li class="nav-item"><a class="nav-link active" href="#pane1" data-bs-toggle="tab" role="tab" aria-controls="pane1" aria-selected="true">Tab 1</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#w0-tab1" data-bs-toggle="tab" role="tab" aria-controls="w0-tab1" aria-selected="false">Tab 2</a></li></ul>
|
||||
<div class="tab-content"><div id="pane1" class="tab-pane active"><div>Content 1</div></div>
|
||||
<div id="w0-tab1" class="tab-pane"><div>Content 2</div></div></div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $html);
|
||||
}
|
||||
|
||||
public function testHeaderOptions()
|
||||
{
|
||||
Tabs::$counter = 0;
|
||||
$html = Tabs::widget([
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Tab 1',
|
||||
'content' => '<div>Content 1</div>',
|
||||
],
|
||||
[
|
||||
'label' => 'Tab 2',
|
||||
'content' => '<div>Content 2</div>',
|
||||
'headerOptions' => ['class' => 'col-6'],
|
||||
],
|
||||
[
|
||||
'label' => 'Link',
|
||||
'url' => 'http://www.example.com/',
|
||||
'headerOptions' => ['class' => 'col-3'],
|
||||
],
|
||||
],
|
||||
'options' => ['class' => 'row'],
|
||||
'headerOptions' => ['class' => 'col'],
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<ul id="w0" class="row nav nav-tabs" role="tablist"><li class="col nav-item"><a class="nav-link active" href="#w0-tab0" data-bs-toggle="tab" role="tab" aria-controls="w0-tab0" aria-selected="true">Tab 1</a></li>
|
||||
<li class="col-6 nav-item"><a class="nav-link" href="#w0-tab1" data-bs-toggle="tab" role="tab" aria-controls="w0-tab1" aria-selected="false">Tab 2</a></li>
|
||||
<li class="col-3 nav-item"><a class="nav-link" href="http://www.example.com/">Link</a></li></ul>
|
||||
<div class="tab-content"><div id="w0-tab0" class="tab-pane active"><div>Content 1</div></div>
|
||||
<div id="w0-tab1" class="tab-pane"><div>Content 2</div></div></div>
|
||||
HTML;
|
||||
|
||||
$this->assertEquals($expected, $html);
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Action;
|
||||
use yii\base\Module;
|
||||
use yii\di\Container;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\web\Controller;
|
||||
|
||||
/**
|
||||
* This is the base class for all yii framework unit tests.
|
||||
*/
|
||||
class TestCase extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* Asserting two strings equality ignoring line endings
|
||||
*
|
||||
* @param string $expected
|
||||
* @param string $actual
|
||||
*/
|
||||
public function assertEqualsWithoutLE(string $expected, string $actual)
|
||||
{
|
||||
$expected = str_replace("\r\n", "\n", $expected);
|
||||
$actual = str_replace("\r\n", "\n", $actual);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserting two strings equality ignoring line endings
|
||||
*
|
||||
* @param string $needle
|
||||
* @param string $haystack
|
||||
*/
|
||||
public function assertContainsWithoutLE(string $needle, string $haystack)
|
||||
{
|
||||
$needle = str_replace("\r\n", "\n", $needle);
|
||||
$haystack = str_replace("\r\n", "\n", $haystack);
|
||||
|
||||
$this->assertContains($needle, $haystack);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockWebApplication();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param string $appClass
|
||||
*/
|
||||
protected function mockWebApplication(array $config = [], string $appClass = '\yii\web\Application')
|
||||
{
|
||||
new $appClass(ArrayHelper::merge([
|
||||
'id' => 'testapp',
|
||||
'basePath' => __DIR__,
|
||||
'vendorPath' => dirname(__DIR__) . '/vendor',
|
||||
'language' => 'en-US',
|
||||
'aliases' => [
|
||||
'@bower' => '@vendor/bower-asset',
|
||||
'@npm' => '@vendor/npm-asset',
|
||||
],
|
||||
'components' => [
|
||||
'i18n' => [
|
||||
'translations' => [
|
||||
'yii/bootstrap5*' => [
|
||||
'class' => 'yii\i18n\GettextMessageSource',
|
||||
'sourceLanguage' => 'en-US',
|
||||
'basePath' => '@yii/bootstrap5/messages',
|
||||
],
|
||||
],
|
||||
],
|
||||
'request' => [
|
||||
'cookieValidationKey' => 'wefJDF8sfdsfSDefwqdxj9oq',
|
||||
'scriptFile' => __DIR__ . '/index.php',
|
||||
'scriptUrl' => '/index.php',
|
||||
]
|
||||
]
|
||||
], $config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks controller action with parameters
|
||||
*
|
||||
* @param string $controllerId
|
||||
* @param string $actionID
|
||||
* @param string|null $moduleID
|
||||
* @param array $params
|
||||
*/
|
||||
protected function mockAction(string $controllerId, string $actionID, string $moduleID = null, array $params = [])
|
||||
{
|
||||
Yii::$app->controller = $controller = new Controller($controllerId, Yii::$app);
|
||||
$controller->actionParams = $params;
|
||||
$controller->action = new Action($actionID, $controller);
|
||||
|
||||
if ($moduleID !== null) {
|
||||
$controller->module = new Module($moduleID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes controller
|
||||
*/
|
||||
protected function removeMockedAction()
|
||||
{
|
||||
Yii::$app->controller = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys application in Yii::$app by setting it to null.
|
||||
*/
|
||||
protected function destroyApplication()
|
||||
{
|
||||
Yii::$app = null;
|
||||
Yii::$container = new Container();
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use PHPUnit\Framework\Constraint\IsType;
|
||||
use Yii;
|
||||
use yii\bootstrap5\Toast;
|
||||
use yii\web\View;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ToastTest extends TestCase
|
||||
{
|
||||
public function testBodyOptions()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
$out = Toast::widget([
|
||||
'bodyOptions' => ['class' => 'toast-body test', 'style' => ['text-align' => 'center']]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto"></strong>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body test" style="text-align: center;">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testContainerOptions()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
|
||||
ob_start();
|
||||
Toast::begin([
|
||||
'title' => 'Toast title',
|
||||
'dateTime' => time() - 60
|
||||
]);
|
||||
echo 'Woohoo, you\'re reading this text in a toast!';
|
||||
Toast::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto">Toast title</strong>
|
||||
<small class="text-muted">a minute ago</small>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
Woohoo, you're reading this text in a toast!
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testDateTimeOptions()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
$out = Toast::widget([
|
||||
'title' => 'Toast title',
|
||||
'dateTime' => time() - 60,
|
||||
'dateTimeOptions' => ['class' => ['toast-date-time'], 'style' => ['text-align' => 'right']]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<strong class="me-auto">Toast title</strong>
|
||||
<small class="toast-date-time text-muted" style="text-align: right;">a minute ago</small>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
public function testTitleOptions()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
$out = Toast::widget([
|
||||
'title' => 'Toast title',
|
||||
'titleOptions' => ['tag' => 'h5', 'style' => ['text-align' => 'left']]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<h5 class="me-auto" style="text-align: left;">Toast title</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/5
|
||||
*/
|
||||
public function testWidgetInitialization()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
ob_start();
|
||||
$toast = Toast::begin([
|
||||
'title' => 'Toast title',
|
||||
'titleOptions' => ['tag' => 'h5', 'style' => ['text-align' => 'left']]
|
||||
]);
|
||||
echo 'test';
|
||||
Toast::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$this->assertInternalType(IsType::TYPE_ARRAY, $toast->clientOptions);
|
||||
$this->assertCount(0, $toast->clientOptions);
|
||||
|
||||
$js = Yii::$app->view->js[View::POS_READY];
|
||||
|
||||
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
|
||||
$options = array_shift($js);
|
||||
|
||||
$this->assertContainsWithoutLE("(new bootstrap.Toast('#w0', {}));", $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/36
|
||||
*/
|
||||
public function testWidgetNoInitialization()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
ob_start();
|
||||
$toast = Toast::begin([
|
||||
'title' => 'Toast title',
|
||||
'clientOptions' => false,
|
||||
'titleOptions' => ['tag' => 'h5', 'style' => ['text-align' => 'left']]
|
||||
]);
|
||||
echo 'test';
|
||||
Toast::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$this->assertFalse($toast->clientOptions);
|
||||
$this->assertArrayHasKey(View::POS_READY, Yii::$app->view->js);
|
||||
}
|
||||
|
||||
public function testWidgetInitializationWithClientOptions()
|
||||
{
|
||||
Toast::$counter = 0;
|
||||
ob_start();
|
||||
$toast = Toast::begin([
|
||||
'title' => 'Toast title',
|
||||
'clientOptions' => ['delay' => 1000],
|
||||
'titleOptions' => ['tag' => 'h5', 'style' => ['text-align' => 'left']]
|
||||
]);
|
||||
echo 'test';
|
||||
Toast::end();
|
||||
$out = ob_get_clean();
|
||||
|
||||
$this->assertArrayHasKey('delay', $toast->clientOptions);
|
||||
$this->assertArrayHasKey(View::POS_READY, Yii::$app->view->js);
|
||||
$js = Yii::$app->view->js[View::POS_READY];
|
||||
|
||||
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
|
||||
$options = array_shift($js);
|
||||
|
||||
$this->assertContainsWithoutLE("(new bootstrap.Toast('#w0', {\"delay\":1000}));", $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\base\Model;
|
||||
use yii\bootstrap5\Html;
|
||||
use yii\bootstrap5\ToggleButtonGroup;
|
||||
|
||||
/**
|
||||
* @group bootstrap5
|
||||
*/
|
||||
class ToggleButtonGroupTest extends TestCase
|
||||
{
|
||||
public function testCheckbox()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$html = ToggleButtonGroup::widget([
|
||||
'type' => ToggleButtonGroup::TYPE_CHECKBOX,
|
||||
'model' => new ToggleButtonGroupTestModel(),
|
||||
'attribute' => 'value',
|
||||
'items' => [
|
||||
'1' => 'item 1',
|
||||
'2' => 'item 2',
|
||||
],
|
||||
]);
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<input type="hidden" name="ToggleButtonGroupTestModel[value]" value=""><div id="togglebuttongrouptestmodel-value" class="btn-group" role="group"><input type="checkbox" id="i0" class="btn-check" name="ToggleButtonGroupTestModel[value][]" value="1" autocomplete="off">
|
||||
<label class="btn btn-outline-secondary" for="i0">item 1</label>
|
||||
<input type="checkbox" id="i1" class="btn-check" name="ToggleButtonGroupTestModel[value][]" value="2" autocomplete="off">
|
||||
<label class="btn btn-outline-secondary" for="i1">item 2</label></div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testCheckboxChecked()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$html = ToggleButtonGroup::widget([
|
||||
'type' => ToggleButtonGroup::TYPE_CHECKBOX,
|
||||
'model' => new ToggleButtonGroupTestModel(['value' => '2']),
|
||||
'attribute' => 'value',
|
||||
'items' => [
|
||||
'1' => 'item 1',
|
||||
'2' => 'item 2',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertContains('<input type="checkbox" id="i1" class="btn-check" name="ToggleButtonGroupTestModel[value][]" value="2" checked autocomplete="off">', $html);
|
||||
}
|
||||
|
||||
public function testRadio()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$html = ToggleButtonGroup::widget([
|
||||
'type' => ToggleButtonGroup::TYPE_RADIO,
|
||||
'model' => new ToggleButtonGroupTestModel(),
|
||||
'attribute' => 'value',
|
||||
'items' => [
|
||||
'1' => 'item 1',
|
||||
'2' => 'item 2',
|
||||
],
|
||||
]);
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<input type="hidden" name="ToggleButtonGroupTestModel[value]" value=""><div id="togglebuttongrouptestmodel-value" class="btn-group" role="group"><input type="radio" id="i0" class="btn-check" name="ToggleButtonGroupTestModel[value]" value="1" autocomplete="off">
|
||||
<label class="btn btn-outline-secondary" for="i0">item 1</label>
|
||||
<input type="radio" id="i1" class="btn-check" name="ToggleButtonGroupTestModel[value]" value="2" autocomplete="off">
|
||||
<label class="btn btn-outline-secondary" for="i1">item 2</label></div>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function testRadioChecked()
|
||||
{
|
||||
Html::$counter = 0;
|
||||
$html = ToggleButtonGroup::widget([
|
||||
'type' => ToggleButtonGroup::TYPE_RADIO,
|
||||
'model' => new ToggleButtonGroupTestModel(['value' => '2']),
|
||||
'attribute' => 'value',
|
||||
'items' => [
|
||||
'1' => 'item 1',
|
||||
'2' => 'item 2',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertContains('<input type="radio" id="i1" class="btn-check" name="ToggleButtonGroupTestModel[value]" value="2" checked autocomplete="off">', $html);
|
||||
}
|
||||
}
|
||||
|
||||
class ToggleButtonGroupTestModel extends Model
|
||||
{
|
||||
public $value;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* @package yii2-bootstrap5
|
||||
* @author Simon Karlen <simi.albi@gmail.com>
|
||||
*/
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5;
|
||||
|
||||
use yii\bootstrap5\Alert;
|
||||
use yii\bootstrap5\Breadcrumbs;
|
||||
|
||||
class TranslationTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
$this->mockWebApplication([
|
||||
'language' => 'de-CH',
|
||||
'sourceLanguage' => 'en-US',
|
||||
'components' => [
|
||||
'i18n' => [
|
||||
'translations' => [
|
||||
'yii/bootstrap5*' => [
|
||||
'class' => 'yii\i18n\GettextMessageSource',
|
||||
'sourceLanguage' => 'en-US',
|
||||
'basePath' => '@yii/bootstrap5/messages',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testTranslatedAlert()
|
||||
{
|
||||
Alert::$counter = 0;
|
||||
$html = Alert::widget([
|
||||
'body' => '<strong>Heilige Guacamole!</strong> Das ist ein deutscher Test.',
|
||||
'options' => [
|
||||
'class' => ['alert-warning']
|
||||
]
|
||||
]);
|
||||
|
||||
$expectedHtml = <<<HTML
|
||||
<div id="w0" class="alert-warning alert alert-dismissible" role="alert">
|
||||
|
||||
<strong>Heilige Guacamole!</strong> Das ist ein deutscher Test.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Schliessen"></button>
|
||||
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
$this->assertEqualsWithoutLE($expectedHtml, $html);
|
||||
}
|
||||
|
||||
public function testTranslatedBreadcrumb()
|
||||
{
|
||||
Breadcrumbs::$counter = 0;
|
||||
$out = Breadcrumbs::widget([
|
||||
'links' => [
|
||||
['label' => 'Library', 'url' => '#'],
|
||||
['label' => 'Data']
|
||||
]
|
||||
]);
|
||||
|
||||
$expected = <<<HTML
|
||||
<nav aria-label="breadcrumb"><ol id="w0" class="breadcrumb"><li class="breadcrumb-item"><a href="/index.php">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="#">Library</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Data</li>
|
||||
</ol></nav>
|
||||
HTML;
|
||||
$this->assertEqualsWithoutLE($expected, $out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
// ensure we get report on all possible php errors
|
||||
error_reporting(-1);
|
||||
|
||||
const YII_ENABLE_ERROR_HANDLER = false;
|
||||
const YII_DEBUG = true;
|
||||
$_SERVER['SCRIPT_NAME'] = '/' . __DIR__;
|
||||
$_SERVER['SCRIPT_FILENAME'] = __FILE__;
|
||||
|
||||
require_once(__DIR__ . '/../vendor/autoload.php');
|
||||
require_once(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
|
||||
|
||||
Yii::setAlias('@yiiunit/extensions/bootstrap5', __DIR__);
|
||||
Yii::setAlias('@yii/bootstrap5', dirname(__DIR__) . '/src');
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5\data;
|
||||
|
||||
use yii\bootstrap5\ActiveField;
|
||||
|
||||
/**
|
||||
* A customized extension from ActiveField
|
||||
*
|
||||
* @see \yiiunit\extensions\bootstrap5\ActiveFieldTest::testHorizontalCssClassesOverride()
|
||||
*
|
||||
* @author Michael Härtl <haertl.mike@gmail.com>
|
||||
*/
|
||||
class ExtendedActiveField extends ActiveField
|
||||
{
|
||||
public ?array $horizontalCssClasses = [
|
||||
'offset' => 'col-md-offset-4',
|
||||
'label' => 'col-md-4',
|
||||
'wrapper' => 'col-md-6',
|
||||
'error' => 'col-md-3',
|
||||
'hint' => 'col-md-3',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5\data;
|
||||
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* Class Singer
|
||||
*
|
||||
* @author Daniel Gomez Pan <pana_1990@hotmail.com>
|
||||
*/
|
||||
class Singer extends Model
|
||||
{
|
||||
public $firstName;
|
||||
public $lastName;
|
||||
public $test;
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['lastName'], 'default', 'value' => 'Lennon'],
|
||||
[['lastName'], 'required'],
|
||||
[['underscore_style'], 'yii\captcha\CaptchaValidator'],
|
||||
[['test'], 'required', 'when' => function ($model) {
|
||||
return $model->firstName === 'cebe';
|
||||
}],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* @package yii2-bootstrap5
|
||||
* @author Simon Karlen <simi.albi@outlook.com>
|
||||
*/
|
||||
|
||||
namespace yiiunit\extensions\bootstrap5\data;
|
||||
|
||||
|
||||
use yii\base\Model;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
public $id;
|
||||
public $firstName;
|
||||
public $lastName;
|
||||
public $username;
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['id', 'integer'],
|
||||
[['firstName', 'lastName'], 'string'],
|
||||
['username', 'string', 'min' => 4],
|
||||
['password', 'string', 'min' => 8, 'max' => '20'],
|
||||
[['username', 'password'], 'required']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function attributeHints()
|
||||
{
|
||||
return [
|
||||
'username' => 'Your username must be at least 4 characters long',
|
||||
'password' => 'Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.'
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user