88use Tempest \Database \DatabaseMigration ;
99use Tempest \Database \Exceptions \ModelDidNotHavePrimaryColumn ;
1010use Tempest \Database \HasOne ;
11- use Tempest \Database \IsDatabaseModel ;
1211use Tempest \Database \Migrations \CreateMigrationsTable ;
1312use Tempest \Database \PrimaryKey ;
1413use Tempest \Database \QueryStatement ;
2322 */
2423final class ModelsWithoutIdTest extends FrameworkIntegrationTestCase
2524{
26- public function test_save_creates_new_record_for_model_without_id (): void
27- {
28- $ this ->migrate (CreateMigrationsTable::class, CreateLogEntryMigration::class);
29-
30- $ log = new LogEntry (level: 'INFO ' , message: 'Frieren discovered ancient magic ' , context: 'exploration ' );
31- $ savedLog = $ log ->save ();
32-
33- $ this ->assertSame ($ log , $ savedLog );
34- $ this ->assertSame ('INFO ' , $ savedLog ->level );
35- $ this ->assertSame ('Frieren discovered ancient magic ' , $ savedLog ->message );
36-
37- $ allLogs = query (LogEntry::class)->all ();
38- $ this ->assertCount (1 , $ allLogs );
39- $ this ->assertSame ('INFO ' , $ allLogs [0 ]->level );
40- }
41-
42- public function test_save_always_inserts_for_models_without_id (): void
43- {
44- $ this ->migrate (CreateMigrationsTable::class, CreateLogEntryMigration::class);
45-
46- $ log = new LogEntry (level: 'INFO ' , message: 'Original message ' , context: 'test ' );
47- $ log ->save ();
48-
49- // Models without primary keys always insert when save() is called
50- $ log ->message = 'Modified message ' ;
51- $ log ->save ();
52-
53- $ allLogs = query (LogEntry::class)->all ();
54- $ this ->assertCount (2 , $ allLogs );
55- $ this ->assertSame ('Original message ' , $ allLogs [0 ]->message );
56- $ this ->assertSame ('Modified message ' , $ allLogs [1 ]->message );
57- }
58-
5925 public function test_update_model_without_id_with_specific_conditions (): void
6026 {
6127 $ this ->migrate (CreateMigrationsTable::class, CreateLogEntryMigration::class);
@@ -166,13 +132,11 @@ public function test_model_with_mixed_id_and_non_id_properties(): void
166132 {
167133 $ this ->migrate (CreateMigrationsTable::class, CreateMixedModelMigration::class);
168134
169- $ mixed = new MixedModel (
135+ $ mixed = query ( MixedModel::class)-> create (
170136 regular_field: 'test ' ,
171137 another_field: 'data ' ,
172138 );
173139
174- $ mixed ->save ();
175-
176140 $ this ->assertInstanceOf (PrimaryKey::class, $ mixed ->id );
177141 $ this ->assertSame ('test ' , $ mixed ->regular_field );
178142
@@ -182,107 +146,6 @@ public function test_model_with_mixed_id_and_non_id_properties(): void
182146 $ this ->assertSame ('test ' , $ all [0 ]->regular_field );
183147 }
184148
185- public function test_refresh_throws_for_models_without_id (): void
186- {
187- $ this ->migrate (CreateMigrationsTable::class, CreateLogEntryMigration::class);
188-
189- $ log = new LogEntry (
190- level: 'INFO ' ,
191- message: 'Frieren studies magic ' ,
192- context: 'training ' ,
193- );
194-
195- $ this ->expectException (ModelDidNotHavePrimaryColumn::class);
196- $ this ->expectExceptionMessage ('does not have a primary column defined, which is required for the `refresh` method ' );
197-
198- $ log ->refresh ();
199- }
200-
201- public function test_load_throws_for_models_without_id (): void
202- {
203- $ this ->migrate (CreateMigrationsTable::class, CreateLogEntryMigration::class);
204-
205- $ log = new LogEntry (
206- level: 'INFO ' ,
207- message: 'Frieren explores ruins ' ,
208- context: 'adventure ' ,
209- );
210-
211- $ this ->expectException (ModelDidNotHavePrimaryColumn::class);
212- $ this ->expectExceptionMessage ('does not have a primary column defined, which is required for the `load` method ' );
213-
214- $ log ->load ('someRelation ' );
215- }
216-
217- public function test_refresh_works_for_models_with_id (): void
218- {
219- $ this ->migrate (CreateMigrationsTable::class, CreateMixedModelMigration::class);
220-
221- $ mixed = query (MixedModel::class)->create (
222- regular_field: 'original ' ,
223- another_field: 'data ' ,
224- );
225-
226- query (MixedModel::class)
227- ->update (regular_field: 'updated ' )
228- ->where ('id ' , $ mixed ->id ->value )
229- ->execute ();
230-
231- $ mixed ->refresh ();
232-
233- $ this ->assertSame ('updated ' , $ mixed ->regular_field );
234- $ this ->assertSame ('data ' , $ mixed ->another_field );
235- }
236-
237- public function test_refresh_works_for_models_with_unloaded_relation (): void
238- {
239- $ this ->migrate (
240- CreateMigrationsTable::class,
241- CreateTestUserMigration::class,
242- CreateTestProfileMigration::class,
243- );
244-
245- $ user = query (TestUser::class)->create (
246- name: 'Frieren ' ,
247- 248- );
249-
250- query (TestProfile::class)->create (
251- user: $ user ,
252- bio: 'Ancient elf mage ' ,
253- age: 1000 ,
254- );
255-
256- // Get user without loading the profile relation
257- $ userWithoutProfile = query (TestUser::class)->findById ($ user ->id );
258-
259- $ this ->assertNull ($ userWithoutProfile ->profile );
260-
261- // Update the user's name in the database
262- query (TestUser::class)
263- ->update (name: 'Frieren the Mage ' )
264- ->where ('id ' , $ user ->id ->value )
265- ->execute ();
266-
267- // Refresh should work even with unloaded relations
268- $ userWithoutProfile ->refresh ();
269-
270- $ this ->assertSame ('Frieren the Mage ' , $ userWithoutProfile ->name );
271- $ this ->
assertSame (
'[email protected] ' ,
$ userWithoutProfile->
email );
272- $ this ->assertNull ($ userWithoutProfile ->profile ); // Relation should still be unloaded
273-
274- // Load the relation
275- $ userWithoutProfile ->load ('profile ' );
276-
277- $ this ->assertInstanceOf (TestProfile::class, $ userWithoutProfile ->profile );
278- $ this ->assertSame ('Ancient elf mage ' , $ userWithoutProfile ->profile ->bio );
279- $ this ->assertSame (1000 , $ userWithoutProfile ->profile ->age );
280-
281- $ userWithoutProfile ->refresh ();
282-
283- $ this ->assertInstanceOf (TestProfile::class, $ userWithoutProfile ->profile );
284- }
285-
286149 public function test_load_works_for_models_with_id (): void
287150 {
288151 $ this ->migrate (CreateMigrationsTable::class, CreateMixedModelMigration::class);
@@ -361,8 +224,6 @@ public function test_load_method_refreshes_all_properties_not_just_relations():
361224
362225final class LogEntry
363226{
364- use IsDatabaseModel;
365-
366227 public function __construct (
367228 public string $ level ,
368229 public string $ message ,
@@ -373,8 +234,6 @@ public function __construct(
373234#[Table('cache_entries ' )]
374235final class CacheEntry
375236{
376- use IsDatabaseModel;
377-
378237 public function __construct (
379238 public string $ cache_key ,
380239 public string $ cache_value ,
@@ -384,8 +243,6 @@ public function __construct(
384243
385244final class MixedModel
386245{
387- use IsDatabaseModel;
388-
389246 public ?PrimaryKey $ id = null ;
390247
391248 public function __construct (
@@ -396,8 +253,6 @@ public function __construct(
396253
397254final class TestUser
398255{
399- use IsDatabaseModel;
400-
401256 public ?PrimaryKey $ id = null ;
402257
403258 #[HasOne(ownerJoin: 'user_id ' )]
@@ -411,8 +266,6 @@ public function __construct(
411266
412267final class TestProfile
413268{
414- use IsDatabaseModel;
415-
416269 public ?PrimaryKey $ id = null ;
417270
418271 #[BelongsTo(ownerJoin: 'user_id ' )]
0 commit comments