From f3fd116da2a138e642de10e00368f1ecf34b5330 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Nov 2023 13:14:20 +0900 Subject: [PATCH 1/4] test: add tests for Model timestamp --- tests/_support/Models/UserTimestampModel.php | 29 +++ tests/system/Models/TimestampModelTest.php | 254 +++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 tests/_support/Models/UserTimestampModel.php create mode 100644 tests/system/Models/TimestampModelTest.php diff --git a/tests/_support/Models/UserTimestampModel.php b/tests/_support/Models/UserTimestampModel.php new file mode 100644 index 000000000000..1cc66d334e37 --- /dev/null +++ b/tests/_support/Models/UserTimestampModel.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Tests\Support\Models; + +use CodeIgniter\Model; + +class UserTimestampModel extends Model +{ + protected $table = 'user'; + protected $allowedFields = [ + 'name', + 'email', + 'country', + 'deleted_at', + ]; + protected $returnType = 'array'; + protected $useSoftDeletes = true; + protected $useTimestamps = true; + protected $dateFormat = 'datetime'; +} diff --git a/tests/system/Models/TimestampModelTest.php b/tests/system/Models/TimestampModelTest.php new file mode 100644 index 000000000000..b44461a8a3c9 --- /dev/null +++ b/tests/system/Models/TimestampModelTest.php @@ -0,0 +1,254 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\Models; + +use CodeIgniter\I18n\Time; +use Tests\Support\Entity\User; +use Tests\Support\Models\UserTimestampModel; + +/** + * @group DatabaseLive + * + * @internal + */ +final class TimestampModelTest extends LiveModelTestCase +{ + protected $migrate = true; + protected $migrateOnce = true; + protected $refresh = false; + protected $seed = ''; + + protected function tearDown(): void + { + parent::tearDown(); + + // Reset current time. + Time::setTestNow(); + } + + /** + * @return int|string Insert ID + */ + private function allowDatesPrepareOneRecord(array $data) + { + $this->createModel(UserTimestampModel::class); + $this->db->table('user')->truncate(); + + $this->model->setAllowedFields([ + 'name', + 'email', + 'country', + 'created_at', + 'updated_at', + 'deleted_at', + ]); + + return $this->model->insert($data, true); + } + + /** + * @return int|string Insert ID + */ + private function doNotAllowDatesPrepareOneRecord(array $data) + { + $this->createModel(UserTimestampModel::class); + $this->db->table('user')->truncate(); + + $this->model->setAllowedFields([ + 'name', + 'email', + 'country', + // no 'created_at', + // no 'updated_at', + 'deleted_at', + ]); + + return $this->model->insert($data, true); + } + + public function testDoNotAllowDatesInsertArrayWithoutDatesSetsTimestamp(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + // no created_at + // no updated_at + ]; + $id = $this->doNotAllowDatesPrepareOneRecord($data); + + $user = $this->model->find($id); + + $this->assertSame('2023-11-25 12:00:00', $user['created_at']); + $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + } + + public function testDoNotAllowDatesInsertArrayWithDatesSetsTimestamp(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + 'created_at' => '2000-01-01 12:00:00', + 'updated_at' => '2000-01-01 12:00:00', + ]; + $id = $this->doNotAllowDatesPrepareOneRecord($data); + + $user = $this->model->find($id); + + $this->assertSame('2023-11-25 12:00:00', $user['created_at']); + $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + } + + public function testDoNotAllowDatesUpdateArrayUpdatesUpdatedAt(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + 'created_at' => '2000-01-01 12:00:00', + 'updated_at' => '2000-01-01 12:00:00', + ]; + $id = $this->doNotAllowDatesPrepareOneRecord($data); + + $user = $this->model->find($id); + + $user['country'] = 'CA'; + $this->model->update($user['id'], $user); + + $user = $this->model->find($id); + + $this->assertSame('2023-11-25 12:00:00', $user['created_at']); + $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + } + + public function testDoNotAllowDatesUpdateEntityUpdatesUpdatedAt(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + 'created_at' => '2000-01-01 12:00:00', + 'updated_at' => '2000-01-01 12:00:00', + ]; + $id = $this->doNotAllowDatesPrepareOneRecord($data); + $this->setPrivateProperty($this->model, 'returnType', User::class); + $this->setPrivateProperty($this->model, 'tempReturnType', User::class); + + $user = $this->model->find($id); + + $user->country = 'CA'; + $this->model->update($user->id, $user); + + $user = $this->model->find($id); + + $this->assertSame('2023-11-25 12:00:00', (string) $user->created_at); + $this->assertSame('2023-11-25 12:00:00', (string) $user->updated_at); + } + + public function testAllowDatesInsertArrayWithoutDatesSetsTimestamp(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + // no created_at + // no updated_at + ]; + $id = $this->allowDatesPrepareOneRecord($data); + + $user = $this->model->find($id); + + $this->assertSame('2023-11-25 12:00:00', $user['created_at']); + $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + } + + public function testAllowDatesInsertArrayWithDatesSetsTimestamp(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + 'created_at' => '2000-01-01 12:00:00', + 'updated_at' => '2000-01-01 12:00:00', + ]; + $id = $this->allowDatesPrepareOneRecord($data); + + $user = $this->model->find($id); + + $this->assertSame('2000-01-01 12:00:00', $user['created_at']); + $this->assertSame('2000-01-01 12:00:00', $user['updated_at']); + } + + public function testAllowDatesUpdateArrayUpdatesUpdatedAt(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + 'created_at' => '2000-01-01 12:00:00', + 'updated_at' => '2000-01-01 12:00:00', + ]; + $id = $this->allowDatesPrepareOneRecord($data); + + $user = $this->model->find($id); + + $user['country'] = 'CA'; + $this->model->update($user['id'], $user); + + $user = $this->model->find($id); + + $this->assertSame('2000-01-01 12:00:00', $user['created_at']); + $this->assertSame('2000-01-01 12:00:00', $user['updated_at']); + } + + public function testAllowDatesUpdateEntityUpdatesUpdatedAt(): void + { + Time::setTestNow('2023-11-25 12:00:00'); + + $data = [ + 'name' => 'John Smith', + 'email' => 'john@example.com', + 'country' => 'US', + 'created_at' => '2000-01-01 12:00:00', + 'updated_at' => '2000-01-01 12:00:00', + ]; + $id = $this->allowDatesPrepareOneRecord($data); + $this->setPrivateProperty($this->model, 'returnType', User::class); + $this->setPrivateProperty($this->model, 'tempReturnType', User::class); + + $user = $this->model->find($id); + + $user->country = 'CA'; + $this->model->update($user->id, $user); + + $user = $this->model->find($id); + + $this->assertSame('2000-01-01 12:00:00', (string) $user->created_at); + // The Entity has `updated_at` value, but it will be discarded because of onlyChanged. + $this->assertSame('2023-11-25 12:00:00', (string) $user->updated_at); + } +} From d690553efc77de7ea9dbf8f90c515e01c14f0f76 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Nov 2023 14:24:59 +0900 Subject: [PATCH 2/4] docs: add comments --- tests/system/Models/TimestampModelTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/system/Models/TimestampModelTest.php b/tests/system/Models/TimestampModelTest.php index b44461a8a3c9..92458449b981 100644 --- a/tests/system/Models/TimestampModelTest.php +++ b/tests/system/Models/TimestampModelTest.php @@ -163,6 +163,10 @@ public function testDoNotAllowDatesUpdateEntityUpdatesUpdatedAt(): void $this->assertSame('2023-11-25 12:00:00', (string) $user->updated_at); } + /** + * We do not recommend to add timestamp fields to $allowedFields. + * If you want to add old data to these fields, use Query Builder. + */ public function testAllowDatesInsertArrayWithoutDatesSetsTimestamp(): void { Time::setTestNow('2023-11-25 12:00:00'); @@ -182,6 +186,10 @@ public function testAllowDatesInsertArrayWithoutDatesSetsTimestamp(): void $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); } + /** + * We do not recommend to add timestamp fields to $allowedFields. + * If you want to add old data to these fields, use Query Builder. + */ public function testAllowDatesInsertArrayWithDatesSetsTimestamp(): void { Time::setTestNow('2023-11-25 12:00:00'); @@ -201,6 +209,10 @@ public function testAllowDatesInsertArrayWithDatesSetsTimestamp(): void $this->assertSame('2000-01-01 12:00:00', $user['updated_at']); } + /** + * We do not recommend to add timestamp fields to $allowedFields. + * If you want to add old data to these fields, use Query Builder. + */ public function testAllowDatesUpdateArrayUpdatesUpdatedAt(): void { Time::setTestNow('2023-11-25 12:00:00'); @@ -225,6 +237,10 @@ public function testAllowDatesUpdateArrayUpdatesUpdatedAt(): void $this->assertSame('2000-01-01 12:00:00', $user['updated_at']); } + /** + * We do not recommend to add timestamp fields to $allowedFields. + * If you want to add old data to these fields, use Query Builder. + */ public function testAllowDatesUpdateEntityUpdatesUpdatedAt(): void { Time::setTestNow('2023-11-25 12:00:00'); From d062b568a5cdebacf750eab7215b4bf85f8e5810 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Nov 2023 18:36:07 +0900 Subject: [PATCH 3/4] test: fix assertions for SQLSRV --- tests/system/Models/TimestampModelTest.php | 48 ++++++++++++++++------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/tests/system/Models/TimestampModelTest.php b/tests/system/Models/TimestampModelTest.php index 92458449b981..6df8b014ba60 100644 --- a/tests/system/Models/TimestampModelTest.php +++ b/tests/system/Models/TimestampModelTest.php @@ -90,8 +90,12 @@ public function testDoNotAllowDatesInsertArrayWithoutDatesSetsTimestamp(): void $user = $this->model->find($id); - $this->assertSame('2023-11-25 12:00:00', $user['created_at']); - $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + $expected = '2023-11-25 12:00:00'; + if ($this->db->DBDriver === 'SQLSRV') { + $expected .= '.000'; + } + $this->assertSame($expected, $user['created_at']); + $this->assertSame($expected, $user['updated_at']); } public function testDoNotAllowDatesInsertArrayWithDatesSetsTimestamp(): void @@ -109,8 +113,12 @@ public function testDoNotAllowDatesInsertArrayWithDatesSetsTimestamp(): void $user = $this->model->find($id); - $this->assertSame('2023-11-25 12:00:00', $user['created_at']); - $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + $expected = '2023-11-25 12:00:00'; + if ($this->db->DBDriver === 'SQLSRV') { + $expected .= '.000'; + } + $this->assertSame($expected, $user['created_at']); + $this->assertSame($expected, $user['updated_at']); } public function testDoNotAllowDatesUpdateArrayUpdatesUpdatedAt(): void @@ -133,8 +141,12 @@ public function testDoNotAllowDatesUpdateArrayUpdatesUpdatedAt(): void $user = $this->model->find($id); - $this->assertSame('2023-11-25 12:00:00', $user['created_at']); - $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + $expected = '2023-11-25 12:00:00'; + if ($this->db->DBDriver === 'SQLSRV') { + $expected .= '.000'; + } + $this->assertSame($expected, $user['created_at']); + $this->assertSame($expected, $user['updated_at']); } public function testDoNotAllowDatesUpdateEntityUpdatesUpdatedAt(): void @@ -182,8 +194,12 @@ public function testAllowDatesInsertArrayWithoutDatesSetsTimestamp(): void $user = $this->model->find($id); - $this->assertSame('2023-11-25 12:00:00', $user['created_at']); - $this->assertSame('2023-11-25 12:00:00', $user['updated_at']); + $expected = '2023-11-25 12:00:00'; + if ($this->db->DBDriver === 'SQLSRV') { + $expected .= '.000'; + } + $this->assertSame($expected, $user['created_at']); + $this->assertSame($expected, $user['updated_at']); } /** @@ -205,8 +221,12 @@ public function testAllowDatesInsertArrayWithDatesSetsTimestamp(): void $user = $this->model->find($id); - $this->assertSame('2000-01-01 12:00:00', $user['created_at']); - $this->assertSame('2000-01-01 12:00:00', $user['updated_at']); + $expected = '2000-01-01 12:00:00'; + if ($this->db->DBDriver === 'SQLSRV') { + $expected .= '.000'; + } + $this->assertSame($expected, $user['created_at']); + $this->assertSame($expected, $user['updated_at']); } /** @@ -233,8 +253,12 @@ public function testAllowDatesUpdateArrayUpdatesUpdatedAt(): void $user = $this->model->find($id); - $this->assertSame('2000-01-01 12:00:00', $user['created_at']); - $this->assertSame('2000-01-01 12:00:00', $user['updated_at']); + $expected = '2000-01-01 12:00:00'; + if ($this->db->DBDriver === 'SQLSRV') { + $expected .= '.000'; + } + $this->assertSame($expected, $user['created_at']); + $this->assertSame($expected, $user['updated_at']); } /** From b09f85eb9b1f366b2e37e368dd92c208c1d8c210 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 25 Nov 2023 20:49:20 +0900 Subject: [PATCH 4/4] test: remove unneeded `deleted_at` in $allowedFields --- tests/_support/Models/UserTimestampModel.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/_support/Models/UserTimestampModel.php b/tests/_support/Models/UserTimestampModel.php index 1cc66d334e37..b3772112379b 100644 --- a/tests/_support/Models/UserTimestampModel.php +++ b/tests/_support/Models/UserTimestampModel.php @@ -20,7 +20,6 @@ class UserTimestampModel extends Model 'name', 'email', 'country', - 'deleted_at', ]; protected $returnType = 'array'; protected $useSoftDeletes = true;