a tiny mvc framework for php using php-activerecord
at v1 523 lines 15 kB view raw
1<?php 2include 'helpers/config.php'; 3 4class ActiveRecordTest extends DatabaseTest 5{ 6 public function set_up($connection_name=null) 7 { 8 parent::set_up($connection_name); 9 $this->options = array('conditions' => 'blah', 'order' => 'blah'); 10 } 11 12 public function test_options_is_not() 13 { 14 $this->assert_false(Author::is_options_hash(null)); 15 $this->assert_false(Author::is_options_hash('')); 16 $this->assert_false(Author::is_options_hash('tito')); 17 $this->assert_false(Author::is_options_hash(array())); 18 $this->assert_false(Author::is_options_hash(array(1,2,3))); 19 } 20 21 /** 22 * @expectedException ActiveRecord\ActiveRecordException 23 */ 24 public function test_options_hash_with_unknown_keys() { 25 $this->assert_false(Author::is_options_hash(array('conditions' => 'blah', 'sharks' => 'laserz', 'dubya' => 'bush'))); 26 } 27 28 public function test_options_is_hash() 29 { 30 $this->assert_true(Author::is_options_hash($this->options)); 31 } 32 33 public function test_extract_and_validate_options() { 34 $args = array('first',$this->options); 35 $this->assert_equals($this->options,Author::extract_and_validate_options($args)); 36 $this->assert_equals(array('first'),$args); 37 } 38 39 public function test_extract_and_validate_options_with_array_in_args() { 40 $args = array('first',array(1,2),$this->options); 41 $this->assert_equals($this->options,Author::extract_and_validate_options($args)); 42 } 43 44 public function test_extract_and_validate_options_removes_options_hash() { 45 $args = array('first',$this->options); 46 Author::extract_and_validate_options($args); 47 $this->assert_equals(array('first'),$args); 48 } 49 50 public function test_extract_and_validate_options_nope() { 51 $args = array('first'); 52 $this->assert_equals(array(),Author::extract_and_validate_options($args)); 53 $this->assert_equals(array('first'),$args); 54 } 55 56 public function test_extract_and_validate_options_nope_because_wasnt_at_end() { 57 $args = array('first',$this->options,array(1,2)); 58 $this->assert_equals(array(),Author::extract_and_validate_options($args)); 59 } 60 61 /** 62 * @expectedException ActiveRecord\UndefinedPropertyException 63 */ 64 public function test_invalid_attribute() 65 { 66 $author = Author::find('first',array('conditions' => 'author_id=1')); 67 $author->some_invalid_field_name; 68 } 69 70 public function test_invalid_attributes() 71 { 72 $book = Book::find(1); 73 try { 74 $book->update_attributes(array('name' => 'new name', 'invalid_attribute' => true , 'another_invalid_attribute' => 'something')); 75 } catch (ActiveRecord\UndefinedPropertyException $e) { 76 $exceptions = explode("\r\n", $e->getMessage()); 77 } 78 79 $this->assert_equals(1, substr_count($exceptions[0], 'invalid_attribute')); 80 $this->assert_equals(1, substr_count($exceptions[1], 'another_invalid_attribute')); 81 } 82 83 public function test_getter_undefined_property_exception_includes_model_name() 84 { 85 $this->assert_exception_message_contains("Author->this_better_not_exist",function() 86 { 87 $author = new Author(); 88 $author->this_better_not_exist; 89 }); 90 } 91 92 public function test_mass_assignment_undefined_property_exception_includes_model_name() 93 { 94 $this->assert_exception_message_contains("Author->this_better_not_exist",function() 95 { 96 new Author(array("this_better_not_exist" => "hi")); 97 }); 98 } 99 100 public function test_setter_undefined_property_exception_includes_model_name() 101 { 102 $this->assert_exception_message_contains("Author->this_better_not_exist",function() 103 { 104 $author = new Author(); 105 $author->this_better_not_exist = "hi"; 106 }); 107 } 108 109 public function test_get_values_for() 110 { 111 $book = Book::find_by_name('Ancient Art of Main Tanking'); 112 $ret = $book->get_values_for(array('book_id','author_id')); 113 $this->assert_equals(array('book_id','author_id'),array_keys($ret)); 114 $this->assert_equals(array(1,1),array_values($ret)); 115 } 116 117 public function test_hyphenated_column_names_to_underscore() 118 { 119 if ($this->conn instanceof ActiveRecord\OciAdapter) 120 return; 121 122 $keys = array_keys(RmBldg::first()->attributes()); 123 $this->assert_true(in_array('rm_name',$keys)); 124 } 125 126 public function test_column_names_with_spaces() 127 { 128 if ($this->conn instanceof ActiveRecord\OciAdapter) 129 return; 130 131 $keys = array_keys(RmBldg::first()->attributes()); 132 $this->assert_true(in_array('space_out',$keys)); 133 } 134 135 public function test_mixed_case_column_name() 136 { 137 $keys = array_keys(Author::first()->attributes()); 138 $this->assert_true(in_array('mixedcasefield',$keys)); 139 } 140 141 public function test_mixed_case_primary_key_save() 142 { 143 $venue = Venue::find(1); 144 $venue->name = 'should not throw exception'; 145 $venue->save(); 146 $this->assert_equals($venue->name,Venue::find(1)->name); 147 } 148 149 public function test_reload() 150 { 151 $venue = Venue::find(1); 152 $this->assert_equals('NY', $venue->state); 153 $venue->state = 'VA'; 154 $this->assert_equals('VA', $venue->state); 155 $venue->reload(); 156 $this->assert_equals('NY', $venue->state); 157 } 158 159 public function test_reload_protected_attribute() 160 { 161 $book = BookAttrAccessible::find(1); 162 163 $book->name = "Should not stay"; 164 $book->reload(); 165 $this->assert_not_equals("Should not stay", $book->name); 166 } 167 168 public function test_active_record_model_home_not_set() 169 { 170 $home = ActiveRecord\Config::instance()->get_model_directory(); 171 ActiveRecord\Config::instance()->set_model_directory(__FILE__); 172 $this->assert_equals(false,class_exists('TestAutoload')); 173 174 ActiveRecord\Config::instance()->set_model_directory($home); 175 } 176 177 public function test_auto_load_with_namespaced_model() 178 { 179 $this->assert_true(class_exists('NamespaceTest\Book')); 180 } 181 182 public function test_namespace_gets_stripped_from_table_name() 183 { 184 $model = new NamespaceTest\Book(); 185 $this->assert_equals('books',$model->table()->table); 186 } 187 188 public function test_namespace_gets_stripped_from_inferred_foreign_key() 189 { 190 $model = new NamespaceTest\Book(); 191 $table = ActiveRecord\Table::load(get_class($model)); 192 $this->assert_equals($table->get_relationship('parent_book')->foreign_key[0], 'book_id'); 193 } 194 195 public function test_should_have_all_column_attributes_when_initializing_with_array() 196 { 197 $author = new Author(array('name' => 'Tito')); 198 $this->assert_true(count(array_keys($author->attributes())) >= 9); 199 } 200 201 public function test_defaults() 202 { 203 $author = new Author(); 204 $this->assert_equals('default_name',$author->name); 205 } 206 207 public function test_alias_attribute_getter() 208 { 209 $venue = Venue::find(1); 210 $this->assert_equals($venue->marquee, $venue->name); 211 $this->assert_equals($venue->mycity, $venue->city); 212 } 213 214 public function test_alias_attribute_setter() 215 { 216 $venue = Venue::find(1); 217 $venue->marquee = 'new name'; 218 $this->assert_equals($venue->marquee, 'new name'); 219 $this->assert_equals($venue->marquee, $venue->name); 220 221 $venue->name = 'another name'; 222 $this->assert_equals($venue->name, 'another name'); 223 $this->assert_equals($venue->marquee, $venue->name); 224 } 225 226 public function test_alias_from_mass_attributes() 227 { 228 $venue = new Venue(array('marquee' => 'meme', 'id' => 123)); 229 $this->assert_equals('meme',$venue->name); 230 $this->assert_equals($venue->marquee,$venue->name); 231 } 232 233 public function test_gh18_isset_on_aliased_attribute() 234 { 235 $this->assert_true(isset(Venue::first()->marquee)); 236 } 237 238 public function test_attr_accessible() 239 { 240 $book = new BookAttrAccessible(array('name' => 'should not be set', 'author_id' => 1)); 241 $this->assert_null($book->name); 242 $this->assert_equals(1,$book->author_id); 243 $book->name = 'test'; 244 $this->assert_equals('test', $book->name); 245 } 246 247 public function test_attr_protected() 248 { 249 $book = new BookAttrAccessible(array('book_id' => 999)); 250 $this->assert_null($book->book_id); 251 $book->book_id = 999; 252 $this->assert_equals(999, $book->book_id); 253 } 254 255 public function test_isset() 256 { 257 $book = new Book(); 258 $this->assert_true(isset($book->name)); 259 $this->assert_false(isset($book->sharks)); 260 } 261 262 public function test_readonly_only_halt_on_write_method() 263 { 264 $book = Book::first(array('readonly' => true)); 265 $this->assert_true($book->is_readonly()); 266 267 try { 268 $book->save(); 269 $this-fail('expected exception ActiveRecord\ReadonlyException'); 270 } catch (ActiveRecord\ReadonlyException $e) { 271 } 272 273 $book->name = 'some new name'; 274 $this->assert_equals($book->name, 'some new name'); 275 } 276 277 public function test_cast_when_using_setter() 278 { 279 $book = new Book(); 280 $book->book_id = '1'; 281 $this->assert_same(1,$book->book_id); 282 } 283 284 public function test_cast_when_loading() 285 { 286 $book = Book::find(1); 287 $this->assert_same(1,$book->book_id); 288 $this->assert_same('Ancient Art of Main Tanking',$book->name); 289 } 290 291 public function test_cast_defaults() 292 { 293 $book = new Book(); 294 $this->assert_same(0.0,$book->special); 295 } 296 297 public function test_transaction_committed() 298 { 299 $original = Author::count(); 300 $ret = Author::transaction(function() { Author::create(array("name" => "blah")); }); 301 $this->assert_equals($original+1,Author::count()); 302 $this->assert_true($ret); 303 } 304 305 public function test_transaction_committed_when_returning_true() 306 { 307 $original = Author::count(); 308 $ret = Author::transaction(function() { Author::create(array("name" => "blah")); return true; }); 309 $this->assert_equals($original+1,Author::count()); 310 $this->assert_true($ret); 311 } 312 313 public function test_transaction_rolledback_by_returning_false() 314 { 315 $original = Author::count(); 316 317 $ret = Author::transaction(function() 318 { 319 Author::create(array("name" => "blah")); 320 return false; 321 }); 322 323 $this->assert_equals($original,Author::count()); 324 $this->assert_false($ret); 325 } 326 327 public function test_transaction_rolledback_by_throwing_exception() 328 { 329 $original = Author::count(); 330 $exception = null; 331 332 try 333 { 334 Author::transaction(function() 335 { 336 Author::create(array("name" => "blah")); 337 throw new Exception("blah"); 338 }); 339 } 340 catch (Exception $e) 341 { 342 $exception = $e; 343 } 344 345 $this->assert_not_null($exception); 346 $this->assert_equals($original,Author::count()); 347 } 348 349 public function test_delegate() 350 { 351 $event = Event::first(); 352 $this->assert_equals($event->venue->state,$event->state); 353 $this->assert_equals($event->venue->address,$event->address); 354 } 355 356 public function test_delegate_prefix() 357 { 358 $event = Event::first(); 359 $this->assert_equals($event->host->name,$event->woot_name); 360 } 361 362 public function test_delegate_returns_null_if_relationship_does_not_exist() 363 { 364 $event = new Event(); 365 $this->assert_null($event->state); 366 } 367 368 public function test_delegate_set_attribute() 369 { 370 $event = Event::first(); 371 $event->state = 'MEXICO'; 372 $this->assert_equals('MEXICO',$event->venue->state); 373 } 374 375 public function test_delegate_getter_gh_98() 376 { 377 Venue::$use_custom_get_state_getter = true; 378 379 $event = Event::first(); 380 $this->assert_equals('ny', $event->venue->state); 381 $this->assert_equals('ny', $event->state); 382 383 Venue::$use_custom_get_state_getter = false; 384 } 385 386 public function test_delegate_setter_gh_98() 387 { 388 Venue::$use_custom_set_state_setter = true; 389 390 $event = Event::first(); 391 $event->state = 'MEXICO'; 392 $this->assert_equals('MEXICO#',$event->venue->state); 393 394 Venue::$use_custom_set_state_setter = false; 395 } 396 397 public function test_table_name_with_underscores() 398 { 399 $this->assert_not_null(AwesomePerson::first()); 400 } 401 402 public function test_model_should_default_as_new_record() 403 { 404 $author = new Author(); 405 $this->assert_true($author->is_new_record()); 406 } 407 408 public function test_setter() 409 { 410 $author = new Author(); 411 $author->password = 'plaintext'; 412 $this->assert_equals(md5('plaintext'),$author->encrypted_password); 413 } 414 415 public function test_setter_with_same_name_as_an_attribute() 416 { 417 $author = new Author(); 418 $author->name = 'bob'; 419 $this->assert_equals('BOB',$author->name); 420 } 421 422 public function test_getter() 423 { 424 $book = Book::first(); 425 $this->assert_equals(strtoupper($book->name), $book->upper_name); 426 } 427 428 public function test_getter_with_same_name_as_an_attribute() 429 { 430 Book::$use_custom_get_name_getter = true; 431 $book = new Book; 432 $book->name = 'bob'; 433 $this->assert_equals('BOB', $book->name); 434 Book::$use_custom_get_name_getter = false; 435 } 436 437 public function test_setting_invalid_date_should_set_date_to_null() 438 { 439 $author = new Author(); 440 $author->created_at = 'CURRENT_TIMESTAMP'; 441 $this->assertNull($author->created_at); 442 } 443 444 public function test_table_name() 445 { 446 $this->assert_equals('authors',Author::table_name()); 447 } 448 449 /** 450 * @expectedException ActiveRecord\ActiveRecordException 451 */ 452 public function test_undefined_instance_method() 453 { 454 Author::first()->find_by_name('sdf'); 455 } 456 457 public function test_clear_cache_for_specific_class() 458 { 459 $book_table1 = ActiveRecord\Table::load('Book'); 460 $book_table2 = ActiveRecord\Table::load('Book'); 461 ActiveRecord\Table::clear_cache('Book'); 462 $book_table3 = ActiveRecord\Table::load('Book'); 463 464 $this->assert_true($book_table1 === $book_table2); 465 $this->assert_true($book_table1 !== $book_table3); 466 } 467 468 public function test_flag_dirty() 469 { 470 $author = new Author(); 471 $author->flag_dirty('some_date'); 472 $this->assert_has_keys('some_date', $author->dirty_attributes()); 473 $this->assert_true($author->attribute_is_dirty('some_date')); 474 $author->save(); 475 $this->assert_false($author->attribute_is_dirty('some_date')); 476 } 477 478 public function test_flag_dirty_attribute() 479 { 480 $author = new Author(); 481 $author->flag_dirty('some_inexistant_property'); 482 $this->assert_null($author->dirty_attributes()); 483 $this->assert_false($author->attribute_is_dirty('some_inexistant_property')); 484 } 485 486 public function test_assigning_php_datetime_gets_converted_to_ar_datetime() 487 { 488 $author = new Author(); 489 $author->created_at = $now = new \DateTime(); 490 $this->assert_is_a("ActiveRecord\\DateTime",$author->created_at); 491 $this->assert_datetime_equals($now,$author->created_at); 492 } 493 494 public function test_assigning_from_mass_assignment_php_datetime_gets_converted_to_ar_datetime() 495 { 496 $author = new Author(array('created_at' => new \DateTime())); 497 $this->assert_is_a("ActiveRecord\\DateTime",$author->created_at); 498 } 499 500 public function test_get_real_attribute_name() 501 { 502 $venue = new Venue(); 503 $this->assert_equals('name', $venue->get_real_attribute_name('name')); 504 $this->assert_equals('name', $venue->get_real_attribute_name('marquee')); 505 $this->assert_equals(null, $venue->get_real_attribute_name('invalid_field')); 506 } 507 508 public function test_id_setter_works_with_table_without_pk_named_attribute() 509 { 510 $author = new Author(array('id' => 123)); 511 $this->assert_equals(123,$author->author_id); 512 } 513 514 public function test_query() 515 { 516 $row = Author::query('SELECT COUNT(*) AS n FROM authors',null)->fetch(); 517 $this->assert_true($row['n'] > 1); 518 519 $row = Author::query('SELECT COUNT(*) AS n FROM authors WHERE name=?',array('Tito'))->fetch(); 520 $this->assert_equals(array('n' => 1), $row); 521 } 522}; 523?>