diff --git a/.github/workflows/main.yml b/.github/workflows/docs.yml similarity index 100% rename from .github/workflows/main.yml rename to .github/workflows/docs.yml diff --git a/.travis.yml b/.travis.yml index a371558..3f97107 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,4 @@ import: env: global: - BEHAT_SUITE="contentreview" + - REQUIRE_EXTRA="symbiote/silverstripe-queuedjobs:^4" diff --git a/behat.yml b/behat.yml index 86e1026..6afcfff 100644 --- a/behat.yml +++ b/behat.yml @@ -2,18 +2,19 @@ default: suites: contentreview: paths: - - '%paths.modules.contentreview%/tests/behat/features' + - "%paths.modules.contentreview%/tests/behat/features" contexts: - - SilverStripe\Framework\Tests\Behaviour\FeatureContext - - SilverStripe\Framework\Tests\Behaviour\CmsFormsContext - - SilverStripe\Framework\Tests\Behaviour\CmsUiContext + - SilverStripe\Admin\Tests\Behat\Context\AdminContext - SilverStripe\BehatExtension\Context\BasicContext - SilverStripe\BehatExtension\Context\EmailContext - - SilverStripe\CMS\Tests\Behaviour\LoginContext - - SilverStripe\CMS\Tests\Behaviour\ThemeContext - - SilverStripe\CMS\Tests\Behaviour\FixtureContext: - # Note: double indent for args is intentional - - '%paths.modules.contentreview%/tests/behat/features/files/' + - SilverStripe\BehatExtension\Context\LoginContext + - SilverStripe\Framework\Tests\Behaviour\CmsFormsContext + - SilverStripe\Framework\Tests\Behaviour\CmsUiContext + - SilverStripe\ContentReview\Tests\Behat\Context\FeatureContext + - SilverStripe\ContentReview\Tests\Behat\Context\FixtureContext + - + SilverStripe\ContentReview\Tests\Behat\Context\FixtureContext: + - "%paths.modules.contentreview%/tests/behat/files/" extensions: SilverStripe\BehatExtension\MinkExtension: @@ -21,9 +22,8 @@ default: javascript_session: facebook_web_driver facebook_web_driver: browser: chrome - wd_host: "http://127.0.0.1:9515" #chromedriver port - browser_name: chrome - + wd_host: "http://127.0.0.1:9515" + SilverStripe\BehatExtension\Extension: - screenshot_path: '%paths.base%/artifacts/screenshots' - bootstrap_file: "vendor/silverstripe/cms/tests/behat/serve-bootstrap.php" + screenshot_path: "%paths.base%/artifacts/screenshots" + bootstrap_file: vendor/silverstripe/framework/tests/behat/serve-bootstrap.php diff --git a/composer.json b/composer.json index f9f78b5..7721077 100644 --- a/composer.json +++ b/composer.json @@ -20,18 +20,16 @@ } ], "require": { + "php": "^7.4 || ^8.0", "silverstripe/vendor-plugin": "^1", - "silverstripe/framework": "^4.2", + "silverstripe/framework": "^4.10", "silverstripe/cms": "^4.2", "silverstripe/reports": "^4.2", "silverstripe/siteconfig": "^4.2" }, "require-dev": { - "sminnee/phpunit": "^5.7", - "squizlabs/php_codesniffer": "^3", - "silverstripe/behat-extension": "^3", - "silverstripe/serve": "^2", - "se/selenium-server-standalone": "2.41.0" + "silverstripe/recipe-testing": "^2", + "squizlabs/php_codesniffer": "^3" }, "suggest": { "symbiote/silverstripe-queuedjobs": "Automatically schedules content review emails to be sent, only requiring one crontask to be created" @@ -44,9 +42,10 @@ "autoload": { "psr-4": { "SilverStripe\\ContentReview\\": "src/", - "SilverStripe\\ContentReview\\Tests\\": "tests/php/" + "SilverStripe\\ContentReview\\Tests\\": "tests/php/", + "SilverStripe\\ContentReview\\Tests\\Behat\\Context\\": "tests/behat/src/" } }, "minimum-stability": "dev", "prefer-stable": true -} \ No newline at end of file +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 965f16a..7e35d22 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,9 @@ - - tests/php/ - + + + tests/php/ + + src/ diff --git a/src/Jobs/ContentReviewNotificationJob.php b/src/Jobs/ContentReviewNotificationJob.php index 85d1d23..c04871a 100644 --- a/src/Jobs/ContentReviewNotificationJob.php +++ b/src/Jobs/ContentReviewNotificationJob.php @@ -80,7 +80,7 @@ class ContentReviewNotificationJob extends AbstractQueuedJob implements QueuedJo return QueuedJob::QUEUED; } - public function setup() + public function setUp() { parent::setup(); diff --git a/src/Reports/PagesDueForReviewReport.php b/src/Reports/PagesDueForReviewReport.php index fc0bd02..cf4bfc3 100644 --- a/src/Reports/PagesDueForReviewReport.php +++ b/src/Reports/PagesDueForReviewReport.php @@ -148,16 +148,26 @@ class PagesDueForReviewReport extends Report /** * @param array $params + * @param array|string|null $sort + * @param int|null $limit * * @return SS_List */ - public function sourceRecords($params = []) + public function sourceRecords($params = [], $sort = null, $limit = null) { Versioned::set_stage(Versioned::DRAFT); $records = SiteTree::get(); $compatibility = ContentReviewCompatability::start(); + // Apply sort and limit if appropriate. + if ($sort !== null) { + $records = $records->sort($sort); + } + if ($limit !== null) { + $records = $records->limit($limit); + } + if (empty($params['ReviewDateBefore']) && empty($params['ReviewDateAfter'])) { // If there's no review dates set, default to all pages due for review now $records = $records->where( diff --git a/src/Reports/PagesWithoutReviewScheduleReport.php b/src/Reports/PagesWithoutReviewScheduleReport.php index 0f7b402..e471d1a 100644 --- a/src/Reports/PagesWithoutReviewScheduleReport.php +++ b/src/Reports/PagesWithoutReviewScheduleReport.php @@ -104,10 +104,12 @@ class PagesWithoutReviewScheduleReport extends Report /** * @param array $params + * @param array|string|null $sort + * @param int|null $limit * * @return SS_List */ - public function sourceRecords($params = []) + public function sourceRecords($params = [], $sort = null, $limit = null) { Versioned::set_stage(Versioned::DRAFT); @@ -125,16 +127,18 @@ class PagesWithoutReviewScheduleReport extends Report )); } - $records->sort("ParentID"); - $records = $records->toArray(); + // Apply sort and limit if appropriate. + if ($sort !== null) { + $records = $records->sort($sort); + } + if ($limit !== null) { + $records = $records->limit($limit); + } // Trim out calculated values - $list = ArrayList::create(); - foreach ($records as $record) { - if (!$this->hasReviewSchedule($record)) { - $list->push($record); - } - } + $list = $records->filterByCallback(function ($record) { + return !$this->hasReviewSchedule($record); + }); ContentReviewCompatability::done($compatibility); diff --git a/tests/behat/features/content-reviews.feature b/tests/behat/features/content-reviews.feature new file mode 100644 index 0000000..94798a9 --- /dev/null +++ b/tests/behat/features/content-reviews.feature @@ -0,0 +1,54 @@ +Feature: Set up reviews + As a CMS user + I can set up content reviews for my content + In order to ensure my content gets reviewed regularly + + Background: + # Note: the review date is deliberately in the past + Given a "page" "My page" with "Content"="

