My awesome content" @@ -102,7 +102,7 @@ So that I can link to a external website or a page on my site Then the "Content" HTML field should contain "awesome" # Required to avoid "unsaved changes" browser dialog When I press the "Save" button - Then I should see a "Saved 'About Us' successfully" success toast + Then I should see a "Saved Page "About Us"" success toast Scenario: I can remove an external link Given I fill in the "Content" HTML field with "My awesome content" @@ -112,7 +112,7 @@ So that I can link to a external website or a page on my site And the "Content" HTML field should not contain "http://silverstripe.org" # Required to avoid "unsaved changes" browser dialog When I press the "Save" button - Then I should see a "Saved 'About Us' successfully" success toast + Then I should see a "Saved Page "About Us"" success toast Scenario: I can navigate list of Site tree links by clicking on the dropdown elements When I select "awesome" in the "Content" HTML field diff --git a/tests/behat/features/insert-anchor-link.feature b/tests/behat/features/insert-anchor-link.feature index 931405f2f7..8527d55eea 100644 --- a/tests/behat/features/insert-anchor-link.feature +++ b/tests/behat/features/insert-anchor-link.feature @@ -28,7 +28,7 @@ So that I can link to a external website or a page on my site Then the "Content" HTML field should contain "awesome" # Required to avoid "unsaved changes" browser dialog When I press the "Save" button - Then I should see a "Saved 'About Us' successfully" success toast + Then I should see a "Saved Page "About Us"" success toast Scenario: I can wrap an image in a link to an anchor in an internal page Given I fill in the "Content" HTML field with "
" @@ -44,7 +44,7 @@ So that I can link to a external website or a page on my site Then the "Content" HTML field should contain "" # Required to avoid "unsaved changes" browser dialog When I press the "Save" button - Then I should see a "Saved 'About Us' successfully" success toast + Then I should see a "Saved Page "About Us"" success toast Scenario: I can link to an anchor from a dataobject on the current page When I select "awesome" in the "Content" HTML field @@ -59,7 +59,7 @@ So that I can link to a external website or a page on my site Then the "Content" HTML field should contain "awesome" # Required to avoid "unsaved changes" browser dialog When I press the "Save" button - Then I should see a "Saved 'About Us' successfully" success toast + Then I should see a "Saved Page "About Us"" success toast Scenario: I can link to an unsaved anchor in the current page Given I fill in the "Content" HTML field with "My awesome content
" @@ -77,4 +77,4 @@ So that I can link to a external website or a page on my site Then the "Content" HTML field should contain "awesome" # Required to avoid "unsaved changes" browser dialog When I press the "Save" button - Then I should see a "Saved 'About Us' successfully" success toast + Then I should see a "Saved Page "About Us"" success toast diff --git a/tests/behat/features/sitetree.feature b/tests/behat/features/sitetree.feature index d6ac54971b..bb38d84921 100644 --- a/tests/behat/features/sitetree.feature +++ b/tests/behat/features/sitetree.feature @@ -44,7 +44,7 @@ Feature: Sitetree When I click on the ".toast__close" element # Wait a little time to ensure the last toast is cleared And I wait for 2 seconds - + # Unpublish pages in a batch When I click on the "#record-2 .jstree-checkbox" element And I select "Unpublish" from the "Form_BatchActionsForm_Action" field with javascript @@ -66,10 +66,10 @@ Feature: Sitetree Then I should not see "Three" # Toggle list and tree views - Then I should not see a "#Form_ListViewForm_Page" element + Then I should not see a "#Form_ListViewForm_Record" element When I click on the "[data-view='listview']" element And I wait for 5 seconds - Then I should see a "#Form_ListViewForm_Page" element + Then I should see a "#Form_ListViewForm_Record" element When I click on the "[data-view='treeview']" element And I wait for 5 seconds - Then I should not see a "#Form_ListViewForm_Page" element + Then I should not see a "#Form_ListViewForm_Record" element diff --git a/tests/php/Controllers/CMSMainTest.php b/tests/php/Controllers/CMSMainTest.php index 0a9d0c8543..0312f74e37 100644 --- a/tests/php/Controllers/CMSMainTest.php +++ b/tests/php/Controllers/CMSMainTest.php @@ -2,11 +2,16 @@ namespace SilverStripe\CMS\Tests\Controllers; +use LogicException; +use PHPUnit\Framework\Attributes\DataProvider; use Psr\SimpleCache\CacheInterface; +use ReflectionMethod; use SilverStripe\Admin\CMSBatchActionHandler; use SilverStripe\CMS\Controllers\CMSMain; use SilverStripe\CMS\Model\RedirectorPage; use SilverStripe\CMS\Model\SiteTree; +use SilverStripe\CMS\Tests\Controllers\CMSMainTest\TestHierarchicalDataObject; +use SilverStripe\CMS\Tests\Controllers\CMSMainTest\TestHierarchicalDataObjectWithSort; use SilverStripe\CMS\Tests\Controllers\CMSMainTest\TestStatusFlagsPage; use SilverStripe\Control\Controller; use SilverStripe\Control\HTTPRequest; @@ -35,6 +40,8 @@ class CMSMainTest extends FunctionalTest protected static $extraDataObjects = [ TestStatusFlagsPage::class, + TestHierarchicalDataObject::class, + TestHierarchicalDataObjectWithSort::class, ]; protected function setUp(): void @@ -50,15 +57,15 @@ protected function setUp(): void } } - public function testSiteTreeHints() + public function testTreeHints() { - $cache = Injector::inst()->get(CacheInterface::class . '.CMSMain_SiteTreeHints'); + $cache = Injector::inst()->get(CacheInterface::class . '.CMSMain_TreeHints'); // Login as user with root creation privileges $user = $this->objFromFixture(Member::class, 'rootedituser'); Security::setCurrentUser($user); $cache->clear(); - $rawHints = singleton(CMSMain::class)->SiteTreeHints(); + $rawHints = singleton(CMSMain::class)->TreeHints(); $this->assertNotNull($rawHints); $rawHints = preg_replace('/^"(.*)"$/', '$1', Convert::xml2raw($rawHints) ?? ''); @@ -127,7 +134,7 @@ public function testChildFilter() * Test that getCMSFields works on each page type. * Mostly, this is just checking that the method doesn't return an error */ - public function testThatGetCMSFieldsWorksOnEveryPageType() + public function testThatGetCMSFieldsWorksOnEveryRecordType() { $classes = ClassInfo::subclassesFor(SiteTree::class); array_shift($classes); @@ -245,10 +252,10 @@ public function testCreationOfTopLevelPage() Security::setCurrentUser($cmsUser); $this->get('admin/pages/add'); $response = $this->post( - 'admin/pages/add/AddForm', + 'admin/pages/AddForm', [ 'ParentID' => '0', - 'PageType' => RedirectorPage::class, + 'RecordType' => RedirectorPage::class, 'Locale' => 'en_US', 'action_doAdd' => 1, 'ajax' => 1, @@ -265,10 +272,10 @@ public function testCreationOfTopLevelPage() $response = $this->get('admin/pages/add'); $response = $this->post( - 'admin/pages/add/AddForm', + 'admin/pages/AddForm', [ 'ParentID' => '0', - 'PageType' => RedirectorPage::class, + 'RecordType' => RedirectorPage::class, 'Locale' => 'en_US', 'action_doAdd' => 1, 'ajax' => 1, @@ -296,10 +303,10 @@ public function testCreationOfRestrictedPage() // Create toplevel page $this->get('admin/pages/add'); $response = $this->post( - 'admin/pages/add/AddForm', + 'admin/pages/AddForm', [ 'ParentID' => '0', - 'PageType' => CMSMainTest_ClassA::class, + 'RecordType' => CMSMainTest_ClassA::class, 'Locale' => 'en_US', 'action_doAdd' => 1, 'ajax' => 1, @@ -316,10 +323,10 @@ public function testCreationOfRestrictedPage() // Create allowed child $this->get('admin/pages/add'); $response = $this->post( - 'admin/pages/add/AddForm', + 'admin/pages/AddForm', [ 'ParentID' => $newPageId, - 'PageType' => CMSMainTest_ClassB::class, + 'RecordType' => CMSMainTest_ClassB::class, 'Locale' => 'en_US', 'action_doAdd' => 1, 'ajax' => 1, @@ -342,10 +349,10 @@ public function testCreationOfRestrictedPage() // Create disallowed child $this->get('admin/pages/add'); $response = $this->post( - 'admin/pages/add/AddForm', + 'admin/pages/AddForm', [ 'ParentID' => $newPageId, - 'PageType' => RedirectorPage::class, + 'RecordType' => RedirectorPage::class, 'Locale' => 'en_US', 'action_doAdd' => 1, 'ajax' => 1, @@ -669,13 +676,15 @@ public function testChangeClass() $this->assertEquals('Class A', $newPage->Title); } - public function testSiteTreeHintsCache() + public function testTreeHintsCache() { $cms = CMSMain::create(); + $reflectionAllowedSubclasses = new ReflectionMethod($cms, 'getAllowedSubClasses'); + $reflectionAllowedSubclasses->setAccessible(true); /** @var Member $user */ $user = $this->objFromFixture(Member::class, 'rootedituser'); Security::setCurrentUser($user); - $pageClass = array_values(SiteTree::page_type_classes())[0]; + $pageClass = array_values($reflectionAllowedSubclasses->invoke($cms))[0]; $mockPageMissesCache = $this->getMockBuilder($pageClass) ->onlyMethods(['canCreate']) ->getMock(); @@ -693,31 +702,31 @@ public function testSiteTreeHintsCache() // Initially, cache misses (1) Injector::inst()->registerService($mockPageMissesCache, $pageClass); - $hints = $cms->SiteTreeHints(); + $hints = $cms->TreeHints(); $this->assertNotNull($hints); // Now it hits Injector::inst()->registerService($mockPageHitsCache, $pageClass); - $hints = $cms->SiteTreeHints(); + $hints = $cms->TreeHints(); $this->assertNotNull($hints); // Mutating member record invalidates cache. Misses (2) $user->FirstName = 'changed'; $user->write(); Injector::inst()->registerService($mockPageMissesCache, $pageClass); - $hints = $cms->SiteTreeHints(); + $hints = $cms->TreeHints(); $this->assertNotNull($hints); // Now it hits again Injector::inst()->registerService($mockPageHitsCache, $pageClass); - $hints = $cms->SiteTreeHints(); + $hints = $cms->TreeHints(); $this->assertNotNull($hints); // Different user. Misses. (3) $user = $this->objFromFixture(Member::class, 'allcmssectionsuser'); Security::setCurrentUser($user); Injector::inst()->registerService($mockPageMissesCache, $pageClass); - $hints = $cms->SiteTreeHints(); + $hints = $cms->TreeHints(); $this->assertNotNull($hints); } @@ -761,21 +770,118 @@ public function testSearchField() ); } - public function testCanOrganiseSitetree() + public function testCanOrganiseTree() { $cms = CMSMain::create(); - $this->assertFalse($cms->CanOrganiseSitetree()); + $this->assertFalse($cms->CanOrganiseTree()); $this->logInWithPermission('CMS_ACCESS_CMSMain'); - $this->assertFalse($cms->CanOrganiseSitetree()); + $this->assertFalse($cms->CanOrganiseTree()); $this->logOut(); $this->logInWithPermission('SITETREE_REORGANISE'); - $this->assertTrue($cms->CanOrganiseSitetree()); + $this->assertTrue($cms->CanOrganiseTree()); $this->logOut(); $this->logInWithPermission('ADMIN'); - $this->assertTrue($cms->CanOrganiseSitetree()); + $this->assertTrue($cms->CanOrganiseTree()); + } + + public function testGetCreatableSubClassesCache() + { + // Use injector because CMSMain defines some injectable dependencies + $cms = CMSMain::create(); + $reflectionMethod = new ReflectionMethod($cms, 'getCreatableSubClasses'); + $reflectionMethod->setAccessible(true); + + $siteTree = new SiteTree(); + $user = $this->objFromFixture(Member::class, 'allcmssectionsuser'); + Security::setCurrentUser($user); + $classes = ClassInfo::getValidSubClasses(SiteTree::class); + SiteTree::singleton()->updateAllowedSubClasses($classes); + $pageClass = array_values($classes)[0]; + + $mockPageMissesCache = $this->getMockBuilder($pageClass) + ->onlyMethods(['canCreate']) + ->getMock(); + $mockPageMissesCache + ->expects($this->exactly(3)) + ->method('canCreate'); + + $mockPageHitsCache = $this->getMockBuilder($pageClass) + ->onlyMethods(['canCreate']) + ->getMock(); + $mockPageHitsCache + ->expects($this->never()) + ->method('canCreate'); + + // Initially, cache misses (1) + Injector::inst()->registerService($mockPageMissesCache, $pageClass); + $result = $reflectionMethod->invoke($cms, $siteTree); + $this->assertNotNull($result); + + // Now it hits + Injector::inst()->registerService($mockPageHitsCache, $pageClass); + $result = $reflectionMethod->invoke($cms, $siteTree); + $this->assertNotNull($result); + + + // Mutating member record invalidates cache. Misses (2) + $user->FirstName = 'changed'; + $user->write(); + Injector::inst()->registerService($mockPageMissesCache, $pageClass); + $result = $reflectionMethod->invoke($cms, $siteTree); + $this->assertNotNull($result); + + // Now it hits again + Injector::inst()->registerService($mockPageHitsCache, $pageClass); + $result = $reflectionMethod->invoke($cms, $siteTree); + $this->assertNotNull($result); + + // Different user. Misses. (3) + $user = $this->objFromFixture(Member::class, 'rootedituser'); + Security::setCurrentUser($user); + Injector::inst()->registerService($mockPageMissesCache, $pageClass); + $result = $reflectionMethod->invoke($cms, $siteTree); + $this->assertNotNull($result); + } + + public static function provideInit(): array + { + return [ + [ + 'class' => DataObject::class, + 'throwsException' => true, + ], + [ + 'class' => TestHierarchicalDataObject::class, + 'throwsException' => true, + ], + [ + 'class' => TestHierarchicalDataObjectWithSort::class, + 'throwsException' => false, + ], + [ + 'class' => SiteTree::class, + 'throwsException' => false, + ], + ]; + } + + #[DataProvider('provideInit')] + public function testInit(string $class, bool $throwsException): void + { + CMSMain::config()->set('model_class', $class); + // Use injector because CMSMain defines some injectable dependencies + $cms = CMSMain::create(); + $initReflection = new ReflectionMethod($cms, 'init'); + $initReflection->setAccessible(true); + if ($throwsException) { + $this->expectException(LogicException::class); + } else { + $this->expectNotToPerformAssertions(); + } + $initReflection->invoke($cms); } } diff --git a/tests/php/Controllers/CMSMainTest/TestHierarchicalDataObject.php b/tests/php/Controllers/CMSMainTest/TestHierarchicalDataObject.php new file mode 100644 index 0000000000..78ea216b6f --- /dev/null +++ b/tests/php/Controllers/CMSMainTest/TestHierarchicalDataObject.php @@ -0,0 +1,18 @@ + 'Int', + ]; + + private static array $extensions = [ + Hierarchy::class, + ]; +} diff --git a/tests/php/Controllers/CMSMainTest/TestHierarchicalDataObjectWithSort.php b/tests/php/Controllers/CMSMainTest/TestHierarchicalDataObjectWithSort.php new file mode 100644 index 0000000000..bc380c5545 --- /dev/null +++ b/tests/php/Controllers/CMSMainTest/TestHierarchicalDataObjectWithSort.php @@ -0,0 +1,20 @@ + 'Int', + ]; + + private static string $sort_field = 'Sort'; + + private static array $extensions = [ + Hierarchy::class, + ]; +} diff --git a/tests/php/Controllers/CMSSiteTreeFilterTest.php b/tests/php/Controllers/CMSSiteTreeFilterTest.php index bf2a925323..9eefb1ce1e 100644 --- a/tests/php/Controllers/CMSSiteTreeFilterTest.php +++ b/tests/php/Controllers/CMSSiteTreeFilterTest.php @@ -24,8 +24,8 @@ public function testSearchFilterEmpty() $f = new CMSSiteTreeFilter_Search(); $results = $f->pagesIncluded(); - $this->assertTrue($f->isPageIncluded($page1)); - $this->assertTrue($f->isPageIncluded($page2)); + $this->assertTrue($f->isRecordIncluded($page1)); + $this->assertTrue($f->isRecordIncluded($page2)); } public function testSearchFilterByTitle() @@ -36,8 +36,8 @@ public function testSearchFilterByTitle() $f = new CMSSiteTreeFilter_Search(['Title' => 'Page 1']); $results = $f->pagesIncluded(); - $this->assertTrue($f->isPageIncluded($page1)); - $this->assertFalse($f->isPageIncluded($page2)); + $this->assertTrue($f->isRecordIncluded($page1)); + $this->assertFalse($f->isRecordIncluded($page2)); $this->assertEquals(1, count($results ?? [])); $this->assertEquals( ['ID' => $page1->ID, 'ParentID' => 0], @@ -50,10 +50,10 @@ public function testUrlSegmentFilter() $page = $this->objFromFixture(SiteTree::class, 'page8'); $filter = CMSSiteTreeFilter_Search::create(['Term' => 'lake-wanaka+adventure']); - $this->assertTrue($filter->isPageIncluded($page)); + $this->assertTrue($filter->isRecordIncluded($page)); $filter = CMSSiteTreeFilter_Search::create(['URLSegment' => 'lake-wanaka+adventure']); - $this->assertTrue($filter->isPageIncluded($page)); + $this->assertTrue($filter->isRecordIncluded($page)); } public function testIncludesParentsForNestedMatches() @@ -64,8 +64,8 @@ public function testIncludesParentsForNestedMatches() $f = new CMSSiteTreeFilter_Search(['Title' => 'Page 3b']); $results = $f->pagesIncluded(); - $this->assertTrue($f->isPageIncluded($parent)); - $this->assertTrue($f->isPageIncluded($child)); + $this->assertTrue($f->isRecordIncluded($parent)); + $this->assertTrue($f->isRecordIncluded($child)); $this->assertEquals(1, count($results ?? [])); $this->assertEquals( ['ID' => $child->ID, 'ParentID' => $parent->ID], @@ -91,8 +91,8 @@ public function testChangedPagesFilter() $f = new CMSSiteTreeFilter_ChangedPages(['Term' => 'Changed']); $results = $f->pagesIncluded(); - $this->assertTrue($f->isPageIncluded($changedPage)); - $this->assertFalse($f->isPageIncluded($unchangedPage)); + $this->assertTrue($f->isRecordIncluded($changedPage)); + $this->assertFalse($f->isRecordIncluded($unchangedPage)); $this->assertEquals(1, count($results ?? [])); $this->assertEquals( ['ID' => $changedPage->ID, 'ParentID' => 0], @@ -130,11 +130,11 @@ public function testDeletedPagesFilter() ); $f = new CMSSiteTreeFilter_DeletedPages(['Term' => 'Page']); - $this->assertTrue($f->isPageIncluded($deletedPage)); + $this->assertTrue($f->isRecordIncluded($deletedPage)); // Check that only changed pages are returned $f = new CMSSiteTreeFilter_DeletedPages(['Term' => 'No Matches']); - $this->assertFalse($f->isPageIncluded($deletedPage)); + $this->assertFalse($f->isRecordIncluded($deletedPage)); } public function testStatusDraftPagesFilter() @@ -148,16 +148,16 @@ public function testStatusDraftPagesFilter() // Check draft page is shown $f = new CMSSiteTreeFilter_StatusDraftPages(['Term' => 'Page']); - $this->assertTrue($f->isPageIncluded($draftPage)); + $this->assertTrue($f->isRecordIncluded($draftPage)); // Check filter respects parameters $f = new CMSSiteTreeFilter_StatusDraftPages(['Term' => 'No Match']); - $this->assertEmpty($f->isPageIncluded($draftPage)); + $this->assertEmpty($f->isRecordIncluded($draftPage)); // Ensures empty array returned if no data to show $f = new CMSSiteTreeFilter_StatusDraftPages(); $draftPage->delete(); - $this->assertEmpty($f->isPageIncluded($draftPage)); + $this->assertEmpty($f->isRecordIncluded($draftPage)); } public function testDateFromToLastSameDate() @@ -171,7 +171,7 @@ public function testDateFromToLastSameDate() 'LastEditedTo' => $date, ]); $this->assertTrue( - $filter->isPageIncluded($draftPage), + $filter->isRecordIncluded($draftPage), 'Using the same date for from and to should show find that page' ); } @@ -189,16 +189,16 @@ public function testStatusRemovedFromDraftFilter() // Check live-only page is included $f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(['LastEditedFrom' => '2000-01-01 00:00']); - $this->assertTrue($f->isPageIncluded($removedDraftPage)); + $this->assertTrue($f->isRecordIncluded($removedDraftPage)); // Check filter is respected $f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(['LastEditedTo' => '1999-01-01 00:00']); - $this->assertEmpty($f->isPageIncluded($removedDraftPage)); + $this->assertEmpty($f->isRecordIncluded($removedDraftPage)); // Ensures empty array returned if no data to show $f = new CMSSiteTreeFilter_StatusRemovedFromDraftPages(); $removedDraftPage->delete(); - $this->assertEmpty($f->isPageIncluded($removedDraftPage)); + $this->assertEmpty($f->isRecordIncluded($removedDraftPage)); } public function testStatusDeletedFilter() @@ -214,10 +214,10 @@ public function testStatusDeletedFilter() // Check deleted page is included $f = new CMSSiteTreeFilter_StatusDeletedPages(['Title' => 'Page']); - $this->assertTrue($f->isPageIncluded($checkParentExists)); + $this->assertTrue($f->isRecordIncluded($checkParentExists)); // Check filter is respected $f = new CMSSiteTreeFilter_StatusDeletedPages(['Title' => 'Bobby']); - $this->assertFalse($f->isPageIncluded($checkParentExists)); + $this->assertFalse($f->isRecordIncluded($checkParentExists)); } } diff --git a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest.php b/tests/php/Controllers/LeftAndMainPageIconsExtensionTest.php deleted file mode 100644 index 4529a826d7..0000000000 --- a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest.php +++ /dev/null @@ -1,30 +0,0 @@ -generatePageIconsCss(); - $this->assertStringNotContainsString('some invalid string', $css); - $this->assertStringContainsString( - 'tests/php/Controllers/LeftAndMainPageIconsExtensionTest/icon_b.jpg?m=', - $css - ); - $this->assertStringContainsString( - 'tests/php/Controllers/LeftAndMainPageIconsExtensionTest/icon_c.jpg?m=', - $css - ); - } -} diff --git a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/ModuleIconB.php b/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/ModuleIconB.php deleted file mode 100644 index 147a044ea0..0000000000 --- a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/ModuleIconB.php +++ /dev/null @@ -1,11 +0,0 @@ -generateRecordIconsCss(); + $this->assertStringNotContainsString('some invalid string', $css); + $this->assertStringContainsString( + 'tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_b.jpg?m=', + $css + ); + $this->assertStringContainsString( + 'tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_c.jpg?m=', + $css + ); + $this->assertStringNotContainsString( + 'tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_d.jpg?m=', + $css + ); + } +} diff --git a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/ModuleIconA.php b/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/ModuleIconA.php similarity index 50% rename from tests/php/Controllers/LeftAndMainPageIconsExtensionTest/ModuleIconA.php rename to tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/ModuleIconA.php index 3b503a34bf..5c1d907104 100644 --- a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/ModuleIconA.php +++ b/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/ModuleIconA.php @@ -1,11 +1,11 @@ $path, + 'cms_icon' => $path, ]; } } diff --git a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/icon_b.jpg b/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_b.jpg similarity index 100% rename from tests/php/Controllers/LeftAndMainPageIconsExtensionTest/icon_b.jpg rename to tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_b.jpg diff --git a/tests/php/Controllers/LeftAndMainPageIconsExtensionTest/icon_c.jpg b/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_c.jpg similarity index 100% rename from tests/php/Controllers/LeftAndMainPageIconsExtensionTest/icon_c.jpg rename to tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_c.jpg diff --git a/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_d.jpg b/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_d.jpg new file mode 100644 index 0000000000..beb5a91b0a Binary files /dev/null and b/tests/php/Controllers/LeftAndMainRecordIconsExtensionTest/icon_d.jpg differ diff --git a/tests/php/Model/SiteTreePermissionsTest.php b/tests/php/Model/SiteTreePermissionsTest.php index ad7c17850c..02a8df272b 100644 --- a/tests/php/Model/SiteTreePermissionsTest.php +++ b/tests/php/Model/SiteTreePermissionsTest.php @@ -96,7 +96,7 @@ public function testPermissionCheckingWorksOnDeletedPages() // Test can_edit_multiple $this->assertEquals( [ $pageID => true ], - SiteTree::getPermissionChecker()->canEditMultiple([$pageID], $member) + $page->getPermissionChecker()->canEditMultiple([$pageID], $member) ); // Test canEdit @@ -119,7 +119,7 @@ public function testPermissionCheckingWorksOnUnpublishedPages() // Test can_edit_multiple $this->assertEquals( [ $pageID => true ], - SiteTree::getPermissionChecker()->canEditMultiple([$pageID], $member) + $page->getPermissionChecker()->canEditMultiple([$pageID], $member) ); // Test canEdit diff --git a/tests/php/Model/SiteTreeTest.php b/tests/php/Model/SiteTreeTest.php index 1de289eee4..2e5c894e5b 100644 --- a/tests/php/Model/SiteTreeTest.php +++ b/tests/php/Model/SiteTreeTest.php @@ -43,6 +43,7 @@ use const RESOURCES_DIR; use PHPUnit\Framework\Attributes\DataProvider; +use SilverStripe\Core\ClassInfo; class SiteTreeTest extends SapphireTest { @@ -64,7 +65,6 @@ class SiteTreeTest extends SapphireTest SiteTreeTest_ClassC::class, SiteTreeTest_ClassD::class, SiteTreeTest_NotRoot::class, - SiteTreeTest_StageStatusInherit::class, SiteTreeTest_DataObject::class, PageWithChild::class, BelongsToPage::class, @@ -445,7 +445,7 @@ public function testRestoreToStage() public function testNoCascadingDeleteWithoutID() { - Config::inst()->set('SiteTree', 'enforce_strict_hierarchy', true); + SiteTree::config()->set('enforce_strict_hierarchy', true); $count = SiteTree::get()->count(); $this->assertNotEmpty($count); $obj = new SiteTree(); @@ -806,7 +806,7 @@ public function testEditPermissionsOnDraftVsLive() // Clear permission cache /** @var InheritedPermissions $checker */ - $checker = SiteTree::getPermissionChecker(); + $checker = SiteTree::singleton()->getPermissionChecker(); $checker->clearCache(); // Confirm that Member.editor can now edit the page @@ -1182,19 +1182,22 @@ public function testVersionsAreCreated() public function testHidePagetypes() { SiteTree::config()->set('hide_pagetypes', ['Page']); - $classes = SiteTree::page_type_classes(); + $classes = ClassInfo::getValidSubClasses(SiteTree::class); + SiteTree::singleton()->updateAllowedSubClasses($classes); $this->assertNotContains('Page', $classes); } public function testPageTypeClasses() { - $classes = SiteTree::page_type_classes(); + $classes = ClassInfo::getValidSubClasses(SiteTree::class); + SiteTree::singleton()->updateAllowedSubClasses($classes); $this->assertNotContains(SiteTree::class, $classes, 'Page types do not include base class'); $this->assertContains('Page', $classes, 'Page types do contain subclasses'); // Testing what happens in an incorrect config value is set - hide_ancestor should be a string Config::modify()->set(SiteTreeTest_ClassA::class, 'hide_ancestor', true); - $newClasses = SiteTree::page_type_classes(); + $newClasses = ClassInfo::getValidSubClasses(SiteTree::class); + SiteTree::singleton()->updateAllowedSubClasses($newClasses); $this->assertEquals( $classes, $newClasses, @@ -1203,7 +1206,8 @@ public function testPageTypeClasses() // Testing what happens if a valid config value is set Config::modify()->set(SiteTreeTest_ClassA::class, 'hide_ancestor', 'Page'); - $classes = SiteTree::page_type_classes(); + $classes = ClassInfo::getValidSubClasses(SiteTree::class); + SiteTree::singleton()->updateAllowedSubClasses($classes); $this->assertNotContains('Page', $classes); } @@ -1289,14 +1293,6 @@ public function testCanBeRoot() } } - public function testModifyStatusFlagByInheritance() - { - $node = new SiteTreeTest_StageStatusInherit(); - $treeTitle = $node->getTreeTitle(); - $this->assertStringContainsString('InheritedTitle', $treeTitle); - $this->assertStringContainsString('inherited-class', $treeTitle); - } - public function testMenuTitleIsUnsetWhenEqualsTitle() { $page = new SiteTree(); @@ -1622,7 +1618,7 @@ public function testGetControllerName() */ public function testGetControllerNameFromConfig() { - Config::inst()->set(SiteTree::class, 'controller_name', 'This\\Is\\A\\New\\Controller'); + SiteTree::config()->set('controller_name', 'This\\Is\\A\\New\\Controller'); $page = new SiteTree(); $this->assertSame('This\\Is\\A\\New\\Controller', $page->getControllerName()); } @@ -1632,7 +1628,7 @@ public function testGetControllerNameFromConfig() */ public function testGetControllerNameFromNamespaceMappingConfig() { - Config::inst()->merge(SiteTree::class, 'namespace_mapping', [ + SiteTree::config()->merge('namespace_mapping', [ 'SilverStripe\\CMS\\Tests\\Page' => 'SilverStripe\\CMS\\Tests\\Controllers', ]); @@ -1640,58 +1636,6 @@ public function testGetControllerNameFromNamespaceMappingConfig() $this->assertSame(SiteTreeTest_NamespaceMapTestNodeController::class, $namespacedSiteTree->getControllerName()); } - public function testTreeTitleCache() - { - $siteTree = new SiteTree(); - $user = $this->objFromFixture(Member::class, 'allsections'); - Security::setCurrentUser($user); - $pageClass = array_values(SiteTree::page_type_classes())[0]; - - $mockPageMissesCache = $this->getMockBuilder($pageClass) - ->onlyMethods(['canCreate']) - ->getMock(); - $mockPageMissesCache - ->expects($this->exactly(3)) - ->method('canCreate'); - - $mockPageHitsCache = $this->getMockBuilder($pageClass) - ->onlyMethods(['canCreate']) - ->getMock(); - $mockPageHitsCache - ->expects($this->never()) - ->method('canCreate'); - - // Initially, cache misses (1) - Injector::inst()->registerService($mockPageMissesCache, $pageClass); - $title = $siteTree->getTreeTitle(); - $this->assertNotNull($title); - - // Now it hits - Injector::inst()->registerService($mockPageHitsCache, $pageClass); - $title = $siteTree->getTreeTitle(); - $this->assertNotNull($title); - - - // Mutating member record invalidates cache. Misses (2) - $user->FirstName = 'changed'; - $user->write(); - Injector::inst()->registerService($mockPageMissesCache, $pageClass); - $title = $siteTree->getTreeTitle(); - $this->assertNotNull($title); - - // Now it hits again - Injector::inst()->registerService($mockPageHitsCache, $pageClass); - $title = $siteTree->getTreeTitle(); - $this->assertNotNull($title); - - // Different user. Misses. (3) - $user = $this->objFromFixture(Member::class, 'editor'); - Security::setCurrentUser($user); - Injector::inst()->registerService($mockPageMissesCache, $pageClass); - $title = $siteTree->getTreeTitle(); - $this->assertNotNull($title); - } - public function testDependentPagesOnUnsavedRecord() { $record = new SiteTree(); diff --git a/tests/php/Model/SiteTreeTest_ClassA.php b/tests/php/Model/SiteTreeTest_ClassA.php index 7cf2020f4d..bf878c9676 100644 --- a/tests/php/Model/SiteTreeTest_ClassA.php +++ b/tests/php/Model/SiteTreeTest_ClassA.php @@ -9,11 +9,6 @@ class SiteTreeTest_ClassA extends SiteTree implements TestOnly { private static $table_name = 'SiteTreeTest_ClassA'; - private static $need_permission = [ - 'ADMIN', - 'CMS_ACCESS_CMSMain', - ]; - private static $allowed_children = [ SiteTreeTest_ClassB::class, ]; diff --git a/tests/php/Model/SiteTreeTest_StageStatusInherit.php b/tests/php/Model/SiteTreeTest_StageStatusInherit.php deleted file mode 100644 index 690c748629..0000000000 --- a/tests/php/Model/SiteTreeTest_StageStatusInherit.php +++ /dev/null @@ -1,18 +0,0 @@ -