Browse Source

More tests

euromark 11 years ago
parent
commit
b96d3b771d

+ 8 - 3
docs/Component/Flash.md

@@ -6,7 +6,8 @@ An enhanced FlashComponent capable of
 - Inject it into the headers as `X-Ajax-Flashmessage` for REST/AJAX requests
 
 ## Configs
-
+- 'headerKey' => 'X-Flash', // Set to empty string to deactivate
+- 'sessionLimit' => 99 // Max message limit for session to avoid session flooding (Configure doesn't need one)
 
 ## Usage
 Attach it to your controllers in `initialize()` like so:
@@ -21,7 +22,7 @@ public $helpers = array('Tools.Flash');
 
 In your layouts, you don't need to change the `$this->Flash->render()` call, as the syntax for this helper is the same.
 
-## Basic Example
+### Basic Example
 ```php
 // Inside an action
 $this->Flash->message('Yeah it works.', 'success');
@@ -29,10 +30,14 @@ $this->Flash->message('Careful.', 'warning');
 $this->Flash->message('O o.', 'error');
 ```
 
-## You can also use the new syntactic sugar:
+### You can also use the new syntactic sugar:
 ```php
 // Inside an action
 $this->Flash->success('Yeah it works.');
 $this->Flash->warning('Careful.');
 $this->Flash->error('O o.');
 ```
+
+## Notes
+You can use any type (success, warning, error, info, ...) of message, except the two reserved ones `message` and `set`.
+At least if you plan on using the magic method invokation. But even if not, it would be good practice to not use those two.

+ 62 - 23
src/Controller/Component/FlashComponent.php

@@ -4,6 +4,7 @@ namespace Tools\Controller\Component;
 use Cake\Controller\Component;
 use Cake\Core\Configure;
 use Cake\Event\Event;
