Completed
Push — master ( 6a7454...e111d0 )
by Dmitry
04:41
created

JsonEditorTest::testEditorWidgetWithScriptInJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace kdn\yii2;
4
5
use kdn\yii2\mocks\ModelMock;
6
use Yii;
7
use yii\widgets\ActiveForm;
8
9
/**
10
 * Class JsonEditorTest.
11
 * @package kdn\yii2
12
 */
13
class JsonEditorTest extends TestCase
14
{
15
    public static function assetProvider()
16
    {
17
        return [
18
            'production' => ['jsoneditor.min.css', 'jsoneditor-minimalist.min.js', 'jsoneditor.min.js'],
19
        ];
20
    }
21
22
    /**
23
     * @param string $css
24
     * @param string $minimalistJs
25
     * @param string $fullJs
26
     * @covers       \kdn\yii2\assets\JsonEditorAsset
27
     * @covers       \kdn\yii2\JsonEditor
28
     * @dataProvider assetProvider
29
     * @medium
30
     */
31
    public function testAsset($css, $minimalistJs, $fullJs)
32
    {
33
        $testWidgetAsset = function ($config, $assetName, $css, $js) {
34
            JsonEditor::widget($config);
35
            $bundles = Yii::$app->assetManager->bundles;
36
            $this->assertArrayHasKey($assetName, $bundles);
37
            $this->assertEquals([$css], $bundles[$assetName]->css);
38
            $this->assertEquals([$js], $bundles[$assetName]->js);
39
        };
40
41
        $fullAssetName = 'kdn\yii2\assets\JsonEditorFullAsset';
42
        $minimalistAssetName = 'kdn\yii2\assets\JsonEditorMinimalistAsset';
43
44
        $testWidgetAsset(['name' => 'data'], $minimalistAssetName, $css, $minimalistJs);
45
        static::mockWebApplication();
46
        $testWidgetAsset(['name' => 'data', 'clientOptions' => ['mode' => 'code']], $fullAssetName, $css, $fullJs);
47
        static::mockWebApplication();
48
        $testWidgetAsset(['name' => 'data', 'clientOptions' => ['modes' => ['code']]], $fullAssetName, $css, $fullJs);
49
    }
50
51
    public static function assetDevelopmentProvider()
52
    {
53
        return [
54
            'development' => ['jsoneditor.css', 'jsoneditor-minimalist.js', 'jsoneditor.js'],
55
        ];
56
    }
57
58
    /**
59
     * @param string $css
60
     * @param string $minimalistJs
61
     * @param string $fullJs
62
     * @covers       \kdn\yii2\assets\JsonEditorAsset
63
     * @covers       \kdn\yii2\JsonEditor
64
     * @dataProvider assetDevelopmentProvider
65
     * @medium
66
     */
67
    public function testAssetDevelopment($css, $minimalistJs, $fullJs)
68
    {
69
        if (!function_exists('runkit_constant_redefine')) {
70
            $this->markTestSkipped('runkit extension required.');
71
            return;
72
        }
73
74
        $yiiEnvDev = YII_ENV_DEV;
75
        runkit_constant_redefine('YII_ENV_DEV', true);
76
        $this->testAsset($css, $minimalistJs, $fullJs);
77
        runkit_constant_redefine('YII_ENV_DEV', $yiiEnvDev);
78
    }
79
80
    /**
81
     * @covers \kdn\yii2\JsonEditor
82
     * @uses   \kdn\yii2\assets\JsonEditorAsset
83
     * @medium
84
     */
85
    public function testEditorWidget()
86
    {
87
        $html = JsonEditor::widget(
88
            [
89
                'clientOptions' => [
90
                    'modes' => ['code', 'form', 'preview', 'text', 'tree', 'view'],
91
                    'mode' => 'view',
92
                    'onChange' => 'function () {console.log(this);}',
93
                    'onError' => 'function (error) {console.log(error);}',
94
                    'onModeChange' => 'function (nMode, oMode) {console.log(this, nMode, oMode);}',
95
                ],
96
                'collapseAll' => ['view'],
97
                'containerOptions' => ['class' => 'container'],
98
                'expandAll' => ['tree', 'form'],
99
                'name' => 'data',
100
                'options' => ['id' => 'data'],
101
            ]
102
        );
103
        $this->assertStringEqualsHtmlFile(__FUNCTION__, $html);
104
        $jsCodeBlock = reset(Yii::$app->view->js);
105
        $this->assertStringEqualsJsFile(__FUNCTION__, reset($jsCodeBlock));
106
    }
107
108
    /**
109
     * @covers \kdn\yii2\JsonEditor
110
     * @uses   \kdn\yii2\assets\JsonEditorAsset
111
     * @medium
112
     */
113
    public function testEditorWidgetWithScriptInJson()
114
    {
115
        $html = JsonEditor::widget(
116
            [
117
                'id' => 'data',
118
                'name' => 'data',
119
                'value' => '{"script":"<script>alert(\"XSS\");</script>"}',
120
            ]
121
        );
122
        $this->assertStringEqualsHtmlFile(__FUNCTION__, $html);
123
        $jsCodeBlock = reset(Yii::$app->view->js);
124
        $this->assertStringEqualsJsFile(__FUNCTION__, reset($jsCodeBlock));
125
    }
126
127
    public static function editorWidgetAndDefaultValueProvider()
128
    {
129
        return [
130
            '0' => ['0', '0'],
131
            'null' => ['null', 'null'],
132
            '""' => ['""', '""'],
133
            'empty string' => ['', 'default'],
134
        ];
135
    }
136
137
    /**
138
     * @param string $value
139
     * @param string $expectedResult
140
     * @covers       \kdn\yii2\JsonEditor
141
     * @uses         \kdn\yii2\assets\JsonEditorAsset
142
     * @dataProvider editorWidgetAndDefaultValueProvider
143
     * @medium
144
     */
145
    public function testEditorWidgetAndDefaultValue($value, $expectedResult)
146
    {
147
        $html = JsonEditor::widget(
148
            ['id' => 'data', 'name' => 'data', 'value' => $value, 'defaultValue' => '{"foo":"bar"}']
149
        );
150
        $fileRoot = __FUNCTION__ . '_' . $expectedResult;
151
        $this->assertStringEqualsHtmlFile($fileRoot, $html);
152
        $jsCodeBlock = reset(Yii::$app->view->js);
153
        $this->assertStringEqualsJsFile($fileRoot, reset($jsCodeBlock));
154
    }
155
156
    /**
157
     * @covers \kdn\yii2\JsonEditor
158
     * @uses   \kdn\yii2\assets\JsonEditorAsset
159
     * @medium
160
     */
161
    public function testEditorActiveWidgetAndDefaults()
162
    {
163
        $html = OutputHelper::catchOutput(
164
            function () {
165
                $form = ActiveForm::begin(['id' => 'data-form', 'action' => 'test', 'options' => ['csrf' => false]]);
166
                echo $form->field(new ModelMock, 'data')->widget(
167
                    'kdn\yii2\JsonEditor',
168
                    ['expandAll' => ['tree'], 'options' => ['class' => false]]
169
                );
170
                ActiveForm::end();
171
            }
172
        )['output'];
173
        $this->assertStringEqualsHtmlFile(__FUNCTION__, $html);
174
        $jsCodeBlock = reset(Yii::$app->view->js);
175
        $this->assertStringEqualsJsFile(__FUNCTION__, reset($jsCodeBlock));
176
    }
177
178
    /**
179
     * @covers \kdn\yii2\JsonEditor
180
     * @uses   \kdn\yii2\assets\JsonEditorAsset
181
     * @medium
182
     */
183
    public function testEditorActiveWidgetWithAttributeExpression()
184
    {
185
        $html = OutputHelper::catchOutput(
186
            function () {
187
                $model = new ModelMock;
188
                $model->data = ['{}', '{"foo":"bar"}'];
189
                $form = ActiveForm::begin(['id' => 'data-form', 'action' => 'test', 'options' => ['csrf' => false]]);
190
                echo $form->field($model, '[1]data[1]')->widget(
191
                    'kdn\yii2\JsonEditor',
192
                    ['options' => ['class' => false]]
193
                );
194
                ActiveForm::end();
195
            }
196
        )['output'];
197
        $this->assertStringEqualsHtmlFile(__FUNCTION__, $html);
198
        $jsCodeBlock = reset(Yii::$app->view->js);
199
        $this->assertStringEqualsJsFile(__FUNCTION__, reset($jsCodeBlock));
200
    }
201
202
    public static function editorActiveWidgetPrecedenceProvider()
203
    {
204
        return [
205
            'decoded value' => [
206
                ['precedence' => 1],
207
                '{"precedence":2}',
208
                '{"precedence":3}',
209
                '{"precedence":4}',
210
                '{"precedence":5}',
211
                1,
212
            ],
213
            'value' => [
214
                null,
215
                '{"precedence":2}',
216
                '{"precedence":3}',
217
                '{"precedence":4}',
218
                '{"precedence":5}',
219
                2,
220
            ],
221
            "options['inputOptions']['value']" => [
222
                null,
223
                '',
224
                '{"precedence":3}',
225
                '{"precedence":4}',
226
                '{"precedence":5}',
227
                3,
228
            ],
229
            'model data' => [
230
                null,
231
                '',
232
                null,
233
                '{"precedence":4}',
234
                '{"precedence":5}',
235
                4,
236
            ],
237
            'default value' => [
238
                null,
239
                '',
240
                null,
241
                null,
242
                '{"precedence":5}',
243
                5,
244
            ],
245
        ];
246
    }
247
248
    /**
249
     * @param mixed $decodedValue
250
     * @param null|string $value
251
     * @param null|string $inputOptionsValue
252
     * @param null|string $modelData
253
     * @param null|string $defaultValue
254
     * @param int $expectedResult
255
     * @covers       \kdn\yii2\JsonEditor
256
     * @uses         \kdn\yii2\assets\JsonEditorAsset
257
     * @dataProvider editorActiveWidgetPrecedenceProvider
258
     * @medium
259
     */
260
    public function testEditorActiveWidgetPrecedence(
261
        $decodedValue,
262
        $value,
263
        $inputOptionsValue,
264
        $modelData,
265
        $defaultValue,
266
        $expectedResult
267
    ) {
268
        $html = OutputHelper::catchOutput(
269
            function () use ($decodedValue, $value, $inputOptionsValue, $modelData, $defaultValue) {
270
                $model = new ModelMock;
271
                $model->data = ['{"foo":"bar"}', $modelData];
272
                $form = ActiveForm::begin(['id' => 'data-form', 'action' => 'test', 'options' => ['csrf' => false]]);
273
                echo $form->field($model, '[1]data[1]', ['inputOptions' => ['value' => $inputOptionsValue]])->widget(
274
                    'kdn\yii2\JsonEditor',
275
                    [
276
                        'decodedValue' => $decodedValue,
277
                        'value' => $value,
278
                        'defaultValue' => $defaultValue,
279
                        'options' => ['class' => false],
280
                    ]
281
                );
282
                ActiveForm::end();
283
            }
284
        )['output'];
285
        $fileRoot = __FUNCTION__ . '_' . $expectedResult;
286
        $this->assertStringEqualsHtmlFile($fileRoot, $html);
287
        $jsCodeBlock = reset(Yii::$app->view->js);
288
        $this->assertStringEqualsJsFile($fileRoot, reset($jsCodeBlock));
289
    }
290
}
291