Browse Source

Merge branch 'master' into 3.next

Mark Story 8 years ago
parent
commit
2dd4bdf37c

+ 2 - 1
src/Controller/Component/PaginatorComponent.php

@@ -187,9 +187,10 @@ class PaginatorComponent extends Component
             $query->applyOptions($options);
             $query->applyOptions($options);
         }
         }
 
 
+        $cleanQuery = clone $query;
         $results = $query->all();
         $results = $query->all();
         $numResults = count($results);
         $numResults = count($results);
-        $count = $numResults ? $query->count() : 0;
+        $count = $numResults ? $cleanQuery->count() : 0;
 
 
         $defaults = $this->getDefaults($alias, $settings);
         $defaults = $this->getDefaults($alias, $settings);
         unset($defaults[0]);
         unset($defaults[0]);

+ 2 - 1
src/Database/Schema/MysqlSchema.php

@@ -406,7 +406,8 @@ class MysqlSchema extends BaseSchema
         }
         }
         $addAutoIncrement = (
         $addAutoIncrement = (
             [$name] == (array)$schema->primaryKey() &&
             [$name] == (array)$schema->primaryKey() &&
-            !$schema->hasAutoincrement()
+            !$schema->hasAutoincrement() &&
+            !isset($data['autoIncrement'])
         );
         );
         if (in_array($data['type'], [TableSchema::TYPE_INTEGER, TableSchema::TYPE_BIGINTEGER]) &&
         if (in_array($data['type'], [TableSchema::TYPE_INTEGER, TableSchema::TYPE_BIGINTEGER]) &&
             ($data['autoIncrement'] === true || $addAutoIncrement)
             ($data['autoIncrement'] === true || $addAutoIncrement)

+ 2 - 2
src/Http/Client/Request.php

@@ -153,7 +153,7 @@ class Request extends Message implements RequestInterface
      * @param array $headers The headers to add.
      * @param array $headers The headers to add.
      * @return void
      * @return void
      */
      */
-    protected function addHeaders($headers)
+    protected function addHeaders(array $headers)
     {
     {
         foreach ($headers as $key => $val) {
         foreach ($headers as $key => $val) {
             $normalized = strtolower($key);
             $normalized = strtolower($key);
@@ -256,5 +256,5 @@ class Request extends Message implements RequestInterface
     }
     }
 }
 }
 
 
-// @deprecated Add backwards compat alias.
+// @deprecated Add backwards compact alias.
 class_alias('Cake\Http\Client\Request', 'Cake\Network\Http\Request');
 class_alias('Cake\Http\Client\Request', 'Cake\Network\Http\Request');

+ 28 - 26
src/Http/ServerRequestFactory.php

@@ -151,52 +151,54 @@ abstract class ServerRequestFactory extends BaseFactory
      */
      */
     protected static function getBase($uri, $server)
     protected static function getBase($uri, $server)
     {
     {
-        $base = $webroot = $baseUrl = null;
-        $config = Configure::read('App');
-        extract($config);
+        $config = (array)Configure::read('App') + [
+            'base' => null,
+            'webroot' => null,
+            'baseUrl' => null
+        ];
 
 
-        if ($base !== false && $base !== null) {
-            return [$base, $base . '/'];
+        if ($config['base'] !== false && $config['base'] !== null) {
+            return [$config['base'], $config['base'] . '/'];
         }
         }
 
 
-        if (!$baseUrl) {
-            $base = dirname(Hash::get($server, 'PHP_SELF'));
+        if (!$config['baseUrl']) {
+            $config['base'] = dirname(Hash::get($server, 'PHP_SELF'));
             // Clean up additional / which cause following code to fail..
             // Clean up additional / which cause following code to fail..
-            $base = preg_replace('#/+#', '/', $base);
+            $config['base'] = preg_replace('#/+#', '/', $config['base']);
 
 
-            $indexPos = strpos($base, '/' . $webroot . '/index.php');
+            $indexPos = strpos($config['base'], '/' . $config['webroot'] . '/index.php');
             if ($indexPos !== false) {
             if ($indexPos !== false) {
-                $base = substr($base, 0, $indexPos) . '/' . $webroot;
+                $config['base'] = substr($config['base'], 0, $indexPos) . '/' . $config['webroot'];
             }
             }
-            if ($webroot === basename($base)) {
-                $base = dirname($base);
+            if ($config['webroot'] === basename($config['base'])) {
+                $config['base'] = dirname($config['base']);
             }
             }
 
 
-            if ($base === DIRECTORY_SEPARATOR || $base === '.') {
-                $base = '';
+            if ($config['base'] === DIRECTORY_SEPARATOR || $config['base'] === '.') {
+                $config['base'] = '';
             }
             }
-            $base = implode('/', array_map('rawurlencode', explode('/', $base)));
+            $config['base'] = implode('/', array_map('rawurlencode', explode('/', $config['base'])));
 
 
-            return [$base, $base . '/'];
+            return [$config['base'], $config['base'] . '/'];
         }
         }
 
 
-        $file = '/' . basename($baseUrl);
-        $base = dirname($baseUrl);
+        $file = '/' . basename($config['baseUrl']);
+        $config['base'] = dirname($config['baseUrl']);
 
 
-        if ($base === DIRECTORY_SEPARATOR || $base === '.') {
-            $base = '';
+        if ($config['base'] === DIRECTORY_SEPARATOR || $config['base'] === '.') {
+            $config['base'] = '';
         }
         }
-        $webrootDir = $base . '/';
+        $webrootDir = $config['base'] . '/';
 
 
         $docRoot = Hash::get($server, 'DOCUMENT_ROOT');
         $docRoot = Hash::get($server, 'DOCUMENT_ROOT');
-        $docRootContainsWebroot = strpos($docRoot, $webroot);
+        $docRootContainsWebroot = strpos($docRoot, $config['webroot']);
 
 
-        if (!empty($base) || !$docRootContainsWebroot) {
-            if (strpos($webrootDir, '/' . $webroot . '/') === false) {
-                $webrootDir .= $webroot . '/';
+        if (!empty($config['base']) || !$docRootContainsWebroot) {
+            if (strpos($webrootDir, '/' . $config['webroot'] . '/') === false) {
+                $webrootDir .= $config['webroot'] . '/';
             }
             }
         }
         }
 
 
-        return [$base . $file, $webrootDir];
+        return [$config['base'] . $file, $webrootDir];
     }
     }
 }
 }

