mockRequest = $this->createMock(Request::class);
$this->mockResponse = $this->createMock(Response::class);
$this->mockConfig = $this->createMock(Config::class);
// Initialize PageHeader with mocked dependencies
$this->pageHeader = new PageHeader($this->mockRequest, $this->mockResponse, $this->mockConfig);
}
protected function tearDown(): void
{
$this->pageHeader = null;
$this->mockRequest = null;
$this->mockResponse = null;
$this->mockConfig = null;
parent::tearDown();
}
/**
* Test basic header generation with default settings
*/
public function testGenerateHeaderWithDefaults()
{
$this->mockConfig->method('get')
->willReturnMap([
['site_title', 'Test Site'],
['site_description', 'Test Description'],
['theme', 'default']
]);
$header = $this->pageHeader->generateHeader();
$this->assertNotEmpty($header);
$this->assertStringContainsString('Test Site', $header);
$this->assertStringContainsString('Test Description', $header);
$this->assertStringContainsString('', $header);
}
/**
* Test header generation with custom title
*/
public function testGenerateHeaderWithCustomTitle()
{
$customTitle = 'Custom Page Title';
$this->mockConfig->method('get')
->willReturnMap([
['site_title', 'Test Site'],
['site_description', 'Test Description'],
['theme', 'default']
]);
$header = $this->pageHeader->generateHeader($customTitle);
$this->assertStringContainsString($customTitle, $header);
$this->assertStringContainsString('Test Site', $header);
}
/**
* Test header generation with empty title
*/
public function testGenerateHeaderWithEmptyTitle()
{
$this->mockConfig->method('get')
->willReturnMap([
['site_title', 'Test Site'],
['site_description', 'Test Description'],
['theme', 'default']
]);
$header = $this->pageHeader->generateHeader('');
$this->assertStringContainsString('Test Site', $header);
$this->assertStringNotContainsString(' | ', $header);
}
/**
* Test header generation with null title
*/
public function testGenerateHeaderWithNullTitle()
{
$this->mockConfig->method('get')
->willReturnMap([
['site_title', 'Test Site'],
['site_description', 'Test Description'],
['theme', 'default']
]);
$header = $this->pageHeader->generateHeader(null);
$this->assertStringContainsString('Test Site', $header);
$this->assertNotEmpty($header);
}
/**
* Test meta tag generation
*/
public function testGenerateMetaTags()
{
$this->mockConfig->method('get')
->willReturnMap([
['site_description', 'Test Description'],
['site_keywords', 'test,keywords,site'],
['site_author', 'Test Author']
]);
$metaTags = $this->pageHeader->generateMetaTags();
$this->assertStringContainsString('name="description"', $metaTags);
$this->assertStringContainsString('Test Description', $metaTags);
$this->assertStringContainsString('name="keywords"', $metaTags);
$this->assertStringContainsString('test,keywords,site', $metaTags);
$this->assertStringContainsString('name="author"', $metaTags);
$this->assertStringContainsString('Test Author', $metaTags);
}
/**
* Test meta tag generation with missing configuration
*/
public function testGenerateMetaTagsWithMissingConfig()
{
$this->mockConfig->method('get')
->willReturn(null);
$metaTags = $this->pageHeader->generateMetaTags();
$this->assertStringContainsString('name="viewport"', $metaTags);
$this->assertStringContainsString('charset=', $metaTags);
}
/**
* Test CSS link generation
*/
public function testGenerateCssLinks()
{
$this->mockConfig->method('get')
->willReturnMap([
['theme', 'custom'],
['css_files', ['main.css', 'theme.css']],
['base_url', 'https://example.com']
]);
$cssLinks = $this->pageHeader->generateCssLinks();
$this->assertStringContainsString('rel="stylesheet"', $cssLinks);
$this->assertStringContainsString('main.css', $cssLinks);
$this->assertStringContainsString('theme.css', $cssLinks);
$this->assertStringContainsString('https://example.com', $cssLinks);
}
/**
* Test CSS link generation with empty CSS files
*/
public function testGenerateCssLinksWithEmptyFiles()
{
$this->mockConfig->method('get')
->willReturnMap([
['theme', 'default'],
['css_files', []],
['base_url', 'https://example.com']
]);
$cssLinks = $this->pageHeader->generateCssLinks();
$this->assertStringContainsString('rel="stylesheet"', $cssLinks);
$this->assertStringContainsString('default', $cssLinks);
}
/**
* Test JavaScript link generation
*/
public function testGenerateJsLinks()
{
$this->mockConfig->method('get')
->willReturnMap([
['js_files', ['main.js', 'utils.js']],
['base_url', 'https://example.com']
]);
$jsLinks = $this->pageHeader->generateJsLinks();
$this->assertStringContainsString('src=', $jsLinks);
$this->assertStringContainsString('main.js', $jsLinks);
$this->assertStringContainsString('utils.js', $jsLinks);
$this->assertStringContainsString('https://example.com', $jsLinks);
}
/**
* Test JavaScript link generation with no JS files
*/
public function testGenerateJsLinksWithNoFiles()
{
$this->mockConfig->method('get')
->willReturnMap([
['js_files', null],
['base_url', 'https://example.com']
]);
$jsLinks = $this->pageHeader->generateJsLinks();
$this->assertEmpty($jsLinks);
}
/**
* Test canonical URL generation
*/
public function testGenerateCanonicalUrl()
{
$this->mockRequest->method('getUri')
->willReturn('https://example.com/page');
$this->mockConfig->method('get')
->willReturnMap([
['canonical_url', true],
['base_url', 'https://example.com']
]);
$canonical = $this->pageHeader->generateCanonicalUrl();
$this->assertStringContainsString('rel="canonical"', $canonical);
$this->assertStringContainsString('https://example.com/page', $canonical);
}
/**
* Test canonical URL generation when disabled
*/
public function testGenerateCanonicalUrlWhenDisabled()
{
$this->mockConfig->method('get')
->willReturn(false);
$canonical = $this->pageHeader->generateCanonicalUrl();
$this->assertEmpty($canonical);
}
/**
* Test Open Graph meta tag generation
*/
public function testGenerateOpenGraphTags()
{
$this->mockConfig->method('get')
->willReturnMap([
['og_title', 'Test OG Title'],
['og_description', 'Test OG Description'],
['og_image', 'https://example.com/image.jpg'],
['og_url', 'https://example.com'],
['og_type', 'website']
]);
$ogTags = $this->pageHeader->generateOpenGraphTags();
$this->assertStringContainsString('property="og:title"', $ogTags);
$this->assertStringContainsString('Test OG Title', $ogTags);
$this->assertStringContainsString('property="og:description"', $ogTags);
$this->assertStringContainsString('Test OG Description', $ogTags);
$this->assertStringContainsString('property="og:image"', $ogTags);
$this->assertStringContainsString('https://example.com/image.jpg', $ogTags);
}
/**
* Test Twitter Card meta tag generation
*/
public function testGenerateTwitterCardTags()
{
$this->mockConfig->method('get')
->willReturnMap([
['twitter_card', 'summary'],
['twitter_site', '@testsite'],
['twitter_creator', '@testcreator'],
['twitter_title', 'Test Twitter Title'],
['twitter_description', 'Test Twitter Description'],
['twitter_image', 'https://example.com/twitter-image.jpg']
]);
$twitterTags = $this->pageHeader->generateTwitterCardTags();
$this->assertStringContainsString('name="twitter:card"', $twitterTags);
$this->assertStringContainsString('summary', $twitterTags);
$this->assertStringContainsString('name="twitter:site"', $twitterTags);
$this->assertStringContainsString('@testsite', $twitterTags);
$this->assertStringContainsString('name="twitter:creator"', $twitterTags);
$this->assertStringContainsString('@testcreator', $twitterTags);
}
/**
* Test favicon generation
*/
public function testGenerateFavicon()
{
$this->mockConfig->method('get')
->willReturnMap([
['favicon', 'favicon.ico'],
['base_url', 'https://example.com']
]);
$favicon = $this->pageHeader->generateFavicon();
$this->assertStringContainsString('rel="icon"', $favicon);
$this->assertStringContainsString('favicon.ico', $favicon);
$this->assertStringContainsString('https://example.com', $favicon);
}
/**
* Test favicon generation with no favicon configured
*/
public function testGenerateFaviconWithNone()
{
$this->mockConfig->method('get')
->willReturn(null);
$favicon = $this->pageHeader->generateFavicon();
$this->assertEmpty($favicon);
}
/**
* Test complete header generation with all components
*/
public function testGenerateCompleteHeader()
{
$this->mockConfig->method('get')
->willReturnMap([
['site_title', 'Complete Test Site'],
['site_description', 'Complete Test Description'],
['theme', 'complete'],
['css_files', ['main.css']],
['js_files', ['main.js']],
['canonical_url', true],
['og_title', 'Test OG Title'],
['twitter_card', 'summary'],
['favicon', 'favicon.ico'],
['base_url', 'https://example.com']
]);
$this->mockRequest->method('getUri')
->willReturn('https://example.com/complete');
$header = $this->pageHeader->generateCompleteHeader('Complete Page');
$this->assertStringContainsString('', $header);
$this->assertStringContainsString('Complete Page', $header);
$this->assertStringContainsString('Complete Test Site', $header);
$this->assertStringContainsString('rel="stylesheet"', $header);
$this->assertStringContainsString('main.css', $header);
$this->assertStringContainsString('main.js', $header);
$this->assertStringContainsString('rel="canonical"', $header);
$this->assertStringContainsString('property="og:title"', $header);
$this->assertStringContainsString('name="twitter:card"', $header);
$this->assertStringContainsString('rel="icon"', $header);
}
/**
* Test header generation with XSS protection
*/
public function testGenerateHeaderWithXssProtection()
{
$maliciousTitle = '';
$this->mockConfig->method('get')
->willReturnMap([
['site_title', 'Test Site'],
['site_description', 'Test Description'],
['theme', 'default']
]);
$header = $this->pageHeader->generateHeader($maliciousTitle);
$this->assertStringNotContainsString('