Welcome

", "NextReviewDate"="01/01/2017", "ReviewPeriodDays"="1" + And the "group" "EDITOR group" has permissions "CMS_ACCESS_LeftAndMain" and "FILE_EDIT_ALL" + And the "group" "FILEONLY group" has permissions "FILE_EDIT_ALL" + And a "member" "Ed" belonging to "EDITOR group" with "Email"="ed@example.com" + And a "member" "Phil" belonging to "FILEONLY group" with "Email"="phil@example.com" + # Login in as EDITOR once https://github.com/silverstripe/silverstripe-contentreview/pull/155 is merged + # And I am logged in with "EDITOR" permissions + And I am logged in with "ADMIN" permissions + And I go to "admin/pages" + And I click on "My page" in the tree + And I click the "Settings" CMS tab + And I click the "Content review" CMS tab + + Scenario: I can set content reviewers to users and groups who can edit pages + When I select "Custom settings" from "Options" input group + And I wait for 1 second + + # Test adding individual member based on them having access to the Pages section fo the CMS + Then the "#Form_EditForm_OwnerUsers" select element should have an option with an "Ed" label + And the "#Form_EditForm_OwnerUsers" select element should not have an option with a "Phil" label + + # Test adding groups + Then the "#Form_EditForm_OwnerGroups" select element should have an option with an "EDITOR group" label + + # Required to avoid "unsaved changed" browser dialog + Then I press the "Save" button + + Scenario: There is an alert icon when a content review is overdue + When I select "Custom settings" from "Options" input group + And I wait for 1 second + Then I should not see the ".content-review__button" element + When I press the "Save" button + And I select "ADMIN group" from "Groups" + And I press the "Save" button + Then I should see the ".content-review__button" element + When I click on the ".content-review__button" element + Then I should see the ".modal" element + And I should see "Mark as reviewed" + + # Fill in a review + When I fill in "Form_EditForm_ReviewContent_Review" with "My review" + And I press "Mark as reviewed" + And I wait for 1 second + Then I should see "Review successfully added" + When I click on the ".close" element + And I press the "Save" button + Then I should see "My review" diff --git a/tests/behat/files/blank.txt b/tests/behat/files/blank.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/behat/src/FeatureContext.php b/tests/behat/src/FeatureContext.php new file mode 100644 index 0000000..19df65e --- /dev/null +++ b/tests/behat/src/FeatureContext.php @@ -0,0 +1,29 @@ + option').forEach(function(option) { + if (option.innerHTML == '$label') { + hasLabel = 1; + } + }); + return hasLabel; +JS; + return $this->getSession()->evaluateScript($js) == $n; + } +} diff --git a/tests/behat/src/FixtureContext.php b/tests/behat/src/FixtureContext.php new file mode 100644 index 0000000..3d34479 --- /dev/null +++ b/tests/behat/src/FixtureContext.php @@ -0,0 +1,9 @@ +translatableEnabledBefore) { diff --git a/tests/php/ContentReviewCMSPageEditControllerTest.php b/tests/php/ContentReviewCMSPageEditControllerTest.php index afcb051..5f5e048 100644 --- a/tests/php/ContentReviewCMSPageEditControllerTest.php +++ b/tests/php/ContentReviewCMSPageEditControllerTest.php @@ -17,9 +17,6 @@ use SilverStripe\Security\Group; use SilverStripe\Security\Member; use SilverStripe\SiteConfig\SiteConfig; -/** - * @mixin PHPUnit_Framework_TestCase - */ class ContentReviewCMSPageEditControllerTest extends ContentReviewBaseTest { /** diff --git a/tests/php/ContentReviewNotificationTest.php b/tests/php/ContentReviewNotificationTest.php index 019fa4a..d2e7aca 100644 --- a/tests/php/ContentReviewNotificationTest.php +++ b/tests/php/ContentReviewNotificationTest.php @@ -18,9 +18,6 @@ use SilverStripe\Security\Member; use SilverStripe\SiteConfig\SiteConfig; use SilverStripe\ContentReview\Models\ContentReviewLog; -/** - * @mixin PHPUnit_Framework_TestCase - */ class ContentReviewNotificationTest extends SapphireTest { /** @@ -28,7 +25,7 @@ class ContentReviewNotificationTest extends SapphireTest */ protected static $fixture_file = 'ContentReviewTest.yml'; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -70,15 +67,15 @@ class ContentReviewNotificationTest extends SapphireTest $email = $this->findEmail($ToEmail, null, $Subject); $this->assertNotNull($email, "Email haven't been sent."); - $this->assertContains( + $this->assertStringContainsString( "

