mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-10-31 02:28:35 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			303 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @link https://www.yiiframework.com/
 | |
|  * @copyright Copyright (c) 2008 Yii Software LLC
 | |
|  * @license https://www.yiiframework.com/license/
 | |
|  */
 | |
| 
 | |
| namespace yiiunit\framework\helpers;
 | |
| 
 | |
| use yii\helpers\Json;
 | |
| use yii\web\JsExpression;
 | |
| use yiiunit\framework\web\Post;
 | |
| use yiiunit\framework\models\JsonModel;
 | |
| use yiiunit\TestCase;
 | |
| 
 | |
| /**
 | |
|  * @group helpers
 | |
|  * @coversDefaultClass \yii\helpers\Json
 | |
|  */
 | |
| class JsonTest extends TestCase
 | |
| {
 | |
|     protected function setUp(): void
 | |
|     {
 | |
|         parent::setUp();
 | |
| 
 | |
|         // destroy application, helper must work without Yii::$app
 | |
|         $this->destroyApplication();
 | |
|     }
 | |
| 
 | |
|     public function testEncode()
 | |
|     {
 | |
|         // Arrayable data encoding
 | |
|         $dataArrayable = $this->getMockBuilder('\yii\base\Arrayable')->getMock();
 | |
|         $dataArrayable->method('toArray')->willReturn([]);
 | |
|         $actual = Json::encode($dataArrayable);
 | |
|         $this->assertSame('[]', $actual);
 | |
| 
 | |
|         // basic data encoding
 | |
|         $data = '1';
 | |
|         $this->assertSame('"1"', Json::encode($data));
 | |
| 
 | |
|         // simple array encoding
 | |
|         $data = [1, 2];
 | |
|         $this->assertSame('[1,2]', Json::encode($data));
 | |
|         $data = ['a' => 1, 'b' => 2];
 | |
|         $this->assertSame('{"a":1,"b":2}', Json::encode($data));
 | |
| 
 | |
|         // simple object encoding
 | |
|         $data = (object) ['a' => 1, 'b' => 2];
 | |
|         $this->assertSame('{"a":1,"b":2}', Json::encode($data));
 | |
| 
 | |
|         // simple object with zero indexed keys encoding
 | |
|         $data = (object) [
 | |
|             0 => 1,
 | |
|             1 => 2
 | |
|         ];
 | |
|         $default = Json::$keepObjectType;
 | |
|         Json::$keepObjectType = true;
 | |
|         $this->assertSame('{"0":1,"1":2}', Json::encode($data));
 | |
|         Json::$keepObjectType = false;
 | |
|         $this->assertSame('[1,2]', Json::encode($data));
 | |
|         Json::$keepObjectType = $default;
 | |
| 
 | |
|         // empty data encoding
 | |
|         $data = [];
 | |
|         $this->assertSame('[]', Json::encode($data));
 | |
|         $data = new \stdClass();
 | |
|         $this->assertSame('{}', Json::encode($data));
 | |
| 
 | |
|         // expression encoding
 | |
|         $expression = 'function () {}';
 | |
|         $data = new JsExpression($expression);
 | |
|         $this->assertSame($expression, Json::encode($data));
 | |
| 
 | |
|         // complex data
 | |
|         $expression1 = 'function (a) {}';
 | |
|         $expression2 = 'function (b) {}';
 | |
|         $data = [
 | |
|             'a' => [1, new JsExpression($expression1)],
 | |
|             'b' => new JsExpression($expression2),
 | |
|         ];
 | |
|         $this->assertSame("{\"a\":[1,$expression1],\"b\":$expression2}", Json::encode($data));
 | |
| 
 | |
|         // https://github.com/yiisoft/yii2/issues/957
 | |
|         $data = (object) null;
 | |
|         $this->assertSame('{}', Json::encode($data));
 | |
| 
 | |
|         // JsonSerializable
 | |
|         $data = new JsonModel();
 | |
|         $this->assertSame('{"json":"serializable"}', Json::encode($data));
 | |
|         // https://github.com/yiisoft/yii2/issues/12043
 | |
|         $data = new JsonModel();
 | |
|         $data->data = [];
 | |
|         $this->assertSame('[]', Json::encode($data));
 | |
|         $data = new JsonModel();
 | |
|         $data->data = (object) null;
 | |
|         $this->assertSame('{}', Json::encode($data));
 | |
| 
 | |
|         // Generator (Only supported since PHP 5.5)
 | |
|         if (PHP_VERSION_ID >= 50500) {
 | |
|             $data = eval(<<<'PHP'
 | |
|                 return function () {
 | |
|                     foreach (['a' => 1, 'b' => 2] as $name => $value) {
 | |
|                         yield $name => $value;
 | |
|                     }
 | |
|                 };
 | |
| PHP
 | |
|             );
 | |
|             $this->assertSame('{"a":1,"b":2}', Json::encode($data()));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function testHtmlEncode()
 | |
|     {
 | |
|         // HTML escaped chars
 | |
|         $data = '&<>"\'/';
 | |
|         $this->assertSame('"\u0026\u003C\u003E\u0022\u0027\/"', Json::htmlEncode($data));
 | |
| 
 | |
|         // basic data encoding
 | |
|         $data = '1';
 | |
|         $this->assertSame('"1"', Json::htmlEncode($data));
 | |
| 
 | |
|         // simple array encoding
 | |
|         $data = [1, 2];
 | |
|         $this->assertSame('[1,2]', Json::htmlEncode($data));
 | |
|         $data = ['a' => 1, 'b' => 2];
 | |
|         $this->assertSame('{"a":1,"b":2}', Json::htmlEncode($data));
 | |
| 
 | |
|         // simple object encoding
 | |
|         $data = (object) ['a' => 1, 'b' => 'c'];
 | |
|         $this->assertSame('{"a":1,"b":"c"}', Json::htmlEncode($data));
 | |
| 
 | |
|         // expression encoding
 | |
|         $expression = 'function () {}';
 | |
|         $data = new JsExpression($expression);
 | |
|         $this->assertSame($expression, Json::htmlEncode($data));
 | |
| 
 | |
|         // complex data
 | |
|         $expression1 = 'function (a) {}';
 | |
|         $expression2 = 'function (b) {}';
 | |
|         $data = [
 | |
|             'a' => [1, new JsExpression($expression1)],
 | |
|             'b' => new JsExpression($expression2),
 | |
|         ];
 | |
|         $this->assertSame("{\"a\":[1,$expression1],\"b\":$expression2}", Json::htmlEncode($data));
 | |
| 
 | |
|         // https://github.com/yiisoft/yii2/issues/957
 | |
|         $data = (object) null;
 | |
|         $this->assertSame('{}', Json::htmlEncode($data));
 | |
| 
 | |
|         // JsonSerializable
 | |
|         $data = new JsonModel();
 | |
|         $this->assertSame('{"json":"serializable"}', Json::htmlEncode($data));
 | |
| 
 | |
|         // https://github.com/yiisoft/yii2/issues/10278
 | |
|         $xml = '<?xml version="1.0" encoding="UTF-8"?>
 | |
| <file>
 | |
|   <apiKey>ieu2iqw4o</apiKey>
 | |
|   <methodProperties>
 | |
|     <FindByString>Kiev</FindByString>
 | |
|   </methodProperties>
 | |
| </file>';
 | |
| 
 | |
|         $document = simplexml_load_string($xml);
 | |
|         $this->assertSame('{"apiKey":"ieu2iqw4o","methodProperties":{"FindByString":"Kiev"}}', Json::encode($document));
 | |
| 
 | |
|         // SimpleXMLElement with empty tag
 | |
|         $xml = '<?xml version="1.0" encoding="UTF-8"?>
 | |
| <parent>
 | |
|   <child1/>
 | |
|   <child2>
 | |
|     <subElement>sub</subElement>
 | |
|   </child2>
 | |
| </parent>';
 | |
| 
 | |
|         $document = simplexml_load_string($xml);
 | |
|         $this->assertSame('{"child1":{},"child2":{"subElement":"sub"}}', Json::encode($document));
 | |
| 
 | |
|         $postsStack = new \SplStack();
 | |
|         $postsStack->push(new Post(915, 'record1'));
 | |
|         $postsStack->push(new Post(456, 'record2'));
 | |
| 
 | |
|         $this->assertSame('{"1":{"id":456,"title":"record2"},"0":{"id":915,"title":"record1"}}', Json::encode($postsStack));
 | |
|     }
 | |
| 
 | |
|     public function testDecode()
 | |
|     {
 | |
|         // empty value
 | |
|         $json = '';
 | |
|         $actual = Json::decode($json);
 | |
|         $this->assertNull($actual);
 | |
| 
 | |
|         // basic data decoding
 | |
|         $json = '"1"';
 | |
|         $this->assertSame('1', Json::decode($json));
 | |
| 
 | |
|         // array decoding
 | |
|         $json = '{"a":1,"b":2}';
 | |
|         $this->assertSame(['a' => 1, 'b' => 2], Json::decode($json));
 | |
| 
 | |
|         // exception
 | |
|         $json = '{"a":1,"b":2';
 | |
|         $this->expectException('\yii\base\InvalidArgumentException');
 | |
|         Json::decode($json);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @covers ::decode
 | |
|      */
 | |
|     public function testDecodeInvalidArgumentException()
 | |
|     {
 | |
|         $this->expectException(\yii\base\InvalidArgumentException::class);
 | |
|         $this->expectExceptionMessage('Invalid JSON data.');
 | |
|         
 | |
|         Json::decode([]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @covers ::decode
 | |
|      */
 | |
|     public function testHandleJsonError()
 | |
|     {
 | |
|         // basic syntax error
 | |
|         try {
 | |
|             $json = "{'a': '1'}";
 | |
|             Json::decode($json);
 | |
|         } catch (\yii\base\InvalidArgumentException $e) {
 | |
|             $this->assertSame(Json::$jsonErrorMessages['JSON_ERROR_SYNTAX'], $e->getMessage());
 | |
|         }
 | |
| 
 | |
|         // unsupported type since PHP 5.5
 | |
|         try {
 | |
|             $fp = fopen('php://stdin', 'r');
 | |
|             $data = ['a' => $fp];
 | |
|             Json::encode($data);
 | |
|             fclose($fp);
 | |
|         } catch (\yii\base\InvalidArgumentException $e) {
 | |
|             if (PHP_VERSION_ID >= 50500) {
 | |
|                 $this->assertSame(Json::$jsonErrorMessages['JSON_ERROR_UNSUPPORTED_TYPE'], $e->getMessage());
 | |
|             } else {
 | |
|                 $this->assertSame(Json::$jsonErrorMessages['JSON_ERROR_SYNTAX'], $e->getMessage());
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function testErrorSummary()
 | |
|     {
 | |
|         $model = new JsonModel();
 | |
|         $model->name = 'not_an_integer';
 | |
|         $model->addError('name', 'Error message. Here are some chars: < >');
 | |
|         $model->addError('name', 'Error message. Here are even more chars: ""');
 | |
|         $model->validate(null, false);
 | |
|         $options = ['showAllErrors' => true];
 | |
|         $expectedHtml = '["Error message. Here are some chars: < >","Error message. Here are even more chars: \"\""]';
 | |
|         $this->assertEquals($expectedHtml, Json::errorSummary($model, $options));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @see https://github.com/yiisoft/yii2/issues/17760
 | |
|      * @covers ::encode
 | |
|      */
 | |
|     public function testEncodeDateTime()
 | |
|     {
 | |
|         $input = new \DateTime('October 12, 2014', new \DateTimeZone('UTC'));
 | |
|         $output = Json::encode($input);
 | |
|         $this->assertEquals('{"date":"2014-10-12 00:00:00.000000","timezone_type":3,"timezone":"UTC"}', $output);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @covers ::encode
 | |
|      */
 | |
|     public function testPrettyPrint()
 | |
|     {
 | |
|         $defaultValue = Json::$prettyPrint;
 | |
|         $input = ['a' => 1, 'b' => 2];
 | |
|         $defOutput = '{"a":1,"b":2}';
 | |
|         $ppOutput = "{\n    \"a\": 1,\n    \"b\": 2\n}";
 | |
| 
 | |
|         // Test unchanged options
 | |
|         Json::$prettyPrint = null;
 | |
|         $output = Json::encode($input, 320);
 | |
|         $this->assertEquals($defOutput, $output);
 | |
|         $output = Json::encode($input, 448);
 | |
|         $this->assertEquals($ppOutput, $output);
 | |
| 
 | |
|         // Test pretty print enabled
 | |
|         Json::$prettyPrint = true;
 | |
|         $output = Json::encode($input, 320);
 | |
|         $this->assertEquals($ppOutput, $output);
 | |
|         $output = Json::encode($input, 448);
 | |
|         $this->assertEquals($ppOutput, $output);
 | |
| 
 | |
|         // Test pretty print disabled
 | |
|         Json::$prettyPrint = false;
 | |
|         $output = Json::encode($input, 320);
 | |
|         $this->assertEquals($defOutput, $output);
 | |
|         $output = Json::encode($input, 448);
 | |
|         $this->assertEquals($defOutput, $output);
 | |
| 
 | |
|         Json::$prettyPrint = $defaultValue;
 | |
|     }
 | |
| }
 | 
