[\s\r\n]*/';
/**
* Helper to be tested
*
* @var \Cake\View\Helper\HtmlHelper
*/
protected $Html;
/**
* Mocked view
*
* @var \Cake\View\View|\PHPUnit\Framework\MockObject\MockObject
*/
protected $View;
/**
* setUp method
*/
public function setUp(): void
{
parent::setUp();
$request = new ServerRequest([
'webroot' => '',
]);
Router::reload();
Router::setRequest($request);
$this->View = $this->getMockBuilder(View::class)
->onlyMethods(['append'])
->setConstructorArgs([$request])
->getMock();
$this->Html = new HtmlHelper($this->View);
$this->loadPlugins(['TestTheme']);
static::setAppNamespace();
Configure::write('Asset.timestamp', false);
$builder = Router::createRouteBuilder('/');
$builder->fallbacks(DashedRoute::class);
}
/**
* tearDown method
*/
public function tearDown(): void
{
parent::tearDown();
$this->clearPlugins();
unset($this->Html, $this->View);
}
/**
* testLink method
*/
public function testLink(): void
{
Router::reload();
$builder = Router::createRouteBuilder('/');
$builder->connect('/{controller}', ['action' => 'index']);
$builder->connect('/{controller}/{action}/*');
Router::setRequest(new ServerRequest());
$this->View->setRequest($this->View->getRequest()->withAttribute('webroot', ''));
$result = $this->Html->link('/home');
$expected = ['a' => ['href' => '/home'], 'preg:/\/home/', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link(['controller' => 'Users', 'action' => 'login', '<[You]>']);
$expected = [
'a' => ['href' => '/Users/login/%3C%5BYou%5D%3E'],
'preg:/\/Users\/login\/<\[You\]>/',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Posts', ['controller' => 'Posts', 'action' => 'index', '_full' => true]);
$expected = ['a' => ['href' => Router::fullBaseUrl() . '/Posts'], 'Posts', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Home', '/home', ['confirm' => 'Are you sure you want to do this?']);
$expected = [
'a' => [
'href' => '/home',
'data-confirm-message' => 'Are you sure you want to do this?',
'onclick' => 'if (confirm(this.dataset.confirmMessage)) { return true; } return false;',
],
'Home',
'/a',
];
$this->assertHtml($expected, $result);
$this->Html->setTemplates(['confirmJs' => 'if (confirm(this.dataset.confirmMessage)) { window.location="/";};']);
$result = $this->Html->link('Home', '/home', ['confirm' => 'Are you sure you want to do this?']);
$expected = [
'a' => [
'href' => '/home',
'data-confirm-message' => 'Are you sure you want to do this?',
'onclick' => 'preg:/if \(confirm\(this.dataset.confirmMessage\)\) \{ window\.location="\/";\};/',
],
'Home',
'/a',
];
$this->assertHtml($expected, $result);
$this->Html->setTemplates(['confirmJs' => '{{confirm}}']);
$result = $this->Html->link('Home', '/home', ['confirm' => 'Confirm\'s "nightmares"']);
$expected = [
'a' => [
'href' => '/home',
'data-confirm-message' => 'Confirm's "nightmares"',
'onclick' => 'if (confirm(this.dataset.confirmMessage)) { return true; } return false;',
],
'Home',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Home', '/home', ['onclick' => 'someFunction();']);
$expected = [
'a' => ['href' => '/home', 'onclick' => 'someFunction();'],
'Home',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#');
$expected = [
'a' => ['href' => '#'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#', ['escape' => true]);
$expected = [
'a' => ['href' => '#'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#', ['escape' => 'utf-8']);
$expected = [
'a' => ['href' => '#'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#', ['escape' => false]);
$expected = [
'a' => ['href' => '#'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#', [
'title' => 'to escape … or not escape?',
'escape' => false,
]);
$expected = [
'a' => ['href' => '#', 'title' => 'to escape … or not escape?'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#', [
'title' => 'to escape … or not escape?',
'escape' => true,
]);
$expected = [
'a' => ['href' => '#', 'title' => 'to escape … or not escape?'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Next >', '#', [
'title' => 'Next >',
'escapeTitle' => false,
]);
$expected = [
'a' => ['href' => '#', 'title' => 'Next >'],
'Next >',
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Original size', [
'controller' => 'Images', 'action' => 'view', 3, '?' => ['height' => 100, 'width' => 200],
]);
$expected = [
'a' => ['href' => '/Images/view/3?height=100&width=200'],
'Original size',
'/a',
];
$this->assertHtml($expected, $result);
Configure::write('Asset.timestamp', false);
$result = $this->Html->link($this->Html->image('test.gif'), '#', ['escape' => false]);
$expected = [
'a' => ['href' => '#'],
'img' => ['src' => 'img/test.gif', 'alt' => ''],
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link($this->Html->image('test.gif'), '#', [
'title' => 'hey "howdy"',
'escapeTitle' => false,
]);
$expected = [
'a' => ['href' => '#', 'title' => 'hey "howdy"'],
'img' => ['src' => 'img/test.gif', 'alt' => ''],
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->image('test.gif', ['url' => '#']);
$expected = [
'a' => ['href' => '#'],
'img' => ['src' => 'img/test.gif', 'alt' => ''],
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link($this->Html->image('../favicon.ico'), '#', ['escape' => false]);
$expected = [
'a' => ['href' => '#'],
'img' => ['src' => 'img/../favicon.ico', 'alt' => ''],
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->image('../favicon.ico', ['url' => '#']);
$expected = [
'a' => ['href' => '#'],
'img' => ['src' => 'img/../favicon.ico', 'alt' => ''],
'/a',
];
$this->assertHtml($expected, $result);
$result = $this->Html->link('http://www.example.org?param1=value1¶m2=value2');
$expected = ['a' => ['href' => 'http://www.example.org?param1=value1¶m2=value2'], 'http://www.example.org?param1=value1¶m2=value2', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('alert', 'javascript:alert(\'cakephp\');');
$expected = ['a' => ['href' => 'javascript:alert('cakephp');'], 'alert', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('write me', 'mailto:example@cakephp.org');
$expected = ['a' => ['href' => 'mailto:example@cakephp.org'], 'write me', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('call me on 0123465-798', 'tel:0123465-798');
$expected = ['a' => ['href' => 'tel:0123465-798'], 'call me on 0123465-798', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('text me on 0123465-798', 'sms:0123465-798');
$expected = ['a' => ['href' => 'sms:0123465-798'], 'text me on 0123465-798', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('say hello to 0123465-798', 'sms:0123465-798?body=hello there');
$expected = ['a' => ['href' => 'sms:0123465-798?body=hello there'], 'say hello to 0123465-798', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('say hello to 0123465-798', 'sms:0123465-798?body=hello "cakephp"');
$expected = ['a' => ['href' => 'sms:0123465-798?body=hello "cakephp"'], 'say hello to 0123465-798', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Home', '/', ['fullBase' => true]);
$expected = ['a' => ['href' => 'http://localhost/'], 'Home', '/a'];
$this->assertHtml($expected, $result);
$result = $this->Html->link('Home', '/', ['fullBase' => false]);
$expected = ['a' => ['href' => '/'], 'Home', '/a'];
$this->assertHtml($expected, $result);
}
public function testLinkFromPath(): void
{
$result = $this->Html->linkFromPath('Index', 'Articles::index');
$expected = 'Index';
$this->assertSame($result, $expected);
$result = $this->Html->linkFromPath('View', 'Articles::view', [3]);
$expected = 'View';
$this->assertSame($result, $expected);
}
/**
* testImageTag method
*/
public function testImageTag(): void
{
$builder = Router::createRouteBuilder('/');
$builder->connect('/:controller', ['action' => 'index']);
$builder->connect('/:controller/:action/*');
$result = $this->Html->image('test.gif');
$expected = ['img' => ['src' => 'img/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('http://google.com/logo.gif');
$expected = ['img' => ['src' => 'http://google.com/logo.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('//google.com/logo.gif');
$expected = ['img' => ['src' => '//google.com/logo.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image(['controller' => 'Test', 'action' => 'view', 1, '_ext' => 'gif']);
$expected = ['img' => ['src' => '/test/view/1.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('/test/view/1.gif');
$expected = ['img' => ['src' => '/test/view/1.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('cid:cakephp_logo');
$expected = ['img' => ['src' => 'cid:cakephp_logo', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('x:">');
$expected = ['img' => ['src' => 'x:"><script>alert(1)</script>', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('//google.com/">');
$expected = ['img' => ['src' => '//google.com/"><script>alert(1)</script>', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image([
'controller' => 'Images',
'action' => 'display',
'test',
'?' => ['one' => 'two', 'three' => 'four'],
]);
$expected = ['img' => ['src' => '/images/display/test?one=two&three=four', 'alt' => '']];
$this->assertHtml($expected, $result);
}
/**
* Ensure that data URIs don't get base paths set.
*/
public function testImageDataUriBaseDir(): void
{
$request = $this->View->getRequest()
->withAttribute('base', 'subdir')
->withAttribute('webroot', 'subdir/');
$this->View->setRequest($request);
Router::setRequest($request);
$data = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4' .
'/8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
$result = $this->Html->image($data);
$expected = ['img' => ['src' => $data, 'alt' => '']];
$this->assertHtml($expected, $result);
$data = 'data:image/png;base64,';
$result = $this->Html->image($data);
$expected = ['img' => ['src' => h($data), 'alt' => '']];
$this->assertHtml($expected, $result);
}
/**
* Test image() with query strings.
*/
public function testImageQueryString(): void
{
$result = $this->Html->image('test.gif?one=two&three=four');
$expected = ['img' => ['src' => 'img/test.gif?one=two&three=four', 'alt' => '']];
$this->assertHtml($expected, $result);
}
/**
* Test that image works with pathPrefix.
*/
public function testImagePathPrefix(): void
{
$result = $this->Html->image('test.gif', ['pathPrefix' => '/my/custom/path/']);
$expected = ['img' => ['src' => '/my/custom/path/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('test.gif', ['pathPrefix' => 'http://cakephp.org/assets/img/']);
$expected = ['img' => ['src' => 'http://cakephp.org/assets/img/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('test.gif', ['pathPrefix' => '//cakephp.org/assets/img/']);
$expected = ['img' => ['src' => '//cakephp.org/assets/img/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$previousConfig = Configure::read('App.imageBaseUrl');
Configure::write('App.imageBaseUrl', '//cdn.cakephp.org/img/');
$result = $this->Html->image('test.gif');
$expected = ['img' => ['src' => '//cdn.cakephp.org/img/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
Configure::write('App.imageBaseUrl', $previousConfig);
}
/**
* Test that image() works with fullBase and a webroot not equal to /
*/
public function testImageWithFullBase(): void
{
$result = $this->Html->image('test.gif', ['fullBase' => true]);
$here = $this->Html->Url->build('/', ['fullBase' => true]);
$expected = ['img' => ['src' => $here . 'img/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$result = $this->Html->image('sub/test.gif', ['fullBase' => true]);
$here = $this->Html->Url->build('/', ['fullBase' => true]);
$expected = ['img' => ['src' => $here . 'img/sub/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
$request = Router::getRequest()
->withAttribute('webroot', '/myproject/')
->withAttribute('base', '/myproject');
Router::setRequest($request);
$result = $this->Html->image('sub/test.gif', ['fullBase' => true]);
$expected = ['img' => ['src' => 'http://localhost/myproject/img/sub/test.gif', 'alt' => '']];
$this->assertHtml($expected, $result);
}
/**
* test image() with Asset.timestamp
*/
public function testImageWithTimestampping(): void
{
Configure::write('Asset.timestamp', 'force');
$request = Router::getRequest()->withAttribute('webroot', '/');
Router::setRequest($request);
$result = $this->Html->image('cake.icon.png');
$expected = ['img' => ['src' => 'preg:/\/img\/cake\.icon\.png\?\d+/', 'alt' => '']];
$this->assertHtml($expected, $result);
Configure::write('debug', false);
Configure::write('Asset.timestamp', 'force');
$result = $this->Html->image('cake.icon.png');
$expected = ['img' => ['src' => 'preg:/\/img\/cake\.icon\.png\?\d+/', 'alt' => '']];
$this->assertHtml($expected, $result);
$request = Router::getRequest()->withAttribute('webroot', '/testing/longer/');
Router::setRequest($request);
$result = $this->Html->image('cake.icon.png');
$expected = [
'img' => ['src' => 'preg:/\/testing\/longer\/img\/cake\.icon\.png\?[0-9]+/', 'alt' => ''],
];
$this->assertHtml($expected, $result);
}
/**
* Tests creation of an image tag using a theme and asset timestamping
*/
public function testImageTagWithTheme(): void
{
$this->skipIf(!is_writable(WWW_ROOT), 'Cannot write to webroot.');
$testfile = WWW_ROOT . 'test_theme/img/__cake_test_image.gif';
$fs = new Filesystem();
$fs->dumpFile($testfile, '');
Configure::write('Asset.timestamp', true);
Configure::write('debug', true);
$request = Router::getRequest()->withAttribute('webroot', '/');
Router::setRequest($request);
$this->Html->Url->getView()->setTheme('TestTheme');
$result = $this->Html->image('__cake_test_image.gif');
$expected = [
'img' => [
'src' => 'preg:/\/test_theme\/img\/__cake_test_image\.gif\?\d+/',
'alt' => '',
],
];
$this->assertHtml($expected, $result);
$request = Router::getRequest()->withAttribute('webroot', '/testing/');
Router::setRequest($request);
$result = $this->Html->image('__cake_test_image.gif');
$expected = [
'img' => [
'src' => 'preg:/\/testing\/test_theme\/img\/__cake_test_image\.gif\?\d+/',
'alt' => '',
],
];
$this->assertHtml($expected, $result);
// phpcs:ignore
@unlink($testfile);
}
/**
* test theme assets in main webroot path
*/
public function testThemeAssetsInMainWebrootPath(): void
{
Configure::write('App.wwwRoot', TEST_APP . 'webroot/');
$this->Html->Url->getView()->setTheme('TestTheme');
$result = $this->Html->css('webroot_test');
$expected = [
'link' => ['rel' => 'stylesheet', 'href' => 'preg:/.*test_theme\/css\/webroot_test\.css/'],
];
$this->assertHtml($expected, $result);
$this->Html->getView()->setTheme('TestTheme');
$result = $this->Html->css('theme_webroot');
$expected = [
'link' => ['rel' => 'stylesheet', 'href' => 'preg:/.*test_theme\/css\/theme_webroot\.css/'],
];
$this->assertHtml($expected, $result);
}
/**
* testStyle method
*/
public function testStyle(): void
{
$result = $this->Html->style(['display' => 'none', 'margin' => '10px']);
$this->assertSame('display:none; margin:10px;', $result);
$result = $this->Html->style(['display' => 'none', 'margin' => '10px'], false);
$this->assertSame("display:none;\nmargin:10px;", $result);
}
/**
* testCssLink method
*/
public function testCssLink(): void
{
$result = $this->Html->css('screen');
$expected = [
'link' => ['rel' => 'stylesheet', 'href' => 'preg:/.*css\/screen\.css/'],
];
$this->assertHtml($expected, $result);
$result = $this->Html->css('screen.css', ['once' => false]);
$this->assertHtml($expected, $result);
$this->loadPlugins(['TestPlugin']);
$result = $this->Html->css('TestPlugin.style', ['plugin' => false]);
$expected['link']['href'] = 'preg:/.*css\/TestPlugin\.style\.css/';
$this->assertHtml($expected, $result);
$this->removePlugins(['TestPlugin']);
$result = $this->Html->css('my.css.library');
$expected['link']['href'] = 'preg:/.*css\/my\.css\.library\.css/';
$this->assertHtml($expected, $result);
$result = $this->Html->css('screen.css?1234');
$expected['link']['href'] = 'preg:/.*css\/screen\.css\?1234/';
$this->assertHtml($expected, $result);
$result = $this->Html->css('screen.css?with=param&other=param');
$expected['link']['href'] = 'css/screen.css?with=param&other=param';
$this->assertHtml($expected, $result);
$result = $this->Html->css('x:">');
$expected['link']['href'] = 'x:"><script>alert(1)</script>';
$this->assertHtml($expected, $result);
$result = $this->Html->css('http://whatever.com/screen.css?1234&a=b');
$expected['link']['href'] = 'http://whatever.com/screen.css?1234&a=b';
$this->assertHtml($expected, $result);
Configure::write('App.cssBaseUrl', '//cdn.cakephp.org/css/');
$result = $this->Html->css('cake.generic');
$expected['link']['href'] = '//cdn.cakephp.org/css/cake.generic.css';
$this->assertHtml($expected, $result);
$result = $this->Html->css('//example.com/css/cake.generic.css');
$expected['link']['href'] = 'preg:/.*example\.com\/css\/cake\.generic\.css/';
$this->assertHtml($expected, $result);
$result = explode("\n", trim($this->Html->css(['cake', 'vendor.generic'])));
$expected['link']['href'] = 'preg:/.*css\/cake\.css/';
$this->assertHtml($expected, $result[0]);
$expected['link']['href'] = 'preg:/.*css\/vendor\.generic\.css/';
$this->assertHtml($expected, $result[1]);
$this->assertCount(2, $result);
$this->View->expects($this->exactly(2))
->method('append')
->withConsecutive(
['css', $this->matchesRegularExpression('/css_in_head.css/')],
['css', $this->matchesRegularExpression('/more_css_in_head.css/')]
);
$result = $this->Html->css('css_in_head', ['block' => true]);
$this->assertNull($result);
$result = $this->Html->css('more_css_in_head', ['block' => true]);
$this->assertNull($result);
$result = $this->Html->css('import-screen', ['rel' => 'import']);
$expected = [
'