a tiny mvc framework for php using php-activerecord
at v1 282 lines 9.6 kB view raw
1<?php 2include 'helpers/config.php'; 3 4class CallBackTest extends DatabaseTest 5{ 6 public function set_up($connection_name=null) 7 { 8 parent::set_up($connection_name); 9 10 // ensure VenueCB model has been loaded 11 VenueCB::find(1); 12 13 $this->callback = new ActiveRecord\CallBack('VenueCB'); 14 } 15 16 public function assert_has_callback($callback_name, $method_name=null) 17 { 18 if (!$method_name) 19 $method_name = $callback_name; 20 21 $this->assert_true(in_array($method_name,$this->callback->get_callbacks($callback_name))); 22 } 23 24 public function assert_implicit_save($first_method, $second_method) 25 { 26 $i_ran = array(); 27 $this->callback->register($first_method,function($model) use (&$i_ran, $first_method) { $i_ran[] = $first_method; }); 28 $this->callback->register($second_method,function($model) use (&$i_ran, $second_method) { $i_ran[] = $second_method; }); 29 $this->callback->invoke(null,$second_method); 30 $this->assert_equals(array($first_method,$second_method),$i_ran); 31 } 32 33 public function test_generic_callback_was_auto_registered() 34 { 35 $this->assert_has_callback('after_construct'); 36 } 37 38 public function test_register() 39 { 40 $this->callback->register('after_construct'); 41 $this->assert_has_callback('after_construct'); 42 } 43 44 public function test_register_non_generic() 45 { 46 $this->callback->register('after_construct','non_generic_after_construct'); 47 $this->assert_has_callback('after_construct','non_generic_after_construct'); 48 } 49 50 /** 51 * @expectedException ActiveRecord\ActiveRecordException 52 */ 53 public function test_register_invalid_callback() 54 { 55 $this->callback->register('invalid_callback'); 56 } 57 58 /** 59 * @expectedException ActiveRecord\ActiveRecordException 60 */ 61 public function test_register_callback_with_undefined_method() 62 { 63 $this->callback->register('after_construct','do_not_define_me'); 64 } 65 66 public function test_register_with_string_definition() 67 { 68 $this->callback->register('after_construct','after_construct'); 69 $this->assert_has_callback('after_construct'); 70 } 71 72 public function test_register_with_closure() 73 { 74 $this->callback->register('after_construct',function($mode) { }); 75 } 76 77 public function test_register_with_null_definition() 78 { 79 $this->callback->register('after_construct',null); 80 $this->assert_has_callback('after_construct'); 81 } 82 83 public function test_register_with_no_definition() 84 { 85 $this->callback->register('after_construct'); 86 $this->assert_has_callback('after_construct'); 87 } 88 89 public function test_register_appends_to_registry() 90 { 91 $this->callback->register('after_construct'); 92 $this->callback->register('after_construct','non_generic_after_construct'); 93 $this->assert_equals(array('after_construct','after_construct','non_generic_after_construct'),$this->callback->get_callbacks('after_construct')); 94 } 95 96 public function test_register_prepends_to_registry() 97 { 98 $this->callback->register('after_construct'); 99 $this->callback->register('after_construct','non_generic_after_construct',array('prepend' => true)); 100 $this->assert_equals(array('non_generic_after_construct','after_construct','after_construct'),$this->callback->get_callbacks('after_construct')); 101 } 102 103 public function test_registers_via_static_array_definition() 104 { 105 $this->assert_has_callback('after_destroy','after_destroy_one'); 106 $this->assert_has_callback('after_destroy','after_destroy_two'); 107 } 108 109 public function test_registers_via_static_string_definition() 110 { 111 $this->assert_has_callback('before_destroy','before_destroy_using_string'); 112 } 113 114 /** 115 * @expectedException ActiveRecord\ActiveRecordException 116 */ 117 public function test_register_via_static_with_invalid_definition() 118 { 119 $class_name = "Venues_" . md5(uniqid()); 120 eval("class $class_name extends ActiveRecord\\Model { static \$table_name = 'venues'; static \$after_save = 'method_that_does_not_exist'; };"); 121 new $class_name(); 122 new ActiveRecord\CallBack($class_name); 123 } 124 125 public function test_can_register_same_multiple_times() 126 { 127 $this->callback->register('after_construct'); 128 $this->callback->register('after_construct'); 129 $this->assert_equals(array('after_construct','after_construct','after_construct'),$this->callback->get_callbacks('after_construct')); 130 } 131 132 public function test_register_closure_callback() 133 { 134 $closure = function($model) {}; 135 $this->callback->register('after_save',$closure); 136 $this->assert_equals(array($closure),$this->callback->get_callbacks('after_save')); 137 } 138 139 public function test_get_callbacks_returns_array() 140 { 141 $this->callback->register('after_construct'); 142 $this->assert_true(is_array($this->callback->get_callbacks('after_construct'))); 143 } 144 145 public function test_get_callbacks_returns_null() 146 { 147 $this->assert_null($this->callback->get_callbacks('this_callback_name_should_never_exist')); 148 } 149 150 public function test_invoke_runs_all_callbacks() 151 { 152 $mock = $this->get_mock('VenueCB',array('after_destroy_one','after_destroy_two')); 153 $mock->expects($this->once())->method('after_destroy_one'); 154 $mock->expects($this->once())->method('after_destroy_two'); 155 $this->callback->invoke($mock,'after_destroy'); 156 } 157 158 public function test_invoke_closure() 159 { 160 $i_ran = false; 161 $this->callback->register('after_validation',function($model) use (&$i_ran) { $i_ran = true; }); 162 $this->callback->invoke(null,'after_validation'); 163 $this->assert_true($i_ran); 164 } 165 166 public function test_invoke_implicitly_calls_save_first() 167 { 168 $this->assert_implicit_save('before_save','before_create'); 169 $this->assert_implicit_save('before_save','before_update'); 170 $this->assert_implicit_save('after_save','after_create'); 171 $this->assert_implicit_save('after_save','after_update'); 172 } 173 174 /** 175 * @expectedException ActiveRecord\ActiveRecordException 176 */ 177 public function test_invoke_unregistered_callback() 178 { 179 $mock = $this->get_mock('VenueCB', array('columns')); 180 $this->callback->invoke($mock,'before_validation_on_create'); 181 } 182 183 public function test_before_callbacks_pass_on_false_return_callback_returned_false() 184 { 185 $this->callback->register('before_validation',function($model) { return false; }); 186 $this->assert_false($this->callback->invoke(null,'before_validation')); 187 } 188 189 public function test_before_callbacks_does_not_pass_on_false_for_after_callbacks() 190 { 191 $this->callback->register('after_validation',function($model) { return false; }); 192 $this->assert_true($this->callback->invoke(null,'after_validation')); 193 } 194 195 public function test_gh_28_after_create_should_be_invoked_after_auto_incrementing_pk_is_set() 196 { 197 $that = $this; 198 VenueCB::$after_create = function($model) use ($that) { $that->assert_not_null($model->id); }; 199 ActiveRecord\Table::clear_cache('VenueCB'); 200 $venue = VenueCB::find(1); 201 $venue = new VenueCB($venue->attributes()); 202 $venue->id = null; 203 $venue->name = 'alksdjfs'; 204 $venue->save(); 205 } 206 207 public function test_before_create_returned_false_halts_execution() 208 { 209 VenueCB::$before_create = array('before_create_halt_execution'); 210 ActiveRecord\Table::clear_cache('VenueCB'); 211 $table = ActiveRecord\Table::load('VenueCB'); 212 213 $i_ran = false; 214 $i_should_have_ran = false; 215 $table->callback->register('before_save', function($model) use (&$i_should_have_ran) { $i_should_have_ran = true; }); 216 $table->callback->register('before_create',function($model) use (&$i_ran) { $i_ran = true; }); 217 $table->callback->register('after_create',function($model) use (&$i_ran) { $i_ran = true; }); 218 219 $v = VenueCB::find(1); 220 $v->id = null; 221 VenueCB::create($v->attributes()); 222 223 $this->assert_true($i_should_have_ran); 224 $this->assert_false($i_ran); 225 $this->assert_true(strpos(ActiveRecord\Table::load('VenueCB')->last_sql, 'INSERT') === false); 226 } 227 228 public function test_before_save_returned_false_halts_execution() 229 { 230 VenueCB::$before_update = array('before_update_halt_execution'); 231 ActiveRecord\Table::clear_cache('VenueCB'); 232 $table = ActiveRecord\Table::load('VenueCB'); 233 234 $i_ran = false; 235 $i_should_have_ran = false; 236 $table->callback->register('before_save', function($model) use (&$i_should_have_ran) { $i_should_have_ran = true; }); 237 $table->callback->register('before_update',function($model) use (&$i_ran) { $i_ran = true; }); 238 $table->callback->register('after_save',function($model) use (&$i_ran) { $i_ran = true; }); 239 240 $v = VenueCB::find(1); 241 $v->name .= 'test'; 242 $ret = $v->save(); 243 244 $this->assert_true($i_should_have_ran); 245 $this->assert_false($i_ran); 246 $this->assert_false($ret); 247 $this->assert_true(strpos(ActiveRecord\Table::load('VenueCB')->last_sql, 'UPDATE') === false); 248 } 249 250 public function test_before_destroy_returned_false_halts_execution() 251 { 252 VenueCB::$before_destroy = array('before_destroy_halt_execution'); 253 ActiveRecord\Table::clear_cache('VenueCB'); 254 $table = ActiveRecord\Table::load('VenueCB'); 255 256 $i_ran = false; 257 $table->callback->register('before_destroy',function($model) use (&$i_ran) { $i_ran = true; }); 258 $table->callback->register('after_destroy',function($model) use (&$i_ran) { $i_ran = true; }); 259 260 $v = VenueCB::find(1); 261 $ret = $v->delete(); 262 263 $this->assert_false($i_ran); 264 $this->assert_false($ret); 265 $this->assert_true(strpos(ActiveRecord\Table::load('VenueCB')->last_sql, 'DELETE') === false); 266 } 267 268 public function test_before_validation_returned_false_halts_execution() 269 { 270 VenueCB::$before_validation = array('before_validation_halt_execution'); 271 ActiveRecord\Table::clear_cache('VenueCB'); 272 $table = ActiveRecord\Table::load('VenueCB'); 273 274 $v = VenueCB::find(1); 275 $v->name .= 'test'; 276 $ret = $v->save(); 277 278 $this->assert_false($ret); 279 $this->assert_true(strpos(ActiveRecord\Table::load('VenueCB')->last_sql, 'UPDATE') === false); 280 } 281}; 282?>