Add PHP unit tests and page tests.
Run "composer install", then "composer test".
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
namespace Xxx\Tests\Unit;
|
||||
|
||||
use Xxx\Tests\Support\SiteData;
|
||||
use Xxx\Tests\Support\TestCase;
|
||||
|
||||
// display_stories() in get_data.lib.php
|
||||
class DisplayStoriesTest extends TestCase {
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
$GLOBALS['num_stories'] = 5;
|
||||
SiteData::install(array(
|
||||
'xxx' => array(
|
||||
array('id' => 1, 'title' => 'First <em>title</em>', 'author' => 'Ann & "Bo"', 'date' => '2020-01-02 03:04:05',
|
||||
'story' => '<p onclick="steal()">One <script>alert(1)</script>hundred</p>'),
|
||||
array('id' => 2, 'title' => 'Second', 'author' => 'Cy', 'date' => '2020-01-01 10:00:00', 'story' => '<p>Two</p>'),
|
||||
array('id' => 3, 'title' => 'Picture', 'author' => 'Di', 'date' => '2019-12-31 10:00:00', 'story' => '',
|
||||
'img' => 'PNG', 'mime' => 'image/png', 'hidden' => '1'),
|
||||
),
|
||||
'queue' => array(
|
||||
array('id' => 20, 'title' => 'Waiting', 'author' => 'Ed', 'date' => '2020-02-01 10:00:00'),
|
||||
),
|
||||
));
|
||||
open_db('open');
|
||||
}
|
||||
|
||||
public function testListsStoriesWithEscapedFields(): void {
|
||||
$page = display_stories();
|
||||
$this->assertStringStartsWith('<ul class="article-list">', $page);
|
||||
$this->assertSame(2, substr_count($page, '<li class="box">'));
|
||||
$this->assertStringContainsString('<a href="/article?id=1">First <em>title</em></a>', $page);
|
||||
$this->assertStringContainsString('<dd class="author">Ann & "Bo"</dd>', $page);
|
||||
$this->assertStringNotContainsString('<em>title</em>', $page);
|
||||
}
|
||||
|
||||
public function testStoryHtmlIsPurified(): void {
|
||||
$page = display_stories();
|
||||
$this->assertStringContainsString('<p>One hundred</p>', $page);
|
||||
$this->assertStringNotContainsString('onclick', $page);
|
||||
$this->assertStringNotContainsString('alert', $page);
|
||||
}
|
||||
|
||||
public function testDatesAreShownWithoutSecondsAndMarkedUp(): void {
|
||||
$page = display_stories();
|
||||
$datetime = date('Y-m-d\TH:i:sP', strtotime('2020-01-02 03:04:05'));
|
||||
$this->assertStringContainsString('<time datetime="' . $datetime . '">2020-01-02 03:04</time>', $page);
|
||||
}
|
||||
|
||||
public function testHiddenStoriesAreLeftOutForVisitors(): void {
|
||||
$this->assertStringNotContainsString('Picture', display_stories());
|
||||
}
|
||||
|
||||
public function testEditorsSeeHiddenStoriesMarkedAndEditLinks(): void {
|
||||
$this->asEditor();
|
||||
$page = display_stories();
|
||||
$this->assertStringContainsString('<span class="right red">[hidden]</span>', $page);
|
||||
$this->assertStringContainsString('[<a href="/publish/edit?id=3&queue=0">edit</a>]', $page);
|
||||
}
|
||||
|
||||
public function testImagesAreServedByDisplay(): void {
|
||||
$this->asEditor();
|
||||
$this->assertStringContainsString('<img src="/display?id=3" alt="Picture" />', display_stories());
|
||||
}
|
||||
|
||||
public function testEditableListLinksTitlesToTheEditor(): void {
|
||||
$this->asEditor();
|
||||
$GLOBALS['editable'] = TRUE;
|
||||
$this->request(array('queue' => '1'));
|
||||
$page = display_stories();
|
||||
$this->assertStringContainsString('<a href="/publish/edit?id=20&queue=1">Waiting</a>', $page);
|
||||
$this->assertStringNotContainsString('[<a href', $page);
|
||||
}
|
||||
|
||||
public function testEditableImagesKeepTheQueue(): void {
|
||||
$this->asEditor();
|
||||
$GLOBALS['editable'] = TRUE;
|
||||
$page = display_stories('3');
|
||||
$this->assertStringContainsString('<img src="/display?id=3&queue=0" alt="Picture" />', $page);
|
||||
}
|
||||
|
||||
public function testOneStoryHasNoPager(): void {
|
||||
$page = display_stories('2');
|
||||
$this->assertSame(1, substr_count($page, '<li class="box">'));
|
||||
$this->assertStringNotContainsString('class="pager"', $page);
|
||||
}
|
||||
|
||||
public function testSeveralStoriesHaveAPager(): void {
|
||||
$this->assertStringContainsString('<div class="pager">', display_stories());
|
||||
}
|
||||
|
||||
public function testNoStories(): void {
|
||||
$page = display_stories('99');
|
||||
$this->assertStringContainsString('<p>No articles found.</p>', $page);
|
||||
$this->assertStringNotContainsString('Try searching again', $page);
|
||||
}
|
||||
|
||||
public function testNoSearchResults(): void {
|
||||
$this->request(array('search' => 'nothing like this'));
|
||||
$page = display_stories();
|
||||
$this->assertStringContainsString('<p>No articles found.</p>', $page);
|
||||
$this->assertStringContainsString('Try searching again', $page);
|
||||
}
|
||||
|
||||
public function testPreviewShowsThePostedStoryWithoutLinks(): void {
|
||||
$GLOBALS['action'] = 'preview';
|
||||
$this->request(array(), array('title' => '<b>Mine</b>', 'author' => 'Me', 'story' => '<p>My <i>story</i></p><script>x()</script>'));
|
||||
$page = display_stories();
|
||||
$this->assertStringContainsString('<h3 class="articletitle"><b>Mine</b></h3>', $page);
|
||||
$this->assertStringContainsString('<dd class="date">Awaiting posting</dd>', $page);
|
||||
$this->assertStringContainsString('<p>My <i>story</i></p>', $page);
|
||||
$this->assertStringNotContainsString('x()', $page);
|
||||
}
|
||||
|
||||
public function testPreviewShowsAPendingImage(): void {
|
||||
$GLOBALS['action'] = 'preview';
|
||||
$GLOBALS['file_src'] = '/display?pending="><script>';
|
||||
$this->request(array(), array('title' => 'Pic', 'author' => 'Me'));
|
||||
$this->assertStringContainsString('<img src="/display?pending="><script>" alt="Pic" />', display_stories());
|
||||
}
|
||||
|
||||
public function testVisitorSubmitShowsTheirStory(): void {
|
||||
$GLOBALS['action'] = 'submit';
|
||||
$this->request(array(), array('title' => 'Sent', 'author' => 'Me', 'story' => '<p>Done</p>'));
|
||||
$page = display_stories();
|
||||
$this->assertMatchesRegularExpression('/<dd class="date">Posted \d{4}-\d\d-\d\d \d\d:\d\d<\/dd>/', $page);
|
||||
$this->assertStringContainsString('<h3 class="articletitle">Sent</h3>', $page);
|
||||
}
|
||||
|
||||
public function testVisitorSeesTheImageTheySubmittedFromTheQueue(): void {
|
||||
$GLOBALS['action'] = 'submit';
|
||||
$_SESSION['allow_queue_image'] = '20';
|
||||
$this->request(array(), array('title' => 'Sent', 'author' => 'Me', 'uploaded' => 'yes'));
|
||||
$this->assertStringContainsString('<img src="/display?id=20" alt="Sent" />', display_stories());
|
||||
}
|
||||
|
||||
// An editor's submit saves to the queue, and the page shows the saved row
|
||||
public function testEditorSubmitShowsTheSavedStoryFromTheQueue(): void {
|
||||
$this->asEditor();
|
||||
$GLOBALS['action'] = 'submit';
|
||||
$page = display_stories('20');
|
||||
$this->assertStringContainsString('Waiting', $page);
|
||||
$this->assertStringContainsString('<p>No articles found.</p>', display_stories('2'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user