+ 9 - 4
src/Log/Engine/BaseLog.php

@@ -15,6 +15,7 @@
 namespace Cake\Log\Engine;
 namespace Cake\Log\Engine;
 
 
 use Cake\Core\InstanceConfigTrait;
 use Cake\Core\InstanceConfigTrait;
+use Cake\Datasource\EntityInterface;
 use JsonSerializable;
 use JsonSerializable;
 use Psr\Log\AbstractLogger;
 use Psr\Log\AbstractLogger;
 
 
@@ -93,14 +94,18 @@ abstract class BaseLog extends AbstractLogger
             return $data;
             return $data;
         }
         }
 
 
-        $object = is_object($data);
+        $isObject = is_object($data);
 
 
-        if ($object && method_exists($data, '__toString')) {
+        if ($isObject && $data instanceof EntityInterface) {
+            return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+        }
+
+        if ($isObject && method_exists($data, '__toString')) {
             return (string)$data;
             return (string)$data;
         }
         }
 
 
-        if ($object && $data instanceof JsonSerializable) {
-            return json_encode($data);
+        if ($isObject && $data instanceof JsonSerializable) {
+            return json_encode($data, JSON_UNESCAPED_UNICODE);
         }
         }
 
 
         return print_r($data, true);
         return print_r($data, true);

+ 6 - 2
src/Shell/Helper/ProgressHelper.php

@@ -113,17 +113,19 @@ class ProgressHelper extends Helper
      * Increment the progress bar.
      * Increment the progress bar.
      *
      *
      * @param int $num The amount of progress to advance by.
      * @param int $num The amount of progress to advance by.
-     * @return void
+     * @return $this
      */
      */
     public function increment($num = 1)
     public function increment($num = 1)
     {
     {
         $this->_progress = min(max(0, $this->_progress + $num), $this->_total);
         $this->_progress = min(max(0, $this->_progress + $num), $this->_total);
+
+        return $this;
     }
     }
 
 
     /**
     /**
      * Render the progress bar based on the current state.
      * Render the progress bar based on the current state.
      *
      *
-     * @return void
+     * @return $this;
      */
      */
     public function draw()
     public function draw()
     {
     {
@@ -143,5 +145,7 @@ class ProgressHelper extends Helper
         $bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT);
         $bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT);
 
 
         $this->_io->overwrite($bar, 0);
         $this->_io->overwrite($bar, 0);
+
+        return $this;
     }
     }
 }
 }

+ 2 - 2
src/Template/Error/missing_action.ctp