+use Cake\Utility\Inflector;
 
 /**
  * A flash component to enhance flash message support with stackable messages, both
@@ -15,6 +16,14 @@ use Cake\Event\Event;
  */
 class FlashComponent extends Component {
 
+	/**
+	 * @var array
+	 */
+	protected $_defaultConfig = [
+		'headerKey' => 'X-Flash', // Set to empty string to deactivate
+		'sessionLimit' => 99 // Max message limit for session (Configure doesn't need one)
+	];
+
 	public function beforeFilter(Event $event) {
 		$this->Controller = $event->subject();
 	}
@@ -27,23 +36,21 @@ class FlashComponent extends Component {
 	 * @return void
 	 */
 	public function beforeRender(Event $event) {
-		if ($messages = $this->Controller->request->session()->read('Message')) {
-			foreach ($messages as $message) {
-				$this->flashMessage($message['message'], 'error');
-			}
-			$this->Controller->request->session()->delete('Message');
+		if (!$this->Controller->request->is('ajax')) {
+			return;
 		}
 
-		if ($this->Controller->request->is('ajax')) {
-			$ajaxMessages = array_merge(
-				(array)$this->Controller->request->session()->read('messages'),
-				(array)Configure::read('messages')
-			);
-			// The header can be read with JavaScript and a custom Message can be displayed
-			$this->Controller->response->header('X-Ajax-Flashmessage', json_encode($ajaxMessages));
-
-			$this->Controller->request->session()->delete('messages');
+		$headerKey = $this->config('headerKey');
+		if (!$headerKey) {
+			return;
 		}
+
+		$ajaxMessages = array_merge(
+			(array)$this->Controller->request->session()->consume('FlashMessage'),
+			(array)Configure::consume('FlashMessage')
+		);
+		// The header can be read with JavaScript and a custom Message can be displayed
+		$this->Controller->response->header($headerKey, json_encode($ajaxMessages));
 	}
 
 	/**
@@ -54,17 +61,24 @@ class FlashComponent extends Component {
 	 * @param string $type Type ('error', 'warning', 'success', 'info' or custom class).
 	 * @return void
 	 */
-	public function message($message, $type = null) {
-		if (!$type) {
-			$type = 'info';
+	public function message($message, $options = null) {
+		if (!is_array($options)) {
+			$type = $options;
+			if (!$type) {
+				$type = 'info';
+			}
+			$options = array();
+		} else {
+			$options += ['element' => 'info'];
+			$type = $options['element'];
 		}
 
-		$old = (array)$this->Controller->request->session()->read('messages');
-		if (isset($old[$type]) && count($old[$type]) > 99) {
+		$old = (array)$this->Controller->request->session()->read('FlashMessage');
+		if (isset($old[$type]) && count($old[$type]) > $this->config('sessionLimit')) {
 			array_shift($old[$type]);
 		}
 		$old[$type][] = $message;
-		$this->Controller->request->session()->write('messages', $old);
+		$this->Controller->request->session()->write('FlashMessage', $old);
 	}
 
 	/**
@@ -77,7 +91,7 @@ class FlashComponent extends Component {
 	 */
 	public function set($message, array $config = []) {
 		// For now we only use the element name
-		$defaults = ['element' => 'default'];
+		$defaults = ['element' => 'info'];
 		$config += $defaults;
 		$this->message($message, $config['element']);
 	}
@@ -96,12 +110,37 @@ class FlashComponent extends Component {
 			$type = 'info';
 		}
 
-		$old = (array)Configure::read('messages');
+		$old = (array)Configure::read('FlashMessage');
 		if (isset($old[$type]) && count($old[$type]) > 99) {
 			array_shift($old[$type]);
 		}
 		$old[$type][] = $message;
-		Configure::write('messages', $old);
+		Configure::write('FlashMessage', $old);
+	}
+
+/**
+ * Magic method for verbose flash methods based on element names.
+ *
+ * For example: $this->Flash->success('My message') would use the
+ * success.ctp element under `App/Template/Element/Flash` for rendering the
+ * flash message.
+ *
+ * @param string $name Element name to use.
+ * @param array $args Parameters to pass when calling `FlashComponent::set()`.
+ * @return void
+ * @throws \Cake\Network\Exception\InternalErrorException If missing the flash message.
+ */
+	public function __call($name, $args) {
+		$options = ['element' => Inflector::underscore($name)];
+
+		if (count($args) < 1) {
+			throw new InternalErrorException('Flash message missing.');
+		}
+
+		if (!empty($args[1])) {
+			$options += (array)$args[1];
+		}
+		$this->message($args[0], $options);
 	}
 
 }

+ 59 - 7
tests/TestCase/Controller/Component/FlashComponentTest.php

@@ -3,13 +3,13 @@ namespace Tools\Test\TestCase\Controller\Component;
 
 use Cake\Controller\ComponentRegistry;
 use Cake\Controller\Component;
-use Cake\Controller\Component\FlashComponent;
 use Cake\Controller\Controller;
 use Cake\Core\Configure;
 use Cake\Network\Request;
 use Cake\Network\Session;
 use Cake\Routing\DispatcherFactory;
 use Cake\TestSuite\TestCase;
+use Cake\Event\Event;
 
 /**
  */
@@ -24,6 +24,8 @@ class FlashComponentTest extends TestCase {
 
 		$this->Controller = new FlashComponentTestController();
 		$this->Controller->startupProcess();
+
+		$this->Controller->request->session()->delete('FlashMessage');
 	}
 
 	public function tearDown() {
@@ -40,10 +42,8 @@ class FlashComponentTest extends TestCase {
 	 */
 	public function testTransientMessage() {
 		$is = $this->Controller->Flash->transientMessage('xyz', 'success');
-		//$this->assertTrue($is);
 
-		$res = Configure::read('messages');
-		//debug($res);
+		$res = Configure::read('FlashMessage');
 		$this->assertTrue(!empty($res));
 		$this->assertTrue(isset($res['success'][0]) && $res['success'][0] === 'xyz');
 	}
@@ -54,12 +54,64 @@ class FlashComponentTest extends TestCase {
 	 * @return void
 	 */
 	public function testMessage() {
-		$this->Controller->request->session()->delete('messages');
 		$is = $this->Controller->Flash->message('efg');
 
-		$res = $this->Controller->request->session()->read('messages');
+		$res = $this->Controller->request->session()->read('FlashMessage');
+		$this->assertTrue(!empty($res));
+		$this->assertTrue(isset($res['info'][0]));
+		$this->assertSame('efg', $res['info'][0]);
+	}
+
+	/**
+	 * FlashComponentTest::testMagic()
+	 *
+	 * @return void
+	 */
+	public function testMagic() {
+		$is = $this->Controller->Flash->error('Some Error Message');
+
+		$res = $this->Controller->request->session()->read('FlashMessage');
 		$this->assertTrue(!empty($res));
-		$this->assertTrue(isset($res['info'][0]) && $res['info'][0] === 'efg');
+		$this->assertTrue(isset($res['error'][0]));
+		$this->assertSame('Some Error Message', $res['error'][0]);
+	}
+
+	/**
+	 * FlashComponentTest::testCoreHook()
+	 *
+	 * @return void
+	 */
+	public function testCoreHook() {
+		$is = $this->Controller->Flash->set('Some Message');
+
+		$res = $this->Controller->request->session()->read('FlashMessage');
+		$this->assertTrue(!empty($res));
+		$this->assertTrue(isset($res['info'][0]));
+		$this->assertSame('Some Message', $res['info'][0]);
+	}
+
+	/**
+	 * FlashComponentTest::testAjax()
+	 *
+	 * @return void
+	 */
+	public function testAjax() {
+		$this->Controller->request = $this->getMock('Cake\Network\Request', ['is']);
+		$this->Controller->Flash->success('yeah');
+		$this->Controller->Flash->transientMessage('xyz', 'warning');
+
+		$this->Controller->request->expects($this->once())
+			->method('is')
+			->with('ajax')
+			->will($this->returnValue(true));
+
+		$event = new Event('Controller.startup', $this->Controller);
+		$this->Controller->Flash->beforeFilter($event);
+		$this->Controller->Flash->beforeRender($event);
+
+		$result = $this->Controller->response->header();
+		$expected = ['X-Flash' => '{"success":["yeah"],"warning":["xyz"]}'];
+		$this->assertSame($expected, $result);
 	}
 
 }