$Subject

". "

There are $PagesCount pages that are due for review today by you, $ToFirstName.

". "

This email was sent to $ToEmail

", $email['HtmlContent'] ); - $this->assertContains('Staff', $email['HtmlContent']); - $this->assertContains('Contact Us', $email['HtmlContent']); - $this->assertContains('Contact Us Child', $email['HtmlContent']); + $this->assertStringContainsString('Staff', $email['HtmlContent']); + $this->assertStringContainsString('Contact Us', $email['HtmlContent']); + $this->assertStringContainsString('Contact Us Child', $email['HtmlContent']); DBDatetime::clear_mock_now(); } diff --git a/tests/php/ContentReviewReportTest.php b/tests/php/ContentReviewReportTest.php index 5179657..29628e2 100644 --- a/tests/php/ContentReviewReportTest.php +++ b/tests/php/ContentReviewReportTest.php @@ -87,11 +87,11 @@ class ContentReviewReportTest extends FunctionalTest $results = $report->sourceRecords(); - $this->assertEquals([ - "Home", - "About Us", - "Page without review date", - "Page owned by group", - ], $results->column("Title")); + $this->assertListEquals([ + ['Title' => 'Home'], + ['Title' => 'About Us'], + ['Title' => 'Page without review date'], + ['Title' => 'Page owned by group'], + ], $results); } } diff --git a/tests/php/ContentReviewSettingsTest.php b/tests/php/ContentReviewSettingsTest.php index f9b364a..1c35c50 100644 --- a/tests/php/ContentReviewSettingsTest.php +++ b/tests/php/ContentReviewSettingsTest.php @@ -4,7 +4,6 @@ namespace SilverStripe\ContentReview\Tests; use function date; use Page; -use PHPUnit_Framework_TestCase; use SilverStripe\CMS\Controllers\CMSPageEditController; use SilverStripe\CMS\Model\SiteTree; use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension; @@ -22,8 +21,6 @@ use SilverStripe\SiteConfig\SiteConfig; /** * This class tests that settings are inherited correctly based on the inherited, * custom or disabled settings. - * - * @mixin PHPUnit_Framework_TestCase */ class ContentReviewSettingsTest extends SapphireTest { diff --git a/tests/php/Extensions/ContentReviewCMSExtensionTest.php b/tests/php/Extensions/ContentReviewCMSExtensionTest.php index b060a90..d53abd8 100644 --- a/tests/php/Extensions/ContentReviewCMSExtensionTest.php +++ b/tests/php/Extensions/ContentReviewCMSExtensionTest.php @@ -5,6 +5,7 @@ namespace SilverStripe\ContentReview\Tests\Extensions; use SilverStripe\ContentReview\Extensions\ContentReviewCMSExtension; use SilverStripe\ContentReview\Forms\ReviewContentHandler; use SilverStripe\Control\Controller; +use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\HTTPRequest; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\Form; @@ -29,21 +30,17 @@ class ContentReviewCMSExtensionTest extends SapphireTest $this->assertTrue($result); } - /** - * @expectedException SilverStripe\Control\HTTPResponse_Exception - * @expectedExceptionMessage Bad record ID #1234 - */ public function testGetReviewContentFormThrowsExceptionWhenPageNotFound() { + $this->expectException(HTTPResponse_Exception::class); + $this->expectExceptionMessage('Bad record ID #1234'); (new ContentReviewCMSExtension)->getReviewContentForm(1234); } - /** - * @expectedException SilverStripe\Control\HTTPResponse_Exception - * @expectedExceptionMessage It seems you don't have the necessary permissions to review this content - */ public function testGetReviewContentFormThrowsExceptionWhenObjectCannotBeReviewed() { + $this->expectException(HTTPResponse_Exception::class); + $this->expectExceptionMessage('It seems you don\'t have the necessary permissions to review this content'); $this->logOut(); $mock = $this->getMockBuilder(ContentReviewCMSExtension::class) diff --git a/tests/php/Forms/ReviewContentHandlerTest.php b/tests/php/Forms/ReviewContentHandlerTest.php index 7561224..8b01163 100644 --- a/tests/php/Forms/ReviewContentHandlerTest.php +++ b/tests/php/Forms/ReviewContentHandlerTest.php @@ -14,6 +14,7 @@ use SilverStripe\Forms\Form; use SilverStripe\Forms\HiddenField; use SilverStripe\Forms\TextareaField; use SilverStripe\Security\Member; +use SilverStripe\ORM\ValidationException; class ReviewContentHandlerTest extends SapphireTest { @@ -37,12 +38,10 @@ class ReviewContentHandlerTest extends SapphireTest $this->assertTrue($saveAction->hasClass('review-content__action')); } - /** - * @expectedException SilverStripe\ORM\ValidationException - * @expectedExceptionMessage It seems you don't have the necessary permissions to submit a content review - */ public function testExceptionThrownWhenSubmittingReviewForInvalidObject() { + $this->expectException(ValidationException::class); + $this->expectExceptionMessage('It seems you don\'t have the necessary permissions to submit a content review'); ReviewContentHandler::create()->submitReview(new Member, ['foo' => 'bar']); } diff --git a/tests/php/SiteTreeContentReviewTest.php b/tests/php/SiteTreeContentReviewTest.php index aefebd5..395947d 100644 --- a/tests/php/SiteTreeContentReviewTest.php +++ b/tests/php/SiteTreeContentReviewTest.php @@ -17,9 +17,6 @@ use SilverStripe\Security\Member; use SilverStripe\SiteConfig\SiteConfig; use SilverStripe\Versioned\Versioned; -/** - * @mixin PHPUnit_Framework_TestCase - */ class SiteTreeContentReviewTest extends ContentReviewBaseTest { protected $usesTransactions = false; diff --git a/yarn.lock b/yarn.lock index 9032e2e..cebe530 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1933,7 +1933,7 @@ fstream-ignore@^1.0.5: inherits "2" minimatch "^3.0.0" -fstream@^1.0.0, fstream@^1.0.12: +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" dependencies: @@ -1942,15 +1942,6 @@ fstream@^1.0.0, fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" -fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - function-bind@^1.0.2, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -2058,8 +2049,8 @@ gonzales-pe@^4.1.1: minimist "1.1.x" graceful-fs@^4.1.2: - version "4.2.6" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" graceful-fs@^4.1.6: version "4.1.11" @@ -4395,7 +4386,7 @@ tar-pack@^3.4.0: tar "^2.2.1" uid-number "^0.0.6" -tar@^2.0.0: +tar@^2.0.0, tar@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" dependencies: @@ -4403,14 +4394,6 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"