diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 38a88b263..66899d64b 100644 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -5,10 +5,23 @@ jQuery.noConflict(); */ (function($) { - window.onresize = function(e) { + var windowWidth, windowHeight; + $(window).bind('resize.leftandmain', function(e) { // Entwine's 'fromWindow::onresize' does not trigger on IE8. Use synthetic event. - $('.cms-container').trigger('windowresize'); - }; + var cb = function() {$('.cms-container').trigger('windowresize');}; + + // Workaround to avoid IE8 infinite loops when elements are resized as a result of this event + if($.browser.msie && parseInt($.browser.version, 10) < 9) { + var newWindowWidth = $(window).width(), newWindowHeight = $(window).height(); + if(newWindowWidth != windowWidth || newWindowHeight != windowHeight) { + windowWidth = newWindowWidth; + windowHeight = newWindowHeight; + cb(); + } + } else { + cb(); + } + }); // setup jquery.entwine $.entwine.warningLevel = $.entwine.WARN_LEVEL_BESTPRACTISE; @@ -136,7 +149,7 @@ jQuery.noConflict(); this._super(); return; } - + // Initialize layouts this.redraw(); @@ -228,15 +241,15 @@ jQuery.noConflict(); }, this.getLayoutOptions() )); - + // Trigger layout algorithm once at the top. This also lays out children - we move from outside to // inside, resizing to fit the parent. this.layout(); // Redraw on all the children that need it - this.find('.cms-panel-layout').redraw(); - this.find('.cms-content-fields[data-layout-type]').redraw(); - this.find('.cms-edit-form[data-layout-type]').redraw(); + this.find('.cms-panel-layout').redraw(); + this.find('.cms-content-fields[data-layout-type]').redraw(); + this.find('.cms-edit-form[data-layout-type]').redraw(); this.find('.cms-preview').redraw(); this.find('.cms-content').redraw(); }, @@ -590,7 +603,7 @@ jQuery.noConflict(); if(typeof(window.sessionStorage)=="undefined" || window.sessionStorage === null) return; var selectedTabs = [], url = this._tabStateUrl(); - this.find('.cms-tabset,.ss-tabset').each(function(i, el) { + this.find('.cms-tabset,.ss-tabset').each(function(i, el) { var id = $(el).attr('id'); if(!id) return; // we need a unique reference if(!$(el).data('tabs')) return; // don't act on uninit'ed controls @@ -650,8 +663,8 @@ jQuery.noConflict(); } else if(sessionStates) { $.each(sessionStates, function(i, sessionState) { if(tabset.is('#' + sessionState.id)) index = sessionState.selected; - }); - } + }); + } if(index !== null) tabset.tabs('select', index); }); }, @@ -671,7 +684,7 @@ jQuery.noConflict(); } else { for(var i=0;i Real men don't eat quiche - <% else_if $MyDinner=$YourDinner %> + <% else_if $MyDinner==$YourDinner %> We both have good taste <% else %> Can I have some of your chips? diff --git a/docs/en/topics/testing/index.md b/docs/en/topics/testing/index.md index ec29bb2ca..9f2053d4b 100644 --- a/docs/en/topics/testing/index.md +++ b/docs/en/topics/testing/index.md @@ -56,16 +56,16 @@ The `phpunit` binary should be used from the root directory of your website. # Runs all tests defined in phpunit.xml phpunit - + # Run all tests of a specific module phpunit framework/tests/ - + # Run specific tests within a specific module phpunit framework/tests/filesystem - + # Run a specific test phpunit framework/tests/filesystem/FolderTest.php - + # Run tests with optional `$_GET` parameters (you need an empty second argument) phpunit framework/tests '' flush=all @@ -81,16 +81,16 @@ particularly around formatting test output. # Run all tests sake dev/tests/all - + # Run all tests of a specific module (comma-separated) sake dev/tests/module/framework,cms - + # Run specific tests (comma-separated) sake dev/tests/FolderTest,OtherTest - + # Run tests with optional `$_GET` parameters sake dev/tests/all flush=all - + # Skip some tests sake dev/tests/all SkipTests=MySkippedTest @@ -187,4 +187,4 @@ understand the problem space and discover suitable APIs for performing specific **Behavior Driven Development (BDD):** An extension of the test-driven programming style, where tests are used primarily for describing the specification of how code should perform. In practice, there's little or no technical difference - it all comes down to language. In BDD, the usual terminology is changed to reflect this change of focus, so *Specification* -is used in place of *Test Case*, and *should* is used in place of *expect* and *assert*. \ No newline at end of file +is used in place of *Test Case*, and *should* is used in place of *expect* and *assert*. diff --git a/javascript/TreeDropdownField.js b/javascript/TreeDropdownField.js index d58313d72..1b46d96c6 100644 --- a/javascript/TreeDropdownField.js +++ b/javascript/TreeDropdownField.js @@ -4,8 +4,22 @@ * On resize of any close the open treedropdownfields * as we'll need to redo with widths */ - $(window).resize(function() { - $('.TreeDropdownField').closePanel(); + var windowWidth, windowHeight; + $(window).bind('resize.treedropdownfield', function() { + // Entwine's 'fromWindow::onresize' does not trigger on IE8. Use synthetic event. + var cb = function() {$('.TreeDropdownField').closePanel();}; + + // Workaround to avoid IE8 infinite loops when elements are resized as a result of this event + if($.browser.msie && parseInt($.browser.version, 10) < 9) { + var newWindowWidth = $(window).width(), newWindowHeight = $(window).height(); + if(newWindowWidth != windowWidth || newWindowHeight != windowHeight) { + windowWidth = newWindowWidth; + windowHeight = newWindowHeight; + cb(); + } + } else { + cb(); + } }); var strings = { diff --git a/tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsUiContext.php b/tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsUiContext.php index 55e738cc7..6c528cf9d 100644 --- a/tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsUiContext.php +++ b/tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsUiContext.php @@ -363,13 +363,13 @@ class CmsUiContext extends BehatContext } assertNotNull($container, 'Chosen.js field container not found'); - + // Click on newly expanded list element, indirectly setting the dropdown value $linkEl = $container->find('xpath', './/a[./@href]'); assertNotNull($linkEl, 'Chosen.js link element not found'); $this->getSession()->wait(100); // wait for dropdown overlay to appear $linkEl->click(); - + if(in_array('treedropdown', explode(' ', $container->getAttribute('class')))) { // wait for ajax dropdown to load $this->getSession()->wait( @@ -422,7 +422,7 @@ class CmsUiContext extends BehatContext ) { if($container->isVisible() && in_array($class, explode(' ', $container->getAttribute('class')))) { return $container; - } +} $container = $container->getParent(); } diff --git a/tests/control/ControllerTest.php b/tests/control/ControllerTest.php index 40bc0ad0c..1666750ec 100644 --- a/tests/control/ControllerTest.php +++ b/tests/control/ControllerTest.php @@ -5,7 +5,7 @@ class ControllerTest extends FunctionalTest { protected static $fixture_file = 'ControllerTest.yml'; protected $autoFollowRedirection = false; - + protected $requiredExtensions = array( 'ControllerTest_AccessBaseController' => array( 'ControllerTest_AccessBaseControllerExtension' @@ -44,7 +44,7 @@ class ControllerTest extends FunctionalTest { public function testAllowedActions() { $adminUser = $this->objFromFixture('Member', 'admin'); - + $response = $this->get("ControllerTest_UnsecuredController/"); $this->assertEquals(200, $response->getStatusCode(), 'Access granted on index action without $allowed_actions on defining controller, ' . @@ -62,7 +62,7 @@ class ControllerTest extends FunctionalTest { 'Access granted on action without $allowed_actions on defining controller, ' . 'when called without an action in the URL' ); - + $response = $this->get("ControllerTest_AccessBaseController/"); $this->assertEquals(200, $response->getStatusCode(), 'Access granted on index with empty $allowed_actions on defining controller, ' . @@ -110,6 +110,12 @@ class ControllerTest extends FunctionalTest { 'if action is not a method but rather a template discovered by naming convention' ); + $response = $this->get("ControllerTest_AccessSecuredController/templateaction"); + $this->assertEquals(403, $response->getStatusCode(), + 'Access denied on action with $allowed_actions on defining controller, ' . + 'if action is not a method but rather a template discovered by naming convention' + ); + $this->session()->inst_set('loggedInAs', $adminUser->ID); $response = $this->get("ControllerTest_AccessSecuredController/templateaction"); $this->assertEquals(200, $response->getStatusCode(), @@ -147,25 +153,25 @@ class ControllerTest extends FunctionalTest { "Access granted to method defined in allowed_actions on extension, " . "where method is also defined on extension" ); - + $response = $this->get('ControllerTest_AccessSecuredController/extensionmethod1'); $this->assertEquals(200, $response->getStatusCode(), "Access granted to method defined in allowed_actions on extension, " . "where method is also defined on extension, even when called in a subclass" ); - + $response = $this->get('ControllerTest_AccessBaseController/extensionmethod2'); - $this->assertEquals(404, $response->getStatusCode(), + $this->assertEquals(404, $response->getStatusCode(), "Access denied to method not defined in allowed_actions on extension, " . "where method is also defined on extension" ); - + $response = $this->get('ControllerTest_IndexSecuredController/'); $this->assertEquals(403, $response->getStatusCode(), "Access denied when index action is limited through allowed_actions, " . "and doesn't satisfy checks, and action is empty" ); - + $response = $this->get('ControllerTest_IndexSecuredController/index'); $this->assertEquals(403, $response->getStatusCode(), "Access denied when index action is limited through allowed_actions, " . @@ -174,13 +180,13 @@ class ControllerTest extends FunctionalTest { $this->session()->inst_set('loggedInAs', $adminUser->ID); $response = $this->get('ControllerTest_IndexSecuredController/'); - $this->assertEquals(200, $response->getStatusCode(), + $this->assertEquals(200, $response->getStatusCode(), "Access granted when index action is limited through allowed_actions, " . "and does satisfy checks" ); $this->session()->inst_set('loggedInAs', null); } - + /** * @expectedException PHPUnit_Framework_Error * @expectedExceptionMessage Wildcards (*) are no longer valid @@ -358,7 +364,7 @@ class ControllerTest extends FunctionalTest { class ControllerTest_Controller extends Controller implements TestOnly { public $Content = "default content"; - + private static $allowed_actions = array( 'methodaction', 'stringaction', @@ -385,13 +391,13 @@ class ControllerTest_UnsecuredController extends Controller implements TestOnly // Not defined, allow access to all // static $allowed_actions = array(); - + // Granted for all public function method1() {} // Granted for all public function method2() {} -} + } class ControllerTest_AccessBaseController extends Controller implements TestOnly { @@ -402,7 +408,7 @@ class ControllerTest_AccessBaseController extends Controller implements TestOnly // Denied for all public function method2() {} -} + } class ControllerTest_AccessSecuredController extends ControllerTest_AccessBaseController implements TestOnly { @@ -414,7 +420,7 @@ class ControllerTest_AccessSecuredController extends ControllerTest_AccessBaseCo ); public function method2() {} - + public function adminonly() {} protected function protectedmethod() {} @@ -427,18 +433,18 @@ class ControllerTest_AccessWildcardSecuredController extends ControllerTest_Acce "*" => "ADMIN", // should throw exception ); -} - + } + class ControllerTest_IndexSecuredController extends ControllerTest_AccessBaseController implements TestOnly { private static $allowed_actions = array( "index" => "ADMIN", ); -} + } class ControllerTest_AccessBaseControllerExtension extends Extension implements TestOnly { - + private static $allowed_actions = array( "extensionmethod1" => true, // granted because defined on this class "method1" => true, // ignored because method not defined on this class @@ -457,7 +463,7 @@ class ControllerTest_AccessBaseControllerExtension extends Extension implements public function internalextensionmethod() {} -} + } class ControllerTest_HasAction extends Controller {