10
10
use Illuminate \Database \Eloquent \Collection as EloquentCollection ;
11
11
use Illuminate \Database \Eloquent \ModelNotFoundException ;
12
12
use Illuminate \Support \Facades \Date ;
13
+ use Illuminate \Support \Facades \DB ;
13
14
use Illuminate \Support \Str ;
14
- use InvalidArgumentException ;
15
15
use MongoDB \BSON \Binary ;
16
16
use MongoDB \BSON \ObjectID ;
17
17
use MongoDB \BSON \UTCDateTime ;
@@ -48,7 +48,7 @@ class ModelTest extends TestCase
48
48
public function tearDown (): void
49
49
{
50
50
Carbon::setTestNow ();
51
- User:: truncate ();
51
+ DB :: connection ( ' mongodb ' )-> getCollection ( ' users ' )-> drop ();
52
52
Soft::truncate ();
53
53
Book::truncate ();
54
54
Item::truncate ();
@@ -1048,19 +1048,34 @@ public function testNumericFieldName(): void
1048
1048
$ this ->assertEquals ([3 => 'two.three ' ], $ found [2 ]);
1049
1049
}
1050
1050
1051
- public function testCreateOrFirst ()
1051
+ #[TestWith([true ])]
1052
+ #[TestWith([false ])]
1053
+ public function testCreateOrFirst (bool $ transaction )
1052
1054
{
1055
+ $ connection = DB ::connection ('mongodb ' );
1056
+ $ connection
1057
+ ->getCollection ('users ' )
1058
+ ->createIndex (['email ' => 1 ], ['unique ' => true ]);
1059
+
1060
+ if ($ transaction ) {
1061
+ $ connection ->beginTransaction ();
1062
+ }
1063
+
1053
1064
Carbon::setTestNow ('2010-06-22 ' );
1054
1065
$ createdAt = Carbon::now ()->getTimestamp ();
1066
+ $ events = [];
1067
+ self ::registerModelEvents (User::class, $ events );
1055
1068
$ user1 = User::
createOrFirst ([
'email ' =>
'[email protected] ' ]);
1056
1069
1057
1070
$ this ->
assertSame (
'[email protected] ' ,
$ user1->
email );
1058
1071
$ this ->assertNull ($ user1 ->name );
1059
1072
$ this ->assertTrue ($ user1 ->wasRecentlyCreated );
1060
1073
$ this ->assertEquals ($ createdAt , $ user1 ->created_at ->getTimestamp ());
1061
1074
$ this ->assertEquals ($ createdAt , $ user1 ->updated_at ->getTimestamp ());
1075
+ $ this ->assertEquals (['saving ' , 'creating ' , 'created ' , 'saved ' ], $ events );
1062
1076
1063
1077
Carbon::setTestNow ('2020-12-28 ' );
1078
+ $ events = [];
1064
1079
$ user2 = User::createOrFirst (
1065
1080
1066
1081
['name ' => 'John Doe ' , 'birthday ' => new DateTime ('1987-05-28 ' )],
@@ -1073,7 +1088,17 @@ public function testCreateOrFirst()
1073
1088
$ this ->assertFalse ($ user2 ->wasRecentlyCreated );
1074
1089
$ this ->assertEquals ($ createdAt , $ user1 ->created_at ->getTimestamp ());
1075
1090
$ this ->assertEquals ($ createdAt , $ user1 ->updated_at ->getTimestamp ());
1091
+ if ($ transaction ) {
1092
+ // In a transaction, firstOrCreate is used instead.
1093
+ // Since a document is found, "save" is not called.
1094
+ $ this ->assertEquals ([], $ events );
1095
+ } else {
1096
+ // The "duplicate key error" exception interrupts the save process
1097
+ // before triggering "created" and "saved". Consistent with Laravel
1098
+ $ this ->assertEquals (['saving ' , 'creating ' ], $ events );
1099
+ }
1076
1100
1101
+ $ events = [];
1077
1102
$ user3 = User::createOrFirst (
1078
1103
1079
1104
['name ' => 'Jane Doe ' , 'birthday ' => new DateTime ('1987-05-28 ' )],
@@ -1086,21 +1111,21 @@ public function testCreateOrFirst()
1086
1111
$ this ->assertTrue ($ user3 ->wasRecentlyCreated );
1087
1112
$ this ->assertEquals ($ createdAt , $ user1 ->created_at ->getTimestamp ());
1088
1113
$ this ->assertEquals ($ createdAt , $ user1 ->updated_at ->getTimestamp ());
1114
+ $ this ->assertEquals (['saving ' , 'creating ' , 'created ' , 'saved ' ], $ events );
1089
1115
1116
+ $ events = [];
1090
1117
$ user4 = User::createOrFirst (
1091
1118
['name ' => 'Robert Doe ' ],
1092
1119
[
'name ' =>
'Maria Doe ' ,
'email ' =>
'[email protected] ' ],
1093
1120
);
1094
1121
1095
1122
$ this ->assertSame ('Maria Doe ' , $ user4 ->name );
1096
1123
$ this ->assertTrue ($ user4 ->wasRecentlyCreated );
1097
- }
1124
+ $ this -> assertEquals ([ ' saving ' , ' creating ' , ' created ' , ' saved ' ], $ events );
1098
1125
1099
- public function testCreateOrFirstRequiresFilter ()
1100
- {
1101
- $ this ->expectException (InvalidArgumentException::class);
1102
- $ this ->expectExceptionMessage ('You must provide attributes to check for duplicates ' );
1103
- User::createOrFirst ([]);
1126
+ if ($ transaction ) {
1127
+ $ connection ->commit ();
1128
+ }
1104
1129
}
1105
1130
1106
1131
#[TestWith([['_id ' => new ObjectID ()]])]
@@ -1116,6 +1141,8 @@ public function testUpdateOrCreate(array $criteria)
1116
1141
1117
1142
Carbon::setTestNow ('2010-01-01 ' );
1118
1143
$ createdAt = Carbon::now ()->getTimestamp ();
1144
+ $ events = [];
1145
+ self ::registerModelEvents (User::class, $ events );
1119
1146
1120
1147
// Create
1121
1148
$ user = User::updateOrCreate (
@@ -1127,11 +1154,12 @@ public function testUpdateOrCreate(array $criteria)
1127
1154
$ this ->assertEquals (new DateTime ('1987-05-28 ' ), $ user ->birthday );
1128
1155
$ this ->assertEquals ($ createdAt , $ user ->created_at ->getTimestamp ());
1129
1156
$ this ->assertEquals ($ createdAt , $ user ->updated_at ->getTimestamp ());
1130
-
1157
+ $ this -> assertEquals ([ ' saving ' , ' creating ' , ' created ' , ' saved ' ], $ events );
1131
1158
Carbon::setTestNow ('2010-02-01 ' );
1132
1159
$ updatedAt = Carbon::now ()->getTimestamp ();
1133
1160
1134
1161
// Update
1162
+ $ events = [];
1135
1163
$ user = User::updateOrCreate (
1136
1164
$ criteria ,
1137
1165
['birthday ' => new DateTime ('1990-01-12 ' ), 'foo ' => 'bar ' ],
@@ -1142,6 +1170,7 @@ public function testUpdateOrCreate(array $criteria)
1142
1170
$ this ->assertEquals (new DateTime ('1990-01-12 ' ), $ user ->birthday );
1143
1171
$ this ->assertEquals ($ createdAt , $ user ->created_at ->getTimestamp ());
1144
1172
$ this ->assertEquals ($ updatedAt , $ user ->updated_at ->getTimestamp ());
1173
+ $ this ->assertEquals (['saving ' , 'updating ' , 'updated ' , 'saved ' ], $ events );
1145
1174
1146
1175
// Stored data
1147
1176
$ checkUser = User::where ($ criteria )->first ();
@@ -1159,13 +1188,26 @@ public function testCreateWithNullId()
1159
1188
$ this ->assertSame (1 , User::count ());
1160
1189
}
1161
1190
1162
- public function testUpdateOrCreateWithNullId ()
1191
+ /** @param class-string<Model> $modelClass */
1192
+ private static function registerModelEvents (string $ modelClass , array &$ events ): void
1163
1193
{
1164
- $ this ->expectException (InvalidArgumentException::class);
1165
- $ this ->expectExceptionMessage ('You must provide attributes to check for duplicates ' );
1166
- User::updateOrCreate (
1167
- ['_id ' => null ],
1168
-
1169
- );
1194
+ $ modelClass ::creating (function () use (&$ events ) {
1195
+ $ events [] = 'creating ' ;
1196
+ });
1197
+ $ modelClass ::created (function () use (&$ events ) {
1198
+ $ events [] = 'created ' ;
1199
+ });
1200
+ $ modelClass ::updating (function () use (&$ events ) {
1201
+ $ events [] = 'updating ' ;
1202
+ });
1203
+ $ modelClass ::updated (function () use (&$ events ) {
1204
+ $ events [] = 'updated ' ;
1205
+ });
1206
+ $ modelClass ::saving (function () use (&$ events ) {
1207
+ $ events [] = 'saving ' ;
1208
+ });
1209
+ $ modelClass ::saved (function () use (&$ events ) {
1210
+ $ events [] = 'saved ' ;
1211
+ });
1170
1212
}
1171
1213
}
0 commit comments