Merge pull request #154 from gordonbanderson/improvecoverage

ENHANCEMENT: Increase test coverage from 54% to 92%
This commit is contained in:
Damian Mooyman 2016-01-18 17:12:47 +13:00
commit 0e64cc4fe0
15 changed files with 1955 additions and 90 deletions

View File

@ -1,9 +1,12 @@
# See https://github.com/silverstripe-labs/silverstripe-travis-support for setup details
sudo: false
language: php
sudo: true
addons:
apt:
packages:
- tidy
php:
- 5.3
- 5.4
@ -11,11 +14,22 @@ php:
- 5.6
- 7.0
before_install:
- pip install --user codecov
env:
- DB=MYSQL CORE_RELEASE=3.2
global:
- DB=MYSQL CORE_RELEASE=3.1
- MODULE_PATH=comments
# Set to 1 in the matrix to enable code coverage
- COVERAGE=0
matrix:
include:
- php: 5.6
#CommentsListTest breaks with this env: DB=MYSQL CORE_RELEASE=3.2 COVERAGE=1
env: DB=SQLITE CORE_RELEASE=3.2 COVERAGE=1
- php: 5.6
env: DB=MYSQL CORE_RELEASE=3
- php: 5.6
@ -26,11 +40,23 @@ matrix:
- php: 7.0
before_script:
- phpenv rehash
- composer self-update || true
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss
- git clone https://github.com/gordonbanderson/silverstripe-travis-support.git --branch pull-24 ~/travis-support
# - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
# Install suggested modules in order to maximize test coverage
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require "ezyang/htmlpurifier:4.*,silverstripe/cms:~3.1"
- cd ~/builds/ss
- composer install
script:
- vendor/bin/phpunit comments/tests
# Execute tests with no coverage. This is the fastest option
- "if [ \"$COVERAGE\" = \"0\" ]; then vendor/bin/phpunit $MODULE_PATH/tests/; fi"
# Execute tests with coverage. Do this for a small
- "if [ \"$COVERAGE\" = \"1\" ]; then vendor/bin/phpunit --coverage-clover=coverage.clover $MODULE_PATH/tests/; fi"
after_script:
- "if [ \"$COVERAGE\" = \"1\" ]; then mv coverage.clover ~/build/$TRAVIS_REPO_SLUG/; fi"
- cd ~/build/$TRAVIS_REPO_SLUG
- wget https://scrutinizer-ci.com/ocular.phar
- "if [ \"$COVERAGE\" = \"1\" ]; then travis_retry codecov && travis_retry php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi"

View File