@@ -32,13 +32,13 @@ if (isset($controller)) {
     $baseClass = $namespace . '\Controller\AppController';
     $baseClass = $namespace . '\Controller\AppController';
     $extends = 'AppController';
     $extends = 'AppController';
     $type = 'Controller';
     $type = 'Controller';
-    $class = $controller;
+    $class = Inflector::camelize($controller);
 }
 }
 // Mailer MissingActionException support
 // Mailer MissingActionException support
 if (isset($mailer)) {
 if (isset($mailer)) {
     $baseClass = 'Cake\Mailer\Mailer';
     $baseClass = 'Cake\Mailer\Mailer';
     $type = $extends = 'Mailer';
     $type = $extends = 'Mailer';
-    $class = $mailer;
+    $class = Inflector::camelize($mailer);
 }
 }
 
 
 if (empty($plugin)) {
 if (empty($plugin)) {

+ 2 - 0
src/Template/Error/missing_controller.ctp

@@ -14,11 +14,13 @@
  */
  */
 use Cake\Core\Plugin;
 use Cake\Core\Plugin;
 use Cake\Core\Configure;
 use Cake\Core\Configure;
+use Cake\Utility\Inflector;
 
 
 $pluginDot = empty($plugin) ? null : $plugin . '.';
 $pluginDot = empty($plugin) ? null : $plugin . '.';
 $namespace = Configure::read('App.namespace');
 $namespace = Configure::read('App.namespace');
 $prefixNs = '';
 $prefixNs = '';
 $prefixPath = '';
 $prefixPath = '';
+$class = Inflector::camelize($class);
 
 
 if (!empty($prefix)) {
 if (!empty($prefix)) {
     $prefix = array_map('\Cake\Utility\Inflector::camelize', explode('/', $prefix));
     $prefix = array_map('\Cake\Utility\Inflector::camelize', explode('/', $prefix));

+ 33 - 1
tests/TestCase/Controller/Component/PaginatorComponentTest.php

@@ -19,6 +19,7 @@ use Cake\Controller\Component\PaginatorComponent;
 use Cake\Controller\Controller;
 use Cake\Controller\Controller;
 use Cake\Core\Configure;
 use Cake\Core\Configure;
 use Cake\Datasource\ConnectionManager;
 use Cake\Datasource\ConnectionManager;
+use Cake\Datasource\EntityInterface;
 use Cake\Http\ServerRequest;
 use Cake\Http\ServerRequest;
 use Cake\Network\Exception\NotFoundException;
 use Cake\Network\Exception\NotFoundException;
 use Cake\ORM\Entity;
 use Cake\ORM\Entity;
@@ -47,7 +48,10 @@ class PaginatorComponentTest extends TestCase
      *
      *
      * @var array
      * @var array
      */
      */
-    public $fixtures = ['core.posts'];
+    public $fixtures = [
+        'core.posts', 'core.articles', 'core.articles_tags',
+        'core.authors', 'core.authors_tags', 'core.tags'
+    ];
 
 
     /**
     /**
      * Don't load data for fixtures for all tests
      * Don't load data for fixtures for all tests
@@ -203,6 +207,34 @@ class PaginatorComponentTest extends TestCase
     }
     }
 
 
     /**
     /**
+     * Test that nested eager loaders don't trigger invalid SQL errors.
+     *
+     * @return void
+     */
+    public function testPaginateNestedEagerLoader()
+    {
+        $this->loadFixtures('Articles', 'Tags', 'Authors', 'ArticlesTags', 'AuthorsTags');
+        $articles = TableRegistry::get('Articles');
+        $articles->belongsToMany('Tags');
+        $tags = TableRegistry::get('Tags');
+        $tags->belongsToMany('Authors');
+
+        $articles->eventManager()->on('Model.beforeFind', function ($event, $query) {
+            $query ->matching('Tags', function ($q) {
+                return $q->matching('Authors', function ($q) {
+                    return $q->where(['Authors.name' => 'larry']);
+                });
+            });
+        });
+        $results = $this->Paginator->paginate($articles, []);
+
+        $result = $results->first();
+        $this->assertInstanceOf(EntityInterface::class, $result);
+        $this->assertInstanceOf(EntityInterface::class, $result->_matchingData['Tags']);
+        $this->assertInstanceOf(EntityInterface::class, $result->_matchingData['Authors']);
+    }
+
+    /**
      * test that flat default pagination parameters work.
      * test that flat default pagination parameters work.
      *
      *
      * @return void
      * @return void

+ 5 - 0
tests/TestCase/Database/Schema/MysqlSchemaTest.php

@@ -630,6 +630,11 @@ SQL;
             ],
             ],
             [
             [
                 'post_id',
                 'post_id',
+                ['type' => 'integer', 'length' => 20, 'null' => false, 'autoIncrement' => false],
+                '`post_id` INTEGER(20) NOT NULL'
+            ],
+            [
+                'post_id',
                 ['type' => 'biginteger', 'length' => 20, 'autoIncrement' => true],
                 ['type' => 'biginteger', 'length' => 20, 'autoIncrement' => true],
                 '`post_id` BIGINT AUTO_INCREMENT'
                 '`post_id` BIGINT AUTO_INCREMENT'
             ],
             ],

+ 34 - 0
tests/TestCase/Error/ExceptionRendererTest.php

@@ -550,6 +550,27 @@ class ExceptionRendererTest extends TestCase
     }
     }
 
 
     /**
     /**
+     * test missingController method
+     *
+     * @return void
+     */
+    public function testMissingControllerLowerCase()
+    {
+        $exception = new MissingControllerException([
+            'class' => 'posts',
+            'prefix' => '',
+            'plugin' => '',
+        ]);
+        $ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
+
+        $result = $ExceptionRenderer->render()->body();
+
+        $this->assertEquals('missingController', $ExceptionRenderer->template);
+        $this->assertContains('Missing Controller', $result);
+        $this->assertContains('<em>PostsController</em>', $result);
+    }
+
+    /**
      * Returns an array of tests to run for the various Cake Exception classes.
      * Returns an array of tests to run for the various Cake Exception classes.
      *
      *
      * @return array
      * @return array
@@ -559,6 +580,19 @@ class ExceptionRendererTest extends TestCase
         return [
         return [
             [
             [
                 new MissingActionException([
                 new MissingActionException([
+                    'controller' => 'postsController',
+                    'action' => 'index',
+                    'prefix' => '',
+                    'plugin' => '',
+                ]),
+                [
+                    '/Missing Method in PostsController/',
+                    '/<em>PostsController::index\(\)<\/em>/'
+                ],
+                404
+            ],
+            [
+                new MissingActionException([
                     'controller' => 'PostsController',
                     'controller' => 'PostsController',
                     'action' => 'index',
                     'action' => 'index',
                     'prefix' => '',
                     'prefix' => '',

+ 40 - 4
tests/TestCase/Http/Client/RequestTest.php

@@ -22,6 +22,7 @@ use Zend\Diactoros\Uri;
  */
  */
 class RequestTest extends TestCase
 class RequestTest extends TestCase
 {
 {
+
     /**
     /**
      * test string ata, header and constructor
      * test string ata, header and constructor
      *
      *
@@ -37,10 +38,44 @@ class RequestTest extends TestCase
         $request = new Request('http://example.com', 'POST', $headers, json_encode($data));
         $request = new Request('http://example.com', 'POST', $headers, json_encode($data));
 
 
         $this->assertEquals('http://example.com', $request->url());
         $this->assertEquals('http://example.com', $request->url());
-        $this->assertEquals('POST', $request->getMethod());
+        $this->assertContains($request->getMethod(), 'POST');
         $this->assertEquals('application/json', $request->getHeaderLine('Content-Type'));
         $this->assertEquals('application/json', $request->getHeaderLine('Content-Type'));
         $this->assertEquals(json_encode($data), $request->body());
         $this->assertEquals(json_encode($data), $request->body());
     }
     }
+    /**
+     * @param array $headers The HTTP headers to set.
+     * @param array|string|null $data The request body to use.
+     * @param string $method The HTTP method to use.
+     *
+     * @dataProvider additionProvider
+     */
+    public function testMethods(array $headers, $data, $method)
+    {
+        $request = new Request('http://example.com', $method, $headers, json_encode($data));
+
+        $this->assertEquals($request->getMethod(), $method);
+        $this->assertEquals('http://example.com', $request->url());
+        $this->assertEquals('application/json', $request->getHeaderLine('Content-Type'));
+        $this->assertEquals(json_encode($data), $request->body());
+    }
+    /**
+     * @dataProvider additionProvider
+     */
+    public function additionProvider()
+    {
+        $headers = [
+            'Content-Type' => 'application/json',
+            'Authorization' => 'Bearer valid-token',
+        ];
+        $data = ['a' => 'b', 'c' => 'd'];
+
+        return [
+            [$headers, $data, Request::METHOD_POST],
+            [$headers, $data, Request::METHOD_GET],
+            [$headers, $data, Request::METHOD_PUT],
+            [$headers, $data, Request::METHOD_DELETE],
+        ];
+    }
 
 
     /**
     /**
      * test array data, header and constructor
      * test array data, header and constructor
@@ -128,7 +163,7 @@ class RequestTest extends TestCase
     }
     }
 
 
     /**
     /**
-     * test method interop.
+     * test method interoperability.
      *
      *
      * @return void
      * @return void
      */
      */
@@ -136,6 +171,7 @@ class RequestTest extends TestCase
     {
     {
         $request = new Request();
         $request = new Request();
         $this->assertSame($request, $request->method(Request::METHOD_GET));
         $this->assertSame($request, $request->method(Request::METHOD_GET));
+
         $this->assertEquals(Request::METHOD_GET, $request->method());
         $this->assertEquals(Request::METHOD_GET, $request->method());
         $this->assertEquals(Request::METHOD_GET, $request->getMethod());
         $this->assertEquals(Request::METHOD_GET, $request->getMethod());
 
 
@@ -293,13 +329,13 @@ class RequestTest extends TestCase
     {
     {
         $request = new Request();
         $request = new Request();
         $result = $request->version('1.0');
         $result = $request->version('1.0');
-        $this->assertSame($request, $request, 'Should return self');
+        $this->assertSame($request, $result, 'Should return self');
 
 
         $this->assertSame('1.0', $request->version());
         $this->assertSame('1.0', $request->version());
     }
     }
 
 
     /**
     /**
-     * test version interop.
+     * test version Interoperable.
      *
      *
      * @return void
      * @return void
      */
      */

+ 135 - 0
tests/TestCase/Log/Engine/BaseLogTest.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         t.b.d.
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Test\TestCase\Log\Engine;
+
+use Cake\Log\Engine\BaseLog;
+use Cake\ORM\Entity;
+use Cake\TestSuite\TestCase;
+use Psr\Log\LogLevel;
+
+/**
+ * Class BaseLogImpl
+ * Implementation of abstract class {@see Cake\Log\Engine\BaseLog},
+ * required by test case {@see Cake\Test\TestCase\Log\Engine\BaseLogTest}.
+ */
+class BaseLogImpl extends BaseLog
+{
+    /**
+     * Logs with an arbitrary level.
+     *
+     * @param mixed $level
+     * @param mixed $message
+     * @param array $context
+     *
+     * @return mixed
+     */
+    public function log($level, $message, array $context = [])
+    {
+        return $this->_format($message, $context);
+    }
+}
+
+class BaseLogTest extends TestCase
+{
+
+    private $testData = ['ä', 'ö', 'ü'];
+
+    private $logger;
+
+    /**
+     * Setting up the test case.
+     * Creates a stub logger implementing the log() function missing from abstract class BaseLog.
+     */
+    public function setUp()
+    {
+        parent::setUp();
+
+        $this->logger = new BaseLogImpl();
+    }
+
+    private function assertUnescapedUnicode(array $needles, $haystack)
+    {
+        foreach ($needles as $needle) {
+            $this->assertContains(
+                $needle,
+                $haystack,
+                'Formatted log message does not contain unescaped unicode character.'
+            );
+        }
+    }
+
+    /**
+     * Tests the logging output of a single string containing unicode characters.
+     */
+    public function testLogUnicodeString()
+    {
+        $logged = $this->logger->log(LogLevel::INFO, implode($this->testData));
+
+        $this->assertUnescapedUnicode($this->testData, $logged);
+    }
+
+    /**
+     * Tests the logging output of an array containing unicode characters.
+     */
+    public function testLogUnicodeArray()
+    {
+        $logged = $this->logger->log(LogLevel::INFO, $this->testData);
+
+        $this->assertUnescapedUnicode($this->testData, $logged);
+    }
+
+    /**
+     * Tests the logging output of an object implementing __toString().
+     * Note: __toString() will return a single string containing unicode characters.
+     */
+    public function testLogUnicodeObjectToString()
+    {
+        $stub = $this->getMockBuilder(\stdClass::class)
+            ->setMethods(['__toString'])
+            ->getMock();
+        $stub->method('__toString')
+            ->willReturn(implode($this->testData));
+
+        $logged = $this->logger->log(LogLevel::INFO, $stub);
+
+        $this->assertUnescapedUnicode($this->testData, $logged);
+    }
+
+    /**
+     * Tests the logging output of an object implementing jsonSerializable().
+     * Note: jsonSerializable() will return an array containing unicode characters.
+     */
+    public function testLogUnicodeObjectJsonSerializable()
+    {
+        $stub = $this->createMock(\JsonSerializable::class);
+        $stub->method('jsonSerialize')
+            ->willReturn($this->testData);
+
+        $logged = $this->logger->log(LogLevel::INFO, $stub);
+
+        $this->assertUnescapedUnicode($this->testData, $logged);
+    }
+
+    /**
+     * Tests the logging output of an entity with property value that contains unicode characters.
+     */
+    public function testLogUnicodeEntity()
+    {
+        $entity = new Entity(['foo' => implode($this->testData)]);
+
+        $logged = $this->logger->log(LogLevel::INFO, $entity);
+
+        $this->assertUnescapedUnicode($this->testData, $logged);
+    }
+}

+ 4 - 4
tests/TestCase/ORM/TableTest.php

@@ -1430,7 +1430,7 @@ class TableTest extends TestCase
         $table = new \TestApp\Model\Table\ArticlesTable([
         $table = new \TestApp\Model\Table\ArticlesTable([
             'connection' => $this->connection,
             'connection' => $this->connection,
         ]);
         ]);
-        $result = $table->find('all')->contain(['authors'])->first();
+        $result = $table->find('all')->contain(['Authors'])->first();
         $this->assertInstanceOf('TestApp\Model\Entity\Author', $result->author);
         $this->assertInstanceOf('TestApp\Model\Entity\Author', $result->author);
     }
     }
 
 
@@ -1445,7 +1445,7 @@ class TableTest extends TestCase
         $table = new \TestApp\Model\Table\ArticlesTable([
         $table = new \TestApp\Model\Table\ArticlesTable([
             'connection' => $this->connection,
             'connection' => $this->connection,
         ]);
         ]);
-        $result = $table->find('all')->contain(['authors' => ['articles']])->first();
+        $result = $table->find('all')->contain(['Authors' => ['Articles']])->first();
         $this->assertCount(2, $result->author->articles);
         $this->assertCount(2, $result->author->articles);
         foreach ($result->author->articles as $article) {
         foreach ($result->author->articles as $article) {
             $this->assertInstanceOf('TestApp\Model\Entity\Article', $article);
             $this->assertInstanceOf('TestApp\Model\Entity\Article', $article);
@@ -1463,7 +1463,7 @@ class TableTest extends TestCase
         $table = new \TestApp\Model\Table\ArticlesTable([
         $table = new \TestApp\Model\Table\ArticlesTable([
             'connection' => $this->connection,
             'connection' => $this->connection,
         ]);
         ]);
-        $result = $table->find('all')->contain(['tags'])->first();
+        $result = $table->find('all')->contain(['Tags'])->first();
         $this->assertInstanceOf('TestApp\Model\Entity\Tag', $result->tags[0]);
         $this->assertInstanceOf('TestApp\Model\Entity\Tag', $result->tags[0]);
         $this->assertInstanceOf(
         $this->assertInstanceOf(
             'TestApp\Model\Entity\ArticlesTag',
             'TestApp\Model\Entity\ArticlesTag',
@@ -1481,7 +1481,7 @@ class TableTest extends TestCase
         $table = new \TestApp\Model\Table\ArticlesTable([
         $table = new \TestApp\Model\Table\ArticlesTable([
             'connection' => $this->connection,
             'connection' => $this->connection,
         ]);
         ]);
-        $results = $table->find('all')->contain(['tags', 'authors'])->toArray();
+        $results = $table->find('all')->contain(['Tags', 'Authors'])->toArray();
         $this->assertCount(3, $results);
         $this->assertCount(3, $results);
         foreach ($results as $article) {
         foreach ($results as $article) {
             $this->assertFalse($article->dirty('id'));
             $this->assertFalse($article->dirty('id'));

+ 26 - 0
tests/TestCase/Shell/Helper/ProgressHelperTest.php

@@ -151,6 +151,32 @@ class ProgressHelperTest extends TestCase
     }
     }
 
 
     /**
     /**
+     * Test using the helper chained.
+     *
+     * @return void
+     */
+    public function testIncrementAndRenderChained()
+    {
+        $this->helper->init()
+            ->increment(20)
+            ->draw()
+            ->increment(40)
+            ->draw()
+            ->increment(40)
+            ->draw();
+
+        $expected = [
+            '',
+            '==============>                                                              20%',
+            '',
+            '============================================>                                60%',
+            '',
+            '==========================================================================> 100%',
+        ];
+        $this->assertEquals($expected, $this->stub->messages());
+    }
+
+    /**
      * Test negative numbers
      * Test negative numbers
      *
      *
      * @return void
      * @return void

+ 27 - 24
tests/TestCase/TestSuite/IntegrationTestCaseTest.php

@@ -180,11 +180,11 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         $this->get('/request_action/test_request_action');
         $this->get('/request_action/test_request_action');
         $this->assertNotEmpty($this->_response);
         $this->assertNotEmpty($this->_response);
         $this->assertInstanceOf('Cake\Http\Response', $this->_response);
         $this->assertInstanceOf('Cake\Http\Response', $this->_response);
-        $this->assertEquals('This is a test', $this->_response->body());
+        $this->assertEquals('This is a test', $this->_response->getBody());
 
 
         $this->_response = null;
         $this->_response = null;
         $this->get('/get/request_action/test_request_action');
         $this->get('/get/request_action/test_request_action');
-        $this->assertEquals('This is a test', $this->_response->body());
+        $this->assertEquals('This is a test', $this->_response->getBody());
     }
     }
 
 
     /**
     /**
@@ -197,7 +197,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         $this->useHttpServer(true);
         $this->useHttpServer(true);
         $this->get('/get/request_action/test_request_action');
         $this->get('/get/request_action/test_request_action');
         $this->assertResponseOk();
         $this->assertResponseOk();
-        $this->assertEquals('This is a test', $this->_response->body());
+        $this->assertEquals('This is a test', $this->_response->getBody());
     }
     }
 
 
     /**
     /**
@@ -229,7 +229,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         $this->get('/request_action/test_request_action');
         $this->get('/request_action/test_request_action');
         $this->assertNotEmpty($this->_response);
         $this->assertNotEmpty($this->_response);
         $this->assertInstanceOf('Cake\Http\Response', $this->_response);
         $this->assertInstanceOf('Cake\Http\Response', $this->_response);
-        $this->assertEquals('This is a test', $this->_response->body());
+        $this->assertEquals('This is a test', $this->_response->getBody());
         $this->assertHeader('X-Middleware', 'true');
         $this->assertHeader('X-Middleware', 'true');
     }
     }
 
 
@@ -276,7 +276,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         $this->useHttpServer(true);
         $this->useHttpServer(true);
 
 
         $this->post('/request_action/post_pass', ['title' => 'value']);
         $this->post('/request_action/post_pass', ['title' => 'value']);
-        $data = json_decode($this->_response->body());
+        $data = json_decode($this->_response->getBody());
         $this->assertEquals('value', $data->title);
         $this->assertEquals('value', $data->title);
         $this->assertHeader('X-Middleware', 'true');
         $this->assertHeader('X-Middleware', 'true');
     }
     }
@@ -291,7 +291,10 @@ class IntegrationTestCaseTest extends IntegrationTestCase
         $this->useHttpServer(true);
         $this->useHttpServer(true);
 
 
         $this->post('/request_action/input_test', '{"hello":"world"}');
         $this->post('/request_action/input_test', '{"hello":"world"}');
-        $this->assertSame('world', $this->_response->body());
+        if ($this->_response->getBody()->isSeekable()) {
+            $this->_response->getBody()->rewind();
+        }
+        $this->assertSame('world', $this->_response->getBody()->getContents());
         $this->assertHeader('X-Middleware', 'true');
         $this->assertHeader('X-Middleware', 'true');
     }
     }
 
 
@@ -627,34 +630,34 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
 
 
-        $this->_response->statusCode(200);
+        $this->_response = $this->_response->withStatus(200);
         $this->assertResponseOk();
         $this->assertResponseOk();
 
 
-        $this->_response->statusCode(201);
+        $this->_response = $this->_response->withStatus(201);
         $this->assertResponseOk();
         $this->assertResponseOk();
 
 
-        $this->_response->statusCode(204);
+        $this->_response = $this->_response->withStatus(204);
         $this->assertResponseOk();
         $this->assertResponseOk();
 
 
-        $this->_response->statusCode(202);
+        $this->_response = $this->_response->withStatus(202);
         $this->assertResponseSuccess();
         $this->assertResponseSuccess();
 
 
-        $this->_response->statusCode(302);
+        $this->_response = $this->_response->withStatus(302);
         $this->assertResponseSuccess();
         $this->assertResponseSuccess();
 
 
-        $this->_response->statusCode(400);
+        $this->_response = $this->_response->withStatus(400);
         $this->assertResponseError();
         $this->assertResponseError();
 
 
-        $this->_response->statusCode(417);
+        $this->_response = $this->_response->withStatus(417);
         $this->assertResponseError();
         $this->assertResponseError();
 
 
-        $this->_response->statusCode(500);
+        $this->_response = $this->_response->withStatus(500);
         $this->assertResponseFailure();
         $this->assertResponseFailure();
 
 
-        $this->_response->statusCode(505);
+        $this->_response = $this->_response->withStatus(505);
         $this->assertResponseFailure();
         $this->assertResponseFailure();
 
 
-        $this->_response->statusCode(301);
+        $this->_response = $this->_response->withStatus(301);
         $this->assertResponseCode(301);
         $this->assertResponseCode(301);
     }
     }
 
 
@@ -666,7 +669,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertRedirect()
     public function testAssertRedirect()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->header('Location', 'http://localhost/tasks/index');
+        $this->_response = $this->_response->withHeader('Location', 'http://localhost/tasks/index');
 
 
         $this->assertRedirect();
         $this->assertRedirect();
         $this->assertRedirect('/tasks/index');
         $this->assertRedirect('/tasks/index');
@@ -709,7 +712,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertRedirectContains()
     public function testAssertRedirectContains()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->header('Location', 'http://localhost/tasks/index');
+        $this->_response = $this->_response->withHeader('Location', 'http://localhost/tasks/index');
 
 
         $this->assertRedirectContains('/tasks/index');
         $this->assertRedirectContains('/tasks/index');
     }
     }
@@ -722,7 +725,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertHeader()
     public function testAssertHeader()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->header('Etag', 'abc123');
+        $this->_response = $this->_response->withHeader('Etag', 'abc123');
 
 
         $this->assertHeader('Etag', 'abc123');
         $this->assertHeader('Etag', 'abc123');
     }
     }
@@ -735,7 +738,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertHeaderContains()
     public function testAssertHeaderContains()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->header('Etag', 'abc123');
+        $this->_response = $this->_response->withHeader('Etag', 'abc123');
 
 
         $this->assertHeaderContains('Etag', 'abc');
         $this->assertHeaderContains('Etag', 'abc');
     }
     }
@@ -775,7 +778,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertResponseContains()
     public function testAssertResponseContains()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->body('Some content');
+        $this->_response = $this->_response->withStringBody('Some content');
 
 
         $this->assertResponseContains('content');
         $this->assertResponseContains('content');
     }
     }
@@ -788,7 +791,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertResponseNotContains()
     public function testAssertResponseNotContains()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->body('Some content');
+        $this->_response = $this->_response->withStringBody('Some content');
 
 
         $this->assertResponseNotContains('contents');
         $this->assertResponseNotContains('contents');
     }
     }
@@ -801,7 +804,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertResponseRegExp()
     public function testAssertResponseRegExp()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->body('Some content');
+        $this->_response = $this->_response->withStringBody('Some content');
 
 
         $this->assertResponseRegExp('/cont/');
         $this->assertResponseRegExp('/cont/');
     }
     }
@@ -826,7 +829,7 @@ class IntegrationTestCaseTest extends IntegrationTestCase
     public function testAssertResponseNotRegExp()
     public function testAssertResponseNotRegExp()
     {
     {
         $this->_response = new Response();
         $this->_response = new Response();
-        $this->_response->body('Some content');
+        $this->_response = $this->_response->withStringBody('Some content');
 
 
         $this->assertResponseNotRegExp('/cant/');
         $this->assertResponseNotRegExp('/cant/');
     }
     }

+ 2 - 2
tests/test_app/TestApp/Model/Table/ArticlesTable.php

@@ -22,8 +22,8 @@ class ArticlesTable extends Table
 
 
     public function initialize(array $config)
     public function initialize(array $config)
     {
     {
-        $this->belongsTo('authors');
-        $this->belongsToMany('tags');
+        $this->belongsTo('Authors');
+        $this->belongsToMany('Tags');
         $this->hasMany('ArticlesTags');
         $this->hasMany('ArticlesTags');
     }
     }
 
 

+ 2 - 2
tests/test_app/TestApp/Model/Table/ArticlesTagsTable.php

@@ -22,7 +22,7 @@ class ArticlesTagsTable extends Table
 
 
     public function initialize(array $config)
     public function initialize(array $config)
     {
     {
-        $this->belongsTo('articles');
-        $this->belongsTo('tags');
+        $this->belongsTo('Articles');
+        $this->belongsTo('Tags');
     }
     }
 }
 }

+ 2 - 2
tests/test_app/TestApp/Model/Table/TagsTable.php

@@ -22,8 +22,8 @@ class TagsTable extends Table
 
 
     public function initialize(array $config)
     public function initialize(array $config)
     {
     {
-        $this->belongsTo('authors');
-        $this->belongsToMany('articles');
+        $this->belongsTo('Authors');
+        $this->belongsToMany('Articles');
         $this->hasMany('ArticlesTags', ['propertyName' => 'extraInfo']);
         $this->hasMany('ArticlesTags', ['propertyName' => 'extraInfo']);
     }
     }
 }
 }