Update framework testing infrastructure and standards
- Add phpt test runner and suite for app functions - Introduce testing workflow to AGENT.md - Add tests for cache, content, context, helpers, hooks, plugins, rendering - Mount tests directory in dev container
This commit is contained in:
parent
33943a907b
commit
449e6f8e03
22 changed files with 909 additions and 7 deletions
45
devel/tests/helpers/extract_meta_description.phpt
Normal file
45
devel/tests/helpers/extract_meta_description.phpt
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
--TEST--
|
||||
extractMetaDescription: returns description from metadata fields or first content paragraph
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/content.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$dir = sys_get_temp_dir() . '/phpt_metadesc_' . getmypid();
|
||||
mkdir($dir);
|
||||
|
||||
// search_description takes priority
|
||||
echo extractMetaDescription($dir, ['search_description' => 'SEO description', 'summary' => 'Summary']) . "\n";
|
||||
|
||||
// summary is fallback when no search_description
|
||||
echo extractMetaDescription($dir, ['summary' => 'Page summary']) . "\n";
|
||||
|
||||
// null metadata, no content files
|
||||
echo (extractMetaDescription($dir, null) ?? 'null') . "\n";
|
||||
|
||||
// First paragraph from markdown (skips headings and short lines)
|
||||
file_put_contents("$dir/index.md", "# Title\n\nThis is the opening paragraph of the post.\n\nSecond paragraph.");
|
||||
echo extractMetaDescription($dir, null) . "\n";
|
||||
unlink("$dir/index.md");
|
||||
|
||||
// Heading-only markdown with no usable paragraph
|
||||
file_put_contents("$dir/index.md", "# Just a Heading\n\nShort.\n");
|
||||
echo (extractMetaDescription($dir, null) ?? 'null') . "\n";
|
||||
unlink("$dir/index.md");
|
||||
|
||||
// First <p> from HTML
|
||||
file_put_contents("$dir/index.html", "<h1>Title</h1><p>HTML paragraph text here.</p>");
|
||||
echo extractMetaDescription($dir, null) . "\n";
|
||||
unlink("$dir/index.html");
|
||||
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECT--
|
||||
SEO description
|
||||
Page summary
|
||||
null
|
||||
This is the opening paragraph of the post.
|
||||
null
|
||||
HTML paragraph text here.
|
||||
20
devel/tests/helpers/extract_raw_date_from_folder.phpt
Normal file
20
devel/tests/helpers/extract_raw_date_from_folder.phpt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
--TEST--
|
||||
extractRawDateFromFolder: extracts YYYY-MM-DD from date-prefixed folder names
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
echo extractRawDateFromFolder('2024-01-15-my-post') . "\n";
|
||||
echo extractRawDateFromFolder('2024-12-31-year-end') . "\n";
|
||||
echo (extractRawDateFromFolder('no-date-here') ?? 'null') . "\n";
|
||||
echo (extractRawDateFromFolder('') ?? 'null') . "\n";
|
||||
echo (extractRawDateFromFolder('2024-1-1-bad-format') ?? 'null') . "\n";
|
||||
echo (extractRawDateFromFolder('20240115-no-separators') ?? 'null') . "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
2024-01-15
|
||||
2024-12-31
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
49
devel/tests/helpers/extract_title.phpt
Normal file
49
devel/tests/helpers/extract_title.phpt
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
--TEST--
|
||||
extractTitle: extracts title from # heading in .md or <h1> in .html
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/content.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$dir = sys_get_temp_dir() . '/phpt_title_' . getmypid();
|
||||
mkdir($dir);
|
||||
|
||||
// No content files
|
||||
echo (extractTitle($dir) ?? 'null') . "\n";
|
||||
|
||||
// Markdown with # heading
|
||||
file_put_contents("$dir/index.md", "# My Great Post\n\nSome body text.");
|
||||
echo extractTitle($dir) . "\n";
|
||||
unlink("$dir/index.md");
|
||||
|
||||
// Markdown heading with extra whitespace
|
||||
file_put_contents("$dir/index.md", "# Spaced Title \n\nBody.");
|
||||
echo extractTitle($dir) . "\n";
|
||||
unlink("$dir/index.md");
|
||||
|
||||
// HTML with <h1>
|
||||
file_put_contents("$dir/index.html", "<h1>HTML Title</h1><p>Body</p>");
|
||||
echo extractTitle($dir) . "\n";
|
||||
unlink("$dir/index.html");
|
||||
|
||||
// HTML with attributes on h1
|
||||
file_put_contents("$dir/index.html", '<h1 class="main">Styled Title</h1>');
|
||||
echo extractTitle($dir) . "\n";
|
||||
unlink("$dir/index.html");
|
||||
|
||||
// Markdown without heading
|
||||
file_put_contents("$dir/index.md", "Just a paragraph, no heading.");
|
||||
echo (extractTitle($dir) ?? 'null') . "\n";
|
||||
unlink("$dir/index.md");
|
||||
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECT--
|
||||
null
|
||||
My Great Post
|
||||
Spaced Title
|
||||
HTML Title
|
||||
Styled Title
|
||||
null
|
||||
33
devel/tests/helpers/find_cover_image.phpt
Normal file
33
devel/tests/helpers/find_cover_image.phpt
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
--TEST--
|
||||
findCoverImage: finds cover.{ext} in directory, prefers first matching extension
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$dir = sys_get_temp_dir() . '/phpt_cover_' . getmypid();
|
||||
mkdir($dir);
|
||||
|
||||
// No cover image
|
||||
echo (findCoverImage($dir) ?? 'null') . "\n";
|
||||
|
||||
// cover.jpg
|
||||
touch("$dir/cover.jpg");
|
||||
echo findCoverImage($dir) . "\n";
|
||||
|
||||
// cover.webp added — jpg should still win (it's first in COVER_IMAGE_EXTENSIONS)
|
||||
touch("$dir/cover.webp");
|
||||
echo findCoverImage($dir) . "\n";
|
||||
|
||||
// Remove jpg — webp should now be found
|
||||
unlink("$dir/cover.jpg");
|
||||
echo findCoverImage($dir) . "\n";
|
||||
|
||||
array_map('unlink', glob("$dir/*"));
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECT--
|
||||
null
|
||||
cover.jpg
|
||||
cover.jpg
|
||||
cover.webp
|
||||
42
devel/tests/helpers/find_page_css.phpt
Normal file
42
devel/tests/helpers/find_page_css.phpt
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
--TEST--
|
||||
findPageCss: returns URL and hash for styles.css, null when absent
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$contentDir = sys_get_temp_dir() . '/phpt_css_' . getmypid();
|
||||
$pageDir = "$contentDir/blog/post";
|
||||
mkdir($pageDir, 0777, true);
|
||||
|
||||
// No styles.css
|
||||
echo (findPageCss($pageDir, $contentDir) ?? 'null') . "\n";
|
||||
|
||||
// Add styles.css
|
||||
file_put_contents("$pageDir/styles.css", 'body { color: red; }');
|
||||
$result = findPageCss($pageDir, $contentDir);
|
||||
echo $result['url'] . "\n";
|
||||
echo ($result['hash'] === md5_file("$pageDir/styles.css") ? 'hash ok' : 'hash mismatch') . "\n";
|
||||
|
||||
// Root-level page (no subpath)
|
||||
$rootCss = "$contentDir/styles.css";
|
||||
file_put_contents($rootCss, 'body {}');
|
||||
$result = findPageCss($contentDir, $contentDir);
|
||||
echo $result['url'] . "\n";
|
||||
|
||||
// Directory named styles.css is ignored
|
||||
unlink("$pageDir/styles.css");
|
||||
mkdir("$pageDir/styles.css");
|
||||
echo (findPageCss($pageDir, $contentDir) ?? 'null') . "\n";
|
||||
|
||||
rmdir("$pageDir/styles.css");
|
||||
unlink($rootCss);
|
||||
rmdir($pageDir);
|
||||
rmdir("$contentDir/blog");
|
||||
rmdir($contentDir);
|
||||
?>
|
||||
--EXPECT--
|
||||
null
|
||||
/blog/post/styles.css
|
||||
hash ok
|
||||
/styles.css
|
||||
null
|
||||
36
devel/tests/helpers/find_page_js.phpt
Normal file
36
devel/tests/helpers/find_page_js.phpt
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
--TEST--
|
||||
findPageJs: returns URL and hash for script.js, null when absent
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$contentDir = sys_get_temp_dir() . '/phpt_js_' . getmypid();
|
||||
$pageDir = "$contentDir/section/page";
|
||||
mkdir($pageDir, 0777, true);
|
||||
|
||||
// No script.js
|
||||
echo (findPageJs($pageDir, $contentDir) ?? 'null') . "\n";
|
||||
|
||||
// Add script.js
|
||||
file_put_contents("$pageDir/script.js", 'console.log("hi");');
|
||||
$result = findPageJs($pageDir, $contentDir);
|
||||
echo $result['url'] . "\n";
|
||||
echo ($result['hash'] === md5_file("$pageDir/script.js") ? 'hash ok' : 'hash mismatch') . "\n";
|
||||
|
||||
// Root-level page (no subpath)
|
||||
$rootJs = "$contentDir/script.js";
|
||||
file_put_contents($rootJs, '');
|
||||
$result = findPageJs($contentDir, $contentDir);
|
||||
echo $result['url'] . "\n";
|
||||
|
||||
unlink("$pageDir/script.js");
|
||||
unlink($rootJs);
|
||||
rmdir($pageDir);
|
||||
rmdir("$contentDir/section");
|
||||
rmdir($contentDir);
|
||||
?>
|
||||
--EXPECT--
|
||||
null
|
||||
/section/page/script.js
|
||||
hash ok
|
||||
/script.js
|
||||
28
devel/tests/helpers/find_pdf_file.phpt
Normal file
28
devel/tests/helpers/find_pdf_file.phpt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
--TEST--
|
||||
findPdfFile: finds first .pdf file in a directory
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$dir = sys_get_temp_dir() . '/phpt_pdf_' . getmypid();
|
||||
mkdir($dir);
|
||||
|
||||
// No PDF
|
||||
echo (findPdfFile($dir) ?? 'null') . "\n";
|
||||
|
||||
// One PDF
|
||||
touch("$dir/document.pdf");
|
||||
echo findPdfFile($dir) . "\n";
|
||||
|
||||
// Non-PDF files are ignored
|
||||
touch("$dir/image.jpg");
|
||||
touch("$dir/notes.txt");
|
||||
echo findPdfFile($dir) . "\n";
|
||||
|
||||
array_map('unlink', glob("$dir/*"));
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECT--
|
||||
null
|
||||
document.pdf
|
||||
document.pdf
|
||||
39
devel/tests/helpers/get_subdirectories.phpt
Normal file
39
devel/tests/helpers/get_subdirectories.phpt
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
--TEST--
|
||||
getSubdirectories: returns only subdirectory names, ignores files
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$dir = sys_get_temp_dir() . '/phpt_subdirs_' . getmypid();
|
||||
mkdir($dir);
|
||||
|
||||
// Empty directory
|
||||
$result = getSubdirectories($dir);
|
||||
echo (empty($result) ? 'empty' : 'not empty') . "\n";
|
||||
|
||||
// Non-existent directory
|
||||
echo count(getSubdirectories($dir . '/nope')) . "\n";
|
||||
|
||||
// Add subdirectories and a file
|
||||
mkdir("$dir/alpha");
|
||||
mkdir("$dir/beta");
|
||||
touch("$dir/file.txt");
|
||||
|
||||
$result = array_values(getSubdirectories($dir));
|
||||
sort($result);
|
||||
echo implode("\n", $result) . "\n";
|
||||
|
||||
// Files are not included
|
||||
echo in_array('file.txt', $result) ? "file included\n" : "file excluded\n";
|
||||
|
||||
unlink("$dir/file.txt");
|
||||
rmdir("$dir/alpha");
|
||||
rmdir("$dir/beta");
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECT--
|
||||
empty
|
||||
0
|
||||
alpha
|
||||
beta
|
||||
file excluded
|
||||
Loading…
Add table
Add a link
Reference in a new issue