@ -1,6 +1,21 @@
# Comments
[![Build Status](https://travis-ci.org/gordonbanderson/silverstripe-comments.svg?branch=testing)](https://travis-ci.org/gordonbanderson/silverstripe-comments)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/gordonbanderson/silverstripe-comments/badges/quality-score.png?b=testing)](https://scrutinizer-ci.com/g/gordonbanderson/silverstripe-comments/?branch=testing)
[![Code Coverage](https://scrutinizer-ci.com/g/gordonbanderson/silverstripe-comments/badges/coverage.png?b=testing)](https://scrutinizer-ci.com/g/gordonbanderson/silverstripe-comments/?branch=testing)
[![Build Status](https://scrutinizer-ci.com/g/gordonbanderson/silverstripe-comments/badges/build.png?b=testing)](https://scrutinizer-ci.com/g/gordonbanderson/silverstripe-comments/build-status/testing)
[![codecov.io](https://codecov.io/github/gordonbanderson/silverstripe-comments/coverage.svg?branch=testing)](https://codecov.io/github/gordonbanderson/silverstripe-comments?branch=testing)
[![Build Status](https://secure.travis-ci.org/silverstripe/silverstripe-comments.png?branch=master)](http://travis-ci.org/silverstripe/silverstripe-comments)
[![Latest Stable Version](https://poser.pugx.org/silverstripe/comments/version)](https://packagist.org/packages/silverstripe/comments)
[![Latest Unstable Version](https://poser.pugx.org/silverstripe/comments/v/unstable)](//packagist.org/packages/silverstripe/comments)
[![Total Downloads](https://poser.pugx.org/silverstripe/comments/downloads)](https://packagist.org/packages/silverstripe/comments)
[![License](https://poser.pugx.org/silverstripe/comments/license)](https://packagist.org/packages/silverstripe/comments)
[![Monthly Downloads](https://poser.pugx.org/silverstripe/comments/d/monthly)](https://packagist.org/packages/silverstripe/comments)
[![Daily Downloads](https://poser.pugx.org/silverstripe/comments/d/daily)](https://packagist.org/packages/silverstripe/comments)
[![Dependency Status](https://www.versioneye.com/php/silverstripe:comments/badge.svg)](https://www.versioneye.com/php/silverstripe:comments)
[![Reference Status](https://www.versioneye.com/php/silverstripe:comments/reference_badge.svg?style=flat)](https://www.versioneye.com/php/silverstripe:comments/references)
![codecov.io](https://codecov.io/github/gordonbanderson/silverstripe-comments/branch.svg?branch=testing)
[Changelog](CHANGELOG.md)
@ -12,7 +27,7 @@
## Introduction
This module provides commenting functionality for Pages and other DataObjects
on your SilverStripe site.
on your SilverStripe site.
For more documentation about the module see the provided documentation located
inside the docs folder.
@ -41,4 +56,4 @@ and any new translations will be merged back to the project source code.
Please use https://www.transifex.com/projects/p/silverstripe-comments/ to contribute translations,
rather than sending pull requests with YAML files.
See the ["i18n" topic](http://doc.silverstripe.org/framework/en/trunk/topics/i18n) on doc.silverstripe.org for more details.
See the ["i18n" topic](http://doc.silverstripe.org/framework/en/trunk/topics/i18n) on doc.silverstripe.org for more details.

View File

@ -202,11 +202,11 @@ class Comment extends DataObject {
public function getOption($key) {
// If possible use the current record
$record = $this->getParent();
if(!$record && $this->BaseClass) {
// Otherwise a singleton of that record
$record = singleton($this->BaseClass);
}
}
else if(!$record) {
// Otherwise just use the default options
$record = singleton('CommentsExtension');
@ -500,7 +500,7 @@ class Comment extends DataObject {
$this->write();
$this->extend('afterMarkUnapproved');
}
/**
* @return string
*/
@ -570,14 +570,15 @@ class Comment extends DataObject {
_t('Comment.ParentComment_Title', 'This comment is a reply to the below')
));
// Created date
$fields->push(
$parent
->obj('Created')
->scaffoldFormField($parent->fieldLabel('Created'))
->setName('ParentComment_Created')
->setValue($parent->Created)
->performReadonlyTransformation()
);
// FIXME - the method setName in DatetimeField is not chainable, hence
// the lack of chaining here
$createdField = $parent
->obj('Created')
->scaffoldFormField($parent->fieldLabel('Created'));
$createdField->setName('ParentComment_Created');
$createdField->setValue($parent->Created);
$createdField->performReadonlyTransformation();
$fields->push($createdField);
// Name (could be member or string value)
$fields->push(
@ -619,8 +620,14 @@ class Comment extends DataObject {
*/
public function getHtmlPurifierService() {
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.AllowedElements', $this->getOption('html_allowed_elements'));
$config->set('AutoFormat.AutoParagraph', true);
$allowedElements = $this->getOption('html_allowed_elements');
$config->set('HTML.AllowedElements', $allowedElements);
// This injector cannot be set unless the 'p' element is allowed
if (in_array('p', $allowedElements)) {
$config->set('AutoFormat.AutoParagraph', true);
}
$config->set('AutoFormat.Linkify', true);
$config->set('URI.DisableExternalResources', true);
$config->set('Cache.SerializerPath', getTempFolder());
@ -672,7 +679,7 @@ class Comment extends DataObject {
if(!$this->getRepliesEnabled()) {
return new ArrayList();
}
// Get all non-spam comments
$order = $this->getOption('order_replies_by')
?: $this->getOption('order_comments_by');
@ -695,7 +702,7 @@ class Comment extends DataObject {
return new ArrayList();
}
$list = $this->AllReplies();
// Filter spam comments for non-administrators if configured
$parent = $this->getParent();
$showSpam = $this->getOption('frontend_spam') && $parent && $parent->canModerateComments();

View File

@ -0,0 +1,57 @@
<?php
class CommentAdminTest extends SapphireTest {
public function testProvidePermissions() {
$commentAdmin = new CommentAdmin();
$locale = i18n::get_locale();
i18n::set_locale('fr');
$expected = array(
'CMS_ACCESS_CommentAdmin' => array(
# FIXME - this is a bug, missing from lang.yml files
'name' => 'Access to \'Comments\' section',
'category' => 'Accès au CMS'
)
);
$this->assertEquals($expected, $commentAdmin->providePermissions());
i18n::set_locale($locale);
$expected = array(
'CMS_ACCESS_CommentAdmin' => array(
# FIXME - this is a bug, missing from lang.yml files
'name' => 'Access to \'Comments\' section',
'category' => 'CMS Access'
)
);
$this->assertEquals($expected, $commentAdmin->providePermissions());
}
public function testGetEditForm() {
$commentAdmin = new CommentAdmin();
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$form = $commentAdmin->getEditForm();
$names = $this->getFormFieldNames($form);
$expected = array(
'NewComments',
'ApprovedComments',
'SpamComments'
);
$this->assertEquals($expected, $names);
if($member = Member::currentUser()) $member->logOut();
$form = $commentAdmin->getEditForm();
}
private function getFormFieldNames($form) {
$result = array();
$fields = $form->Fields();
$tab = $fields->findOrMakeTab('Root');
$fields = $tab->FieldList();
foreach ($fields as $field) {
array_push($result, $field->getName());
}
return $result;
}
}

138
tests/CommentListTest.php Normal file
View File

@ -0,0 +1,138 @@
<?php
class CommentListTest extends FunctionalTest {
public static $fixture_file = 'comments/tests/CommentsTest.yml';
protected $extraDataObjects = array(
'CommentableItem',
'CommentableItemEnabled',
'CommentableItemDisabled'
);
public function setUp() {
parent::setUp();
Config::nest();
// Set good default values
Config::inst()->update('CommentsExtension', 'comments', array(
'enabled' => true,
'enabled_cms' => false,
'require_login' => false,
'require_login_cms' => false,
'required_permission' => false,
'require_moderation_nonmembers' => false,
'require_moderation' => false,
'require_moderation_cms' => false,
'frontend_moderation' => false,
'frontend_spam' => false,
));
// Configure this dataobject
Config::inst()->update('CommentableItem', 'comments', array(
'enabled_cms' => true
));
}
public function tearDown() {
Config::unnest();
parent::tearDown();
}
public function testGetForeignClass() {
$item = $this->objFromFixture('CommentableItem', 'first');
// This is the class the Comments are related to
$this->assertEquals('CommentableItem',
$item->Comments()->getForeignClass());
}
public function testAddNonComment() {
$item = $this->objFromFixture('CommentableItem', 'first');
$comments = $item->Comments();
$this->assertEquals(4, $comments->count());
$member = Member::get()->first();
try {
$comments->add($member);
$this->fail('Should not have been able to add member to comments');
} catch (InvalidArgumentException $e) {
$this->assertEquals(
'CommentList::add() expecting a Comment object, or ID value',
$e->getMessage()
);
}
}
public function testAddComment() {
$item = $this->objFromFixture('CommentableItem', 'first');
$firstComment = $this->objFromFixture('Comment', 'firstComA');
$comments = $item->Comments();//->sort('Created');
foreach ($comments as $comment) {
error_log($comment->ID . ' ' . $comment->Created .' ' . $comment->Comment);
}
$this->assertEquals(4, $comments->count());
$newComment = new Comment();
$newComment->Name = 'Fred Bloggs';
$newComment->Comment = 'This is a test comment';
$newComment->write();
$comments->add($newComment);
// As a comment has been added, there should be 5 comments now
$this->assertEquals(5, $item->Comments()->count());
$newComment2 = new Comment();
$newComment2->Name = 'John Smith';
$newComment2->Comment = 'This is another test comment';
$newComment2->write();
// test adding the same comment by ID
$comments->add($newComment2->ID);
$this->assertEquals(6, $item->Comments()->count());
$this->setExpectedException(
'InvalidArgumentException',
"CommentList::add() can't be called until a single foreign ID is set"
);
$list = new CommentList('CommentableItem');
$list->add($newComment);
}
public function testRemoveComment() {
// remove by comment
$item = $this->objFromFixture('CommentableItem', 'first');
$this->assertEquals(4, $item->Comments()->count());
$comments = $item->Comments();
$comment = $comments->first();
$comments->remove($comment);
// now remove by ID
$comments = $item->Comments();
$comment = $comments->first();
$comments->remove($comment->ID);
$this->assertEquals(2, $item->Comments()->count());
}
public function testRemoveNonComment() {
$item = $this->objFromFixture('CommentableItem', 'first');
$this->assertEquals(4, $item->Comments()->count());
$comments = $item->Comments();
// try and remove a non comment
$member = Member::get()->first();
try {
$comments->remove($member);
$this->fail('Should not have been able to remove member from comments');
} catch (InvalidArgumentException $e) {
$this->assertEquals(
'CommentList::remove() expecting a Comment object, or ID',
$e->getMessage()
);
}
}
}

View File

@ -0,0 +1,25 @@
<?php
class CommentTestHelper {
/*
This only works if the last section is not a field group, e.g. a Comments
field group inside of a Root.Settings tab will not work
*/
public static function assertFieldsForTab($context, $tabName, $expected, $fields) {
$tab = $fields->findOrMakeTab($tabName);
$fields = $tab->FieldList();
CommentTestHelper::assertFieldNames($context, $expected, $fields);
}
public static function assertFieldNames($context, $expected, $fields) {
$actual = array();
foreach ($fields as $field) {
if (get_class($field) == 'FieldGroup') {
array_push($actual, $field->Name());
} else {
array_push($actual, $field->getName());
}
}
$context->assertEquals($expected, $actual);
}
}

View File

@ -5,13 +5,13 @@
* @subpackage tests
*/
class CommentingControllerTest extends FunctionalTest {
public static $fixture_file = 'CommentsTest.yml';
protected $extraDataObjects = array(
'CommentableItem'
);
protected $securityEnabled;
public function tearDown() {
@ -28,8 +28,92 @@ class CommentingControllerTest extends FunctionalTest {
$this->securityEnabled = SecurityToken::is_enabled();
}
public function testApprove() {
SecurityToken::disable();
// mark a comment as spam then approve it
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->markSpam();
$st = new Comment_SecurityToken($comment);
$url = 'CommentingController/approve/' . $comment->ID;
$url = $st->addToUrl($url, Member::currentUser());
$response = $this->get($url);
$this->assertEquals(200, $response->getStatusCode());
$comment = DataObject::get_by_id('Comment', $comment->ID);
// Need to use 0,1 here instead of false, true for SQLite
$this->assertEquals(0, $comment->IsSpam);
$this->assertEquals(1, $comment->Moderated);
// try and approve a non existent comment
$response = $this->get('CommentingController/approve/100000');
$this->assertEquals(404, $response->getStatusCode());
}
public function testSetGetOwnerController() {
$commController = new CommentingController();
$commController->setOwnerController(Controller::curr());
$this->assertEquals(Controller::curr(), $commController->getOwnerController());
$commController->setOwnerController(null);
$this->assertNull($commController->getOwnerController());
}
public function testHam() {
SecurityToken::disable();
// mark a comment as spam then ham it
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->markSpam();
$st = new Comment_SecurityToken($comment);
$url = 'CommentingController/ham/' . $comment->ID;
$url = $st->addToUrl($url, Member::currentUser());
$response = $this->get($url);
$this->assertEquals(200, $response->getStatusCode());
$comment = DataObject::get_by_id('Comment', $comment->ID);
// Need to use 0,1 here instead of false, true for SQLite
$this->assertEquals(0, $comment->IsSpam);
$this->assertEquals(1, $comment->Moderated);
// try and ham a non existent comment
$response = $this->get('CommentingController/ham/100000');
$this->assertEquals(404, $response->getStatusCode());
}
public function testSpam() {
// mark a comment as approved then spam it
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->markApproved();
$st = new Comment_SecurityToken($comment);
$url = 'CommentingController/spam/' . $comment->ID;
$url = $st->addToUrl($url, Member::currentUser());
$response = $this->get($url);
$this->assertEquals(200, $response->getStatusCode());
$comment = DataObject::get_by_id('Comment', $comment->ID);
// Need to use 0,1 here instead of false, true for SQLite
$this->assertEquals(1, $comment->IsSpam);
$this->assertEquals(1, $comment->Moderated);
// try and spam a non existent comment
$response = $this->get('CommentingController/spam/100000');
$this->assertEquals(404, $response->getStatusCode());
}
public function testRSS() {
$item = $this->objFromFixture('CommentableItem', 'first');
// Delete the newly added children of firstComA so as not to have to recalculate values below
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
$item = $this->objFromFixture('CommentableItem', 'first');
// comments sitewide
$response = $this->get('CommentingController/rss');
@ -55,7 +139,81 @@ class CommentingControllerTest extends FunctionalTest {
$this->assertEquals(404, $response->getStatusCode());
}
// This is returning a 404 which looks logical code wise but also a bit weird.
// Test module on a clean install and check what the actual URL is first
/* public function testReply() {
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$item = $this->objFromFixture('CommentableItem', 'first');
$st = new Comment_SecurityToken($comment);
$url = 'CommentingController/reply/' . $item->ID.'?ParentCommentID=' . $comment->ID;
error_log($url);
$response = $this->get($url);
error_log(print_r($response,1));
$this->assertEquals(200, $response->getStatusCode());
}
*/
/*
public function testCommentsFormLoadMemberData() {
Config::inst()->update('CommentableItem', 'comments', array(
'use_preview' => false
));
$this->logInAs('visitor');
SecurityToken::disable();
$parent = $this->objFromFixture('CommentableItem', 'first');
$parent->CommentsRequireLogin = true;
$parent->PostingRequiredPermission = true;
//$parent->write();
$commController = new CommentingController();
$commController->setOwnerRecord($parent);
$form = $commController->CommentsForm();
$commentsFields = $form->Fields()->first()->FieldList();
$expected = array('Name', 'Email', 'URL', 'Comment', 'PreviewComment');
CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
}
*/
public function testCommentsFormUsePreview() {
// test with preview on
Config::inst()->update('CommentableItem', 'comments', array(
'use_preview' => true
));
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
SecurityToken::disable();
$this->autoFollowRedirection = false;
$parent = $this->objFromFixture('CommentableItem', 'first');
$commController = new CommentingController();
$commController->setOwnerRecord($parent);
$form = $commController->CommentsForm();
$commentsFields = $form->Fields()->first()->FieldList();
$expected = array('Name', 'Email', 'URL', 'Comment', 'PreviewComment');
CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
// Turn off preview. Assert lack of preview field
Config::inst()->update('CommentableItem', 'comments', array(
'use_preview' => false
));
$form = $commController->CommentsForm();
$commentsFields = $form->Fields()->first()->FieldList();
$expected = array('Name', 'Email', 'URL', 'Comment');
CommentTestHelper::assertFieldNames($this, $expected, $commentsFields);
}
public function testCommentsForm() {
// Delete the newly added children of firstComA so as not to change this test
$this->objFromFixture('Comment', 'firstComAChild1')->delete();
$this->objFromFixture('Comment', 'firstComAChild2')->delete();
$this->objFromFixture('Comment', 'firstComAChild3')->delete();
SecurityToken::disable();
$this->autoFollowRedirection = false;
$parent = $this->objFromFixture('CommentableItem', 'first');
@ -83,7 +241,7 @@ class CommentingControllerTest extends FunctionalTest {
)),
Comment::get()->filter('Email', 'guy@test.com')
);
// Test posting to parent comment
$parentComment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(0, $parentComment->ChildComments()->count());
@ -110,5 +268,7 @@ class CommentingControllerTest extends FunctionalTest {
'BaseClass' => 'CommentableItem',
'ParentCommentID' => $parentComment->ID
)), $parentComment->ChildComments());
}
}

173
tests/CommentingTest.php Normal file
View File

@ -0,0 +1,173 @@
<?php
class CommentingTest extends SapphireTest {
public function setUpOnce() {
parent::setUpOnce();
}
public function testDeprecatedMethods() {
$methods = array('add', 'remove', 'has_commenting');
foreach ($methods as $methodName) {
try {
Commenting::$methodName('Member');
} catch (PHPUnit_Framework_Error_Deprecated $e) {
$expected = 'Using Commenting:' . $methodName .' is deprecated.'
. ' Please use the config API instead';
$this->assertEquals($expected, $e->getMessage());
}
}
}
public function test_set_config_value() {
// public static function set_config_value($class, $key, $value = false) {
Commenting::set_config_value(
'CommentableItem',
'comments_holder_id',
'commentable_item'
);
$config = Config::inst()->get(
'CommentableItem',
'comments'
);
$actual = $config['comments_holder_id'];
$this->assertEquals(
'commentable_item',
$actual
);
Commenting::set_config_value(
'all',
'comments_holder_id',
'all_items_actually_commentsextension'
);
$config = Config::inst()->get(
'CommentsExtension',
'comments'
);
$actual = $config['comments_holder_id'];
$this->assertEquals(
'all_items_actually_commentsextension',
$actual
);
}
public function test_get_config_value() {
Config::inst()->update('CommentableItem', 'comments',
array(
'comments_holder_id' => 'commentable_item'
)
);
$this->assertEquals(
'commentable_item',
Commenting::get_config_value('CommentableItem', 'comments_holder_id')
);
Config::inst()->update('CommentsExtension', 'comments',
array(
'comments_holder_id' => 'comments_extension'
)
);
// if class is null, method uses the CommentsExtension property
$this->assertEquals(
'comments_extension',
Commenting::get_config_value(null, 'comments_holder_id')
);
$this->setExpectedException(
'InvalidArgumentException',
'Member does not have commenting enabled'
);
Commenting::get_config_value('Member', 'comments_holder_id');
}
public function test_config_value_equals() {
Config::inst()->update('CommentableItem', 'comments',
array(
'comments_holder_id' => 'some_value'
)
);
$this->assertTrue(
Commenting::config_value_equals(
'CommentableItem',
'comments_holder_id',
'some_value'
)
);
$this->assertNull(
Commenting::config_value_equals(
'CommentableItem',
'comments_holder_id',
'not_some_value'
)
);
}
public function test_add() {
Commenting::add('Member', array('comments_holder_id' => 'test_add_value'));
$config = Config::inst()->get(
'Member',
'comments'
);
$actual = $config['comments_holder_id'];
$this->assertEquals(
'test_add_value',
$actual
);
Commenting::add('Member');
$config = Config::inst()->get(
'Member',
'comments'
);
$actual = $config['comments_holder_id'];
// no settings updated
$this->assertEquals(
'test_add_value',
$actual
);
$this->setExpectedException('InvalidArgumentException', "\$settings needs to be an array or null");
Commenting::add('Member', 'illegal format, not an array');
}
public function test_can_member_post() {
// logout
if($member = Member::currentUser()) $member->logOut();
Config::inst()->update('CommentableItem', 'comments',
array(
'require_login' => false
)
);
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
Config::inst()->update('CommentableItem', 'comments',
array(
'require_login' => true
)
);
$this->assertFalse(Commenting::can_member_post('CommentableItem'));
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
Config::inst()->update('CommentableItem', 'comments',
array(
'require_login' => false
)
);
$this->assertTrue(Commenting::can_member_post('CommentableItem'));
}
}

View File

@ -0,0 +1,407 @@
<?php
class CommentsExtensionTest extends SapphireTest {
public static $fixture_file = 'comments/tests/CommentsTest.yml';
protected $extraDataObjects = array(
'CommentableItem',
'CommentableItemEnabled',
'CommentableItemDisabled'
);
public function setUp() {
parent::setUp();
Config::nest();
// Set good default values
Config::inst()->update('CommentsExtension', 'comments', array(
'enabled' => true,
'enabled_cms' => false,
'require_login' => false,
'require_login_cms' => false,
'required_permission' => false,
'require_moderation_nonmembers' => false,
'require_moderation' => false,
'require_moderation_cms' => false,
'frontend_moderation' => false,
'Member' => false,
));
$this->requiredExtensions = array(
'CommentableItem' => 'CommentsExtension'
);
// Configure this dataobject
Config::inst()->update('CommentableItem', 'comments', array(
'enabled_cms' => true
));
}
public function tearDown() {
Config::unnest();
parent::tearDown();
}
public function testPopulateDefaults() {
$this->markTestSkipped('TODO');
}
public function testUpdateSettingsFields() {
$this->markTestSkipped('This needs SiteTree installed');
}
public function testGetModerationRequired() {
// the 3 options take precedence in this order, executed if true
Config::inst()->update('CommentableItem', 'comments', array(
'require_moderation_cms' => true,
'require_moderation' => true,
'require_moderation_nonmembers' => true
));
// With require moderation CMS set to true, the value of the field
// 'ModerationRequired' is returned
$item = $this->objFromFixture('CommentableItem', 'first');
$item->ModerationRequired = 'None';
$this->assertEquals('None', $item->getModerationRequired());
$item->ModerationRequired = 'Required';
$this->assertEquals('Required', $item->getModerationRequired());
$item->ModerationRequired = 'NonMembersOnly';
$this->assertEquals('NonMembersOnly', $item->getModerationRequired());
Config::inst()->update('CommentableItem', 'comments', array(
'require_moderation_cms' => false,
'require_moderation' => true,
'require_moderation_nonmembers' => true
));
$this->assertEquals('Required', $item->getModerationRequired());
Config::inst()->update('CommentableItem', 'comments', array(
'require_moderation_cms' => false,
'require_moderation' => false,
'require_moderation_nonmembers' => true
));
$this->assertEquals('NonMembersOnly', $item->getModerationRequired());
Config::inst()->update('CommentableItem', 'comments', array(
'require_moderation_cms' => false,
'require_moderation' => false,
'require_moderation_nonmembers' => false
));
$this->assertEquals('None', $item->getModerationRequired());
}
public function testGetCommentsRequireLogin() {
Config::inst()->update('CommentableItem', 'comments', array(
'require_login_cms' => true
));
// With require moderation CMS set to true, the value of the field
// 'ModerationRequired' is returned
$item = $this->objFromFixture('CommentableItem', 'first');
$item->CommentsRequireLogin = true;
$this->assertTrue($item->getCommentsRequireLogin());
$item->CommentsRequireLogin = false;
$this->assertFalse($item->getCommentsRequireLogin());
Config::inst()->update('CommentableItem', 'comments', array(
'require_login_cms' => false,
'require_login' => false
));
$this->assertFalse($item->getCommentsRequireLogin());
Config::inst()->update('CommentableItem', 'comments', array(
'require_login_cms' => false,
'require_login' => true
));
$this->assertTrue($item->getCommentsRequireLogin());
}
public function testAllComments() {
$this->markTestSkipped('TODO');
}
public function testAllVisibleComments() {
$this->markTestSkipped('TODO');
}
public function testComments() {
$this->markTestSkipped('TODO');
}
public function testGetCommentsEnabled() {
$this->markTestSkipped('TODO');
}
public function testGetCommentHolderID() {
$item = $this->objFromFixture('CommentableItem', 'first');
Config::inst()->update('CommentableItem', 'comments', array(
'comments_holder_id' => 'commentid_test1',
));
$this->assertEquals('commentid_test1', $item->getCommentHolderID());
Config::inst()->update('CommentableItem', 'comments', array(
'comments_holder_id' => 'commtentid_test_another',
));
$this->assertEquals('commtentid_test_another', $item->getCommentHolderID());
}
public function testGetPostingRequiredPermission() {
$this->markTestSkipped('TODO');
}
public function testCanModerateComments() {
// ensure nobody logged in
if(Member::currentUser()) { Member::currentUser()->logOut(); }
$item = $this->objFromFixture('CommentableItem', 'first');
$this->assertFalse($item->canModerateComments());
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$this->assertTrue($item->canModerateComments());
}
public function testGetCommentRSSLink() {
$item = $this->objFromFixture('CommentableItem', 'first');
$link = $item->getCommentRSSLink();
$this->assertEquals('/CommentingController/rss', $link);
}
public function testGetCommentRSSLinkPage() {
$item = $this->objFromFixture('CommentableItem', 'first');
$page = $item->getCommentRSSLinkPage();
$this->assertEquals(
'/CommentingController/rss/CommentableItem/' . $item->ID,
$page
);
}
public function testCommentsForm() {
Config::inst()->update('CommentableItem', 'comments', array(
'include_js' => false
)
);
$item = $this->objFromFixture('CommentableItem', 'first');
// The comments form is HTML to do assertions by contains
$cf = $item->CommentsForm();
$expected = '<form id="Form_CommentsForm" action="/CommentingController'
. '/CommentsForm" method="post" enctype="application/x-www-form-urlenco'
. 'ded">';
$this->assertContains($expected, $cf);
$this->assertContains('<h4>Post your comment</h4>', $cf);
// check the comments form exists
$expected = '<input type="text" name="Name" value="ADMIN User" class="text" id="Form_CommentsForm_Name" required="required"';
$this->assertContains($expected, $cf);
$expected = '<input type="email" name="Email" value="ADMIN@example.org" class="email text" id="Form_CommentsForm_Email"';
$this->assertContains($expected, $cf);
$expected = '<input type="text" name="URL" class="text" id="Form_CommentsForm_URL" data-msg-url="Please enter a valid URL"';
$this->assertContains($expected, $cf);
$expected = '<input type="hidden" name="ParentID" value="' . $item->ID . '" class="hidden" id="Form_CommentsForm_ParentID" />';
$this->assertContains($expected, $cf);
$expected = '<textarea name="Comment" class="textarea" id="Form_CommentsForm_Comment" required="required"';
$this->assertContains($expected, $cf);
$expected = '<input type="submit" name="action_doPostComment" value="Post" class="action" id="Form_CommentsForm_action_doPostComment"';
$this->assertContains($expected, $cf);
$expected = '<a href="/CommentingController/spam/';
$this->assertContains($expected, $cf);
$expected = '<p>Reply to firstComA 1</p>';
$this->assertContains($expected, $cf);
$expected = '<a href="/CommentingController/delete';
$this->assertContains($expected, $cf);
$expected = '<p>Reply to firstComA 2</p>';
$this->assertContains($expected, $cf);
$expected = '<p>Reply to firstComA 3</p>';
$this->assertContains($expected, $cf);
// Check for JS inclusion
$backend = Requirements::backend();
$this->assertEquals(
array(),
$backend->get_javascript()
);
Config::inst()->update('CommentableItem', 'comments', array(
'include_js' => true
)
);
$cf = $item->CommentsForm();
$backend = Requirements::backend();
$this->assertEquals(
array(
'framework/thirdparty/jquery/jquery.js',
'framework/thirdparty/jquery-entwine/dist/jquery.entwine-dist.js',
'framework/thirdparty/jquery-validate/lib/jquery.form.js',
'comments/thirdparty/jquery-validate/jquery.validate.min.js',
'comments/javascript/CommentsInterface.js'
),
$backend->get_javascript()
);
}
public function testAttachedToSiteTree() {
$this->markTestSkipped('TODO');
}
public function testPagedComments() {
$item = $this->objFromFixture('CommentableItem', 'first');
// Ensure Created times are set, as order not guaranteed if all set to 0
$comments = $item->PagedComments()->sort('ID');
$ctr = 0;
$timeBase = time()-10000;
foreach ($comments as $comment) {
$comment->Created = $timeBase + $ctr * 1000;
$comment->write();
$ctr++;
}
$results = $item->PagedComments()->toArray();
foreach ($results as $result) {
$result->sourceQueryParams = null;
}
$this->assertEquals(
$this->objFromFixture('Comment', 'firstComA')->Comment,
$results[3]->Comment
);
$this->assertEquals(
$this->objFromFixture('Comment', 'firstComAChild1')->Comment,
$results[2]->Comment
);
$this->assertEquals(
$this->objFromFixture('Comment', 'firstComAChild2')->Comment,
$results[1]->Comment
);
$this->assertEquals(
$this->objFromFixture('Comment', 'firstComAChild3')->Comment,
$results[0]->Comment
);
$this->assertEquals(4, sizeof($results));
}
public function testGetCommentsOption() {
$this->markTestSkipped('TODO');
}
public function testUpdateModerationFields() {
$this->markTestSkipped('TODO');
}
public function testUpdateCMSFields() {
Config::inst()->update('CommentableItem', 'comments', array(
'require_login_cms' => false
)
);
$this->logInWithPermission('ADMIN');
$item = $this->objFromFixture('CommentableItem', 'first');
$item->ProvideComments = true;
$item->write();
$fields = $item->getCMSFields();
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments',
array('CommentsNewCommentsTab', 'CommentsCommentsTab', 'CommentsSpamCommentsTab'),
$fields
);
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments.CommentsNewCommentsTab',
array('NewComments'),
$fields
);
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments.CommentsCommentsTab',
array('ApprovedComments'),
$fields
);
CommentTestHelper::assertFieldsForTab($this, 'Root.Comments.CommentsSpamCommentsTab',
array('SpamComments'),
$fields
);
Config::inst()->update('CommentableItem', 'comments', array(
'require_login_cms' => true
)
);
$fields = $item->getCMSFields();
CommentTestHelper::assertFieldsForTab($this, 'Root.Settings', array('Comments'), $fields);
$settingsTab = $fields->findOrMakeTab('Root.Settings');
$settingsChildren = $settingsTab->getChildren();
$this->assertEquals(1, $settingsChildren->count());
$fieldGroup = $settingsChildren->first();
$fields = $fieldGroup->getChildren();
CommentTestHelper::assertFieldNames(
$this,
array('ProvideComments', 'CommentsRequireLogin'),
$fields
);
Config::inst()->update('CommentableItem', 'comments', array(
'require_login_cms' => true,
'require_moderation_cms' => true
)
);
$fields = $item->getCMSFields();
CommentTestHelper::assertFieldsForTab(
$this,
'Root.Settings',
array('Comments', 'ModerationRequired'), $fields
);
$settingsTab = $fields->findOrMakeTab('Root.Settings');
$settingsChildren = $settingsTab->getChildren();
$this->assertEquals(2, $settingsChildren->count());
$fieldGroup = $settingsChildren->first();
$fields = $fieldGroup->getChildren();
CommentTestHelper::assertFieldNames(
$this,
array('ProvideComments', 'CommentsRequireLogin'),
$fields
);
}
public function testDeprecatedMethods() {
$item = $this->objFromFixture('CommentableItem', 'first');
$methodNames = array(
'getRssLinkPage',
'getRssLink',
'PageComments',
'getPostingRequiresPermission',
'canPost',
'getCommentsConfigured'
);
foreach ($methodNames as $methodName) {
try {
$item->$methodName();
$this->fail('Method ' . $methodName .' should be depracated');
} catch (PHPUnit_Framework_Error_Deprecated $e) {
$expected = 'CommentsExtension->' . $methodName . ' is '.
'deprecated.';
$this->assertStringStartsWith($expected, $e->getMessage());
}
}
// ooh, $this->setExpectedException('ExpectedException', 'Expected Message');
}
}

View File

@ -0,0 +1,133 @@
<?php
class CommentsGridFieldActionTest extends SapphireTest {
/** @var ArrayList */
protected $list;
/** @var GridField */
protected $gridField;
/** @var Form */
protected $form;
public function setUp() {
parent::setUp();
$this->list = new DataList('GridFieldAction_Delete_Team');
$config = CommentsGridFieldConfig::create()->addComponent(new GridFieldDeleteAction());
$this->gridField = new CommentsGridField('testfield', 'testfield', $this->list, $config);
$this->form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList());
}
public function testAugmentColumns() {
$action = new CommentsGridFieldAction();
// an entry called 'Actions' is added to the columns array
$columns = array();
$action->augmentColumns($this->gridField, $columns);
$expected = array('Actions');
$this->assertEquals($expected, $columns);
$columns = array('Actions');
$action->augmentColumns($this->gridField, $columns);
$expected = array('Actions');
$this->assertEquals($expected, $columns);
}
public function testGetColumnAttributes() {
$action = new CommentsGridFieldAction();
$record = new Comment();
$attrs = $action->getColumnAttributes($this->gridField, $record, 'Comment');
$this->assertEquals(array('class' => 'col-buttons'), $attrs);
}
public function testGetColumnMetadata() {
$action = new CommentsGridFieldAction();
$result = $action->getColumnMetadata($this->gridField, 'Actions');
$this->assertEquals(array('title' => ''), $result);
$result = $action->getColumnMetadata($this->gridField, 'SomethingElse');
$this->assertNull($result);
}
public function testGetColumnsHandled() {
$action = new CommentsGridFieldAction();
$result = $action->getColumnsHandled($this->gridField);
$this->assertEquals(array('Actions'), $result);
}
public function testGetColumnContent() {
$this->logInWithPermission('CMS_ACCESS_CommentAdmin');
$action = new CommentsGridFieldAction();
$record = new Comment();
$record->Name = 'Name of commeter';
$record->Comment = 'This is a comment';
$record->write();
$recordID = $record->ID;
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
$this->assertContains('data-url="Controller/mockform/field/testfield',
$html);
$spamAction = 'value="Spam" class="action" id="action_CustomAction' .
$recordID . 'Spam"';
$this->assertContains($spamAction, $html);
$approveAction = 'value="Approve" class="action" id="action_CustomAction' .
$recordID . 'Approve"';
$this->assertContains($approveAction, $html);
// If marked as spam, only the approve button should be available
$record->markSpam();
$record->write();
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
$this->assertContains($approveAction, $html);
$this->assertNotContains($spamAction, $html);
// If marked as spam, only the approve button should be available
$record->markApproved();
$record->write();
$html = $action->getColumnContent($this->gridField, $record, 'Comment');
$this->assertNotContains($approveAction, $html);
$this->assertContains($spamAction, $html);
}
public function testGetActions() {
$action = new CommentsGridFieldAction();
$result = $action->getActions($this->gridField);
$this->assertEquals(array('spam', 'approve'), $result);
}
public function testHandleAction() {
$action = new CommentsGridFieldAction();
$record = new Comment();
$record->Name = 'Name of commeter';
$record->Comment = 'This is a comment';
$record->write();
$recordID = $record->ID;
$arguments = array('RecordID' => $recordID);
$data = array();
$result = $action->handleAction($this->gridField, 'spam', $arguments, $data );
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
$this->assertEquals(
'Comment marked as spam.',
Controller::curr()->getResponse()->getStatusDescription()
);
$record = DataObject::get_by_id('Comment', $recordID);
$this->assertEquals(1, $record->Moderated);
$this->assertEquals(1, $record->IsSpam);
//getStatusDescription
$result = $action->handleAction($this->gridField, 'approve', $arguments, $data );
$this->assertEquals(200, Controller::curr()->getResponse()->getStatusCode());
$this->assertEquals(
'Comment approved.',
Controller::curr()->getResponse()->getStatusDescription()
);
$record = DataObject::get_by_id('Comment', $recordID);
$this->assertEquals(1, $record->Moderated);
$this->assertEquals(0, $record->IsSpam);
error_log(Controller::curr()->getResponse()->getStatusCode());
}
}

View File

@ -0,0 +1,12 @@
<?php
class CommentsGridFieldBulkActionTest extends SapphireTest {
public function testSpam() {
$this->markTestSkipped('TODO');
}
public function testApprove() {
$this->markTestSkipped('TODO');
}
}

View File

@ -0,0 +1,9 @@
<?php
class CommentsGridFieldConfigTest extends SapphireTest {
public function test__construct() {
$config = new CommentsGridFieldConfigTest();
$this->markTestSkipped('TODO');
}
}

View File

@ -0,0 +1,40 @@
<?php
class CommentsGridFieldTest extends SapphireTest {
public function testNewRow() {
$gridfield = new CommentsGridField('testfield', 'testfield');
// protected function newRow($total, $index, $record, $attributes, $content) {
$comment = new Comment();
$comment->Name = 'Fred Bloggs';
$comment->Comment = 'This is a comment';
$attr = array();
try {
$class = new ReflectionClass($gridfield);
$method = $class->getMethod('newRow');
$method->setAccessible(true);
}
catch (ReflectionException $e) {
$this->fail($e->getMessage());
}
$params = array(1, 1, $comment, $attr, $comment->Comment);
$newRow = $method->invokeArgs($gridfield, $params);
$this->assertEquals('<tr>This is a comment</tr>', $newRow);
$attr = array('class' => 'cssClass');
$params = array(1, 1, $comment, $attr, $comment->Comment);
$newRow = $method->invokeArgs($gridfield, $params);
$this->assertEquals('<tr class="cssClass">This is a comment</tr>', $newRow);
$comment->markSpam();
$params = array(1, 1, $comment, $attr, $comment->Comment);
$newRow = $method->invokeArgs($gridfield, $params);
$this->assertEquals('<tr class="cssClass spam">This is a comment</tr>', $newRow);
}
}

View File

@ -4,9 +4,9 @@
* @package comments
*/
class CommentsTest extends FunctionalTest {
public static $fixture_file = 'comments/tests/CommentsTest.yml';
protected $extraDataObjects = array(
'CommentableItem',
'CommentableItemEnabled',
@ -75,7 +75,7 @@ class CommentsTest extends FunctionalTest {
// require_moderation_nonmembers still filters out unmoderated comments
Config::inst()->update('CommentableItem', 'comments', array('require_moderation' => false));
$this->assertEquals(1, $item->Comments()->Count());
Config::inst()->update('CommentableItem', 'comments', array('require_moderation_nonmembers' => false));
$this->assertEquals(2, $item->Comments()->Count());
@ -212,50 +212,8 @@ class CommentsTest extends FunctionalTest {
$this->logInWithPermission('ANY_PERMISSION');
$this->assertTrue($item->canPostComment());
$this->assertTrue($item2->canPostComment());
}
public function testCanView() {
$visitor = $this->objFromFixture('Member', 'visitor');
$admin = $this->objFromFixture('Member', 'commentadmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertTrue($comment->canView($visitor),
'Unauthenticated members can view comments associated to a object with ProvideComments=1'
);
$this->assertTrue($comment->canView($admin),
'Admins with CMS_ACCESS_CommentAdmin permissions can view comments associated to a page with ProvideComments=1'
);
$disabledComment = $this->objFromFixture('Comment', 'disabledCom');
$this->assertFalse($disabledComment->canView($visitor),
'Unauthenticated members can not view comments associated to a object with ProvideComments=0'
);
$this->assertTrue($disabledComment->canView($admin),
'Admins with CMS_ACCESS_CommentAdmin permissions can view comments associated to a page with ProvideComments=0'
);
}
public function testCanEdit() {
$visitor = $this->objFromFixture('Member', 'visitor');
$admin = $this->objFromFixture('Member', 'commentadmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertFalse($comment->canEdit($visitor));
$this->assertTrue($comment->canEdit($admin));
}
public function testCanDelete() {
$visitor = $this->objFromFixture('Member', 'visitor');
$admin = $this->objFromFixture('Member', 'commentadmin');
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertFalse($comment->canEdit($visitor));
$this->assertTrue($comment->canEdit($admin));
}
public function testDeleteComment() {
// Test anonymous user
if($member = Member::currentUser()) $member->logOut();
@ -378,7 +336,7 @@ class CommentsTest extends FunctionalTest {
// Cannot re-ham hammed comment
$this->assertNull($check->HamLink());
}
public function testApproveComment() {
// Test anonymous user
if($member = Member::currentUser()) $member->logOut();
@ -445,10 +403,15 @@ class CommentsTest extends FunctionalTest {
return;
}
$origAllowed = Commenting::get_config_value('CommentableItem','html_allowed');
// Add p for paragraph
// NOTE: The config method appears to append to the existing array
Config::inst()->update('CommentableItem', 'comments', array(
'html_allowed_elements' => array('p'),
));
// Without HTML allowed
$comment1 = new Comment();
$comment1->AllowHtml = false;
$comment1->BaseClass = 'CommentableItem';
$comment1->Comment = '<p><script>alert("w00t")</script>my comment</p>';
$comment1->write();
@ -460,8 +423,8 @@ class CommentsTest extends FunctionalTest {
);
// With HTML allowed
Commenting::set_config_value('CommentableItem','html_allowed', true);
$comment2 = new Comment();
$comment2->AllowHtml = true;
$comment2->BaseClass = 'CommentableItem';
$comment2->Comment = '<p><script>alert("w00t")</script>my comment</p>';
$comment2->write();
@ -470,8 +433,6 @@ class CommentsTest extends FunctionalTest {
$comment2->Comment,
'Removes HTML tags which are not on the whitelist'
);
Commenting::set_config_value('CommentableItem','html_allowed', $origAllowed);
}
public function testDefaultTemplateRendersHtmlWithAllowHtml() {
@ -479,31 +440,35 @@ class CommentsTest extends FunctionalTest {
$this->markTestSkipped('HTMLPurifier class not found');
}
$origAllowed = Commenting::get_config_value('CommentableItem', 'html_allowed');
Config::inst()->update('CommentableItem', 'comments', array(
'html_allowed_elements' => array('p'),
));
$item = new CommentableItem();
$item->write();
// Without HTML allowed
$comment = new Comment();
$comment->Comment = '<p>my comment</p>';
$comment->AllowHtml = false;
$comment->ParentID = $item->ID;
$comment->BaseClass = 'CommentableItem';
$comment->write();
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
$this->assertContains(
'&lt;p&gt;my comment&lt;/p&gt;',
$html
);
Commenting::set_config_value('CommentableItem','html_allowed', true);
$comment->AllowHtml = true;
$comment->write();
$html = $item->customise(array('CommentsEnabled' => true))->renderWith('CommentsInterface');
$this->assertContains(
'<p>my comment</p>',
$html
);
Commenting::set_config_value('CommentableItem','html_allowed', $origAllowed);
}
@ -559,6 +524,666 @@ class CommentsTest extends FunctionalTest {
$this->assertFalse((bool)$obj->CommentsRequireLogin);
}
/*
When a parent comment is deleted, remove the children
*/
public function testOnBeforeDelete() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$child = new Comment();
$child->Name = 'Fred Bloggs';
$child->Comment = 'Child of firstComA';
$child->write();
$comment->ChildComments()->add($child);
$this->assertEquals(4, $comment->ChildComments()->count());
$commentID = $comment->ID;
$childCommentID = $child->ID;
$comment->delete();
// assert that the new child been deleted
$this->assertFalse(DataObject::get_by_id('Comment', $commentID));
$this->assertFalse(DataObject::get_by_id('Comment', $childCommentID));
}
public function testRequireDefaultRecords() {
$this->markTestSkipped('TODO');
}
public function testLink() {
$comment = $this->objFromFixture('Comment', 'thirdComD');
$this->assertEquals('CommentableItem_Controller#comment-'.$comment->ID,
$comment->Link());
$this->assertEquals($comment->ID, $comment->ID);
// An orphan comment has no link
$comment->ParentID = 0;
$comment->write();
$this->assertEquals('', $comment->Link());
}
public function testPermalink() {
$comment = $this->objFromFixture('Comment', 'thirdComD');
$this->assertEquals('comment-' . $comment->ID, $comment->Permalink());
}
/*
Test field labels in 2 languages
*/
public function testFieldLabels() {
$locale = i18n::get_locale();
i18n::set_locale('fr');
$comment = $this->objFromFixture('Comment', 'firstComA');
$labels = $comment->FieldLabels();
$expected = array(
'Name' => 'Nom de l\'Auteur',
'Comment' => 'Commentaire',
'Email' => 'Email',
'URL' => 'URL',
'BaseClass' => 'Base Class',
'Moderated' => 'Modéré?',
'IsSpam' => 'Spam?',
'ParentID' => 'Parent ID',
'AllowHtml' => 'Allow Html',
'SecretToken' => 'Secret Token',
'Depth' => 'Depth',
'Author' => 'Author Member',
'ParentComment' => 'Parent Comment',
'ChildComments' => 'Child Comments',
'ParentTitle' => 'Parent',
'Created' => 'Date de publication'
);
i18n::set_locale($locale);
$this->assertEquals($expected, $labels);
$labels = $comment->FieldLabels();
$expected = array(
'Name' => 'Author Name',
'Comment' => 'Comment',
'Email' => 'Email',
'URL' => 'URL',
'BaseClass' => 'Base Class',
'Moderated' => 'Moderated?',
'IsSpam' => 'Spam?',
'ParentID' => 'Parent ID',
'AllowHtml' => 'Allow Html',
'SecretToken' => 'Secret Token',
'Depth' => 'Depth',
'Author' => 'Author Member',
'ParentComment' => 'Parent Comment',
'ChildComments' => 'Child Comments',
'ParentTitle' => 'Parent',
'Created' => 'Date posted'
);
$this->assertEquals($expected, $labels);
}
public function testGetOption() {
$this->markTestSkipped('TODO');
}
public function testGetParent() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$item = $this->objFromFixture('CommentableItem', 'first');
$parent = $comment->getParent();
$this->assertEquals($item, $parent);
}
public function testGetParentTitle() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$title = $comment->getParentTitle();
$this->assertEquals('First', $title);
// Title from a comment with no parent is blank
$comment->ParentID = 0;
$comment->write();
$this->assertEquals('', $comment->getParentTitle());
}
public function testGetParentClassName() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$className = $comment->getParentClassName();
$this->assertEquals('CommentableItem', $className);
}
public function testCastingHelper() {
$this->markTestSkipped('TODO');
}
public function testGetEscapedComment() {
$this->markTestSkipped('TODO');
}
public function testIsPreview() {
$comment = new Comment();
$comment->Name = 'Fred Bloggs';
$comment->Comment = 'this is a test comment';
$this->assertTrue($comment->isPreview());
$comment->write();
$this->assertFalse($comment->isPreview());
}
public function testCanCreate() {
$comment = $this->objFromFixture('Comment', 'firstComA');
// admin can create - this is always false
$this->logInAs('commentadmin');
$this->assertFalse($comment->canCreate());
// visitor can view
$this->logInAs('visitor');
$this->assertFalse($comment->canCreate());
}
public function testCanView() {
$comment = $this->objFromFixture('Comment', 'firstComA');
// admin can view
$this->logInAs('commentadmin');
$this->assertTrue($comment->canView());
// visitor can view
$this->logInAs('visitor');
$this->assertTrue($comment->canView());
$comment->ParentID = 0;
$comment->write();
$this->assertFalse($comment->canView());
}
public function testCanEdit() {
$comment = $this->objFromFixture('Comment', 'firstComA');
// admin can edit
$this->logInAs('commentadmin');
$this->assertTrue($comment->canEdit());
// visitor cannot
$this->logInAs('visitor');
$this->assertFalse($comment->canEdit());
$comment->ParentID = 0;
$comment->write();
$this->assertFalse($comment->canEdit());
}
public function testCanDelete() {
$comment = $this->objFromFixture('Comment', 'firstComA');
// admin can delete
$this->logInAs('commentadmin');
$this->assertTrue($comment->canDelete());
// visitor cannot
$this->logInAs('visitor');
$this->assertFalse($comment->canDelete());
$comment->ParentID = 0;
$comment->write();
$this->assertFalse($comment->canDelete());
}
public function testGetMember() {
$this->logInAs('visitor');
$current = Member::currentUser();
$comment = $this->objFromFixture('Comment', 'firstComA');
$method = $this->getMethod('getMember');
// null case
$member = $method->invokeArgs($comment, array());
$this->assertEquals($current, $member);
// numeric ID case
$member = $method->invokeArgs($comment, array($current->ID));
$this->assertEquals($current, $member);
// identity case
$member = $method->invokeArgs($comment, array($current));
$this->assertEquals($current, $member);
}
public function testGetAuthorName() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(
'FA',
$comment->getAuthorName()
);
$comment->Name = '';
$this->assertEquals(
'',
$comment->getAuthorName()
);
$author = $this->objFromFixture('Member', 'visitor');
$comment->AuthorID = $author->ID;
$comment->write();
$this->assertEquals(
'visitor',
$comment->getAuthorName()
);
// null the names, expect null back
$comment->Name = null;
$comment->AuthorID = 0;
$this->assertNull($comment->getAuthorName());
}
public function testLinks() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->logInAs('commentadmin');
$method = $this->getMethod('ActionLink');
// test with starts of strings and tokens and salts change each time
$this->assertStringStartsWith(
'/CommentingController/theaction/'.$comment->ID,
$method->invokeArgs($comment, array('theaction'))
);
$this->assertStringStartsWith(
'/CommentingController/delete/'.$comment->ID,
$comment->DeleteLink()
);
$this->assertStringStartsWith(
'/CommentingController/spam/'.$comment->ID,
$comment->SpamLink()
);
$comment->markSpam();
$this->assertStringStartsWith(
'/CommentingController/ham/'.$comment->ID,
$comment->HamLink()
);
//markApproved
$comment->markUnapproved();
$this->assertStringStartsWith(
'/CommentingController/approve/'.$comment->ID,
$comment->ApproveLink()
);
}
public function testMarkSpam() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->markSpam();
$this->assertTrue($comment->Moderated);
$this->assertTrue($comment->IsSpam);
}
public function testMarkApproved() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->markApproved();
$this->assertTrue($comment->Moderated);
$this->assertFalse($comment->IsSpam);
}
public function testMarkUnapproved() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->markApproved();
$this->assertTrue($comment->Moderated);
}
public function testSpamClass() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals('notspam', $comment->spamClass());
$comment->Moderated = false;
$this->assertEquals('unmoderated', $comment->spamClass());
$comment->IsSpam = true;
$this->assertEquals('spam', $comment->spamClass());
}
public function testGetTitle() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(
'Comment by FA on First',
$comment->getTitle()
);
}
public function testGetCMSFields() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$fields = $comment->getCMSFields();
$names = array();
foreach ($fields as $field) {
$names[] = $field->getName();
}
$expected = array(
'Created',
'Name',
'Comment',
'Email',
'URL',
null #FIXME this is suspicious
);
$this->assertEquals($expected, $names);
}
public function testGetCMSFieldsCommentHasAuthor() {
$member = Member::get()->filter('FirstName', 'visitor')->first();
$comment = $this->objFromFixture('Comment', 'firstComA');
$comment->AuthorID = $member->ID;
$comment->write();
$fields = $comment->getCMSFields();
$names = array();
foreach ($fields as $field) {
$names[] = $field->getName();
}
$expected = array(
'Created',
'Name',
'AuthorMember',
'Comment',
'Email',
'URL',
null #FIXME this is suspicious
);
$this->assertEquals($expected, $names);
}
public function testGetCMSFieldsWithParentComment() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$child = new Comment();
$child->Name = 'John Smith';
$child->Comment = 'This is yet another test commnent';
$child->ParentCommentID = $comment->ID;
$child->write();
$fields = $child->getCMSFields();
$names = array();
foreach ($fields as $field) {
$names[] = $field->getName();
}
$expected = array(
'Created',
'Name',
'Comment',
'Email',
'URL',
null, #FIXME this is suspicious
'ParentComment_Title',
'ParentComment_Created',
'ParentComment_AuthorName',
'ParentComment_EscapedComment'
);
$this->assertEquals($expected, $names);
}
public function testPurifyHtml() {
$comment = $this->objFromFixture('Comment', 'firstComA');
$dirtyHTML = '<p><script>alert("w00t")</script>my comment</p>';
$this->assertEquals(
'my comment',
$comment->purifyHtml($dirtyHTML)
);
}
public function testGravatar() {
// Turn gravatars on
Config::inst()->update('CommentableItem', 'comments', array(
'use_gravatar' => true
));
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(
'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?s'.
'=80&d=identicon&r=g',
$comment->gravatar()
);
// Turn gravatars off
Config::inst()->update('CommentableItem', 'comments', array(
'use_gravatar' => false
));
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(
'',
$comment->gravatar()
);
}
public function testGetRepliesEnabled() {
$comment = $this->objFromFixture('Comment', 'firstComA');
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => false
));
$this->assertFalse($comment->getRepliesEnabled());
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4
));
$this->assertTrue($comment->getRepliesEnabled());
$comment->Depth = 4;
$this->assertFalse($comment->getRepliesEnabled());
}
public function testAllReplies() {
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4
));
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(
3,
$comment->allReplies()->count()
);
$child = new Comment();
$child->Name = 'Fred Smith';
$child->Comment = 'This is a child comment';
$child->ParentCommentID = $comment->ID;
// spam should be returned by this method
$child->markSpam();
$child->write();
$replies = $comment->allReplies();
$this->assertEquals(
4,
$comment->allReplies()->count()
);
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => false
));
$this->assertEquals(0, $comment->allReplies()->count());
}
public function testReplies() {
CommentableItem::add_extension('CommentsExtension');
$this->logInWithPermission('ADMIN');
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4
));
$comment = $this->objFromFixture('Comment', 'firstComA');
$this->assertEquals(
3,
$comment->Replies()->count()
);
// Test that spam comments are not returned
$childComment = $comment->Replies()->first();
$childComment->IsSpam = 1;
$childComment->write();
$this->assertEquals(
2,
$comment->Replies()->count()
);
// Test that unmoderated comments are not returned
//
$childComment = $comment->Replies()->first();
// FIXME - moderation settings scenarios need checked here
$childComment->Moderated = 0;
$childComment->IsSpam = 0;
$childComment->write();
$this->assertEquals(
2,
$comment->Replies()->count()
);
// Test moderation required on the front end
$item = $this->objFromFixture('CommentableItem', 'first');
$item->ModerationRequired = 'Required';
$item->write();
Config::inst()->update('CommentableItemDisabled', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4,
'frontend_moderation' => true
));
$comment = DataObject::get_by_id('Comment', $comment->ID);
$this->assertEquals(
2,
$comment->Replies()->count()
);
// Turn off nesting, empty array should be returned
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => false
));
$this->assertEquals(
0,
$comment->Replies()->count()
);
CommentableItem::remove_extension('CommentsExtension');
}
public function testPagedReplies() {
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4,
'comments_per_page' => 2 #Force 2nd page for 3 items
));
$comment = $this->objFromFixture('Comment', 'firstComA');
$pagedList = $comment->pagedReplies();
$this->assertEquals(
2,
$pagedList->TotalPages()
);
$this->assertEquals(
3,
$pagedList->getTotalItems()
);
//TODO - 2nd page requires controller
//
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => false
));
$this->assertEquals(0, $comment->PagedReplies()->count());
}
public function testReplyForm() {
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => false,
'nested_depth' => 4
));
$comment = $this->objFromFixture('Comment', 'firstComA');
// No nesting, no reply form
$form = $comment->replyForm();
$this->assertNull($form);
// parent item so show form
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4
));
$form = $comment->replyForm();
$names = array();
foreach ($form->Fields() as $field) {
array_push($names, $field->getName());
}
$this->assertEquals(
array(
null, #FIXME suspicious
'ParentID',
'ReturnURL',
'ParentCommentID',
'BaseClass'
),
$names
);
// no parent, no reply form
$comment->ParentID = 0;
$comment->write();
$form = $comment->replyForm();
$this->assertNull($form);
}
public function testUpdateDepth() {
Config::inst()->update('CommentableItem', 'comments', array(
'nested_comments' => true,
'nested_depth' => 4
));
$comment = $this->objFromFixture('Comment', 'firstComA');
$children = $comment->allReplies()->toArray();
// Make the second child a child of the first
// Make the third child a child of the second
$reply1 = $children[0];
$reply2 = $children[1];
$reply3 = $children[2];
$reply2->ParentCommentID = $reply1->ID;
$reply2->write();
$this->assertEquals(3, $reply2->Depth);
$reply3->ParentCommentID = $reply2->ID;
$reply3->write();
$this->assertEquals(4, $reply3->Depth);
}
public function testGetToken() {
$this->markTestSkipped('TODO');
}
public function testMemberSalt() {
$this->markTestSkipped('TODO');
}
public function testAddToUrl() {
$this->markTestSkipped('TODO');
}
public function testCheckRequest() {
$this->markTestSkipped('TODO');
}
public function testGenerate() {
$this->markTestSkipped('TODO');
}
protected static function getMethod($name) {
$class = new ReflectionClass('Comment');
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
}
@ -581,8 +1206,18 @@ class CommentableItem extends DataObject implements TestOnly {
}
public function canView($member = null) {
return true;
}
return true;
}
// This is needed for canModerateComments
public function canEdit($member = null) {
if($member instanceof Member) $memberID = $member->ID;
else if(is_numeric($member)) $memberID = $member;
else $memberID = Member::currentUserID();
if($memberID && Permission::checkMember($memberID, array("ADMIN", "CMS_ACCESS_CommentAdmin"))) return true;
return false;
}
public function Link() {
return $this->RelativeLink();
@ -615,7 +1250,7 @@ class CommentableItemDisabled extends CommentableItem {
* @subpackage tests
*/
class CommentableItem_Controller extends Controller implements TestOnly {
public function index() {
return CommentableItem::get()->first()->CommentsForm();
}

View File

@ -43,7 +43,35 @@ Comment:
Comment: textFA
BaseClass: CommentableItem
Moderated: 1
IsSpam:
Depth: 1
firstComAChild1:
ParentID: =>CommentableItem.first
ParentCommentID: =>Comment.firstComA
Name: John Smith
Comment: Reply to firstComA 1
BaseClass: CommentableItem
Moderated: 1
IsSpam: 0
Depth: 2
firstComAChild2:
ParentID: =>CommentableItem.first
ParentCommentID: =>Comment.firstComA
Name: John Smith
Comment: Reply to firstComA 2
BaseClass: CommentableItem
Moderated: 1
IsSpam: 0
Depth: 2
firstComAChild3:
ParentID: =>CommentableItem.first
ParentCommentID: =>Comment.firstComA
Name: John Smith
Comment: Reply to firstComA 3
BaseClass: CommentableItem
Moderated: 1
IsSpam: 0
Depth: 2
secondComA:
ParentID: =>CommentableItem.second
Name: SA
@ -169,4 +197,4 @@ Comment:
Name: Comment 4
Moderated: 0
IsSpam: 1
BaseClass: CommentableItem
BaseClass: CommentableItem