Skip to content

Commit 80d800d

Browse files
authored
Merge pull request #7692 from ProcessMaker/FOUR-19974
FOUR-19974 Fixes and performance updates for cases_started and cases_participated migrations
2 parents 34d4648 + 1c9301a commit 80d800d

File tree

4 files changed

+1242
-208
lines changed

4 files changed

+1242
-208
lines changed
Lines changed: 396 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,396 @@
1+
<?php
2+
3+
namespace Tests\Upgrades;
4+
5+
use Illuminate\Foundation\Testing\RefreshDatabase;
6+
use Illuminate\Support\Facades\DB;
7+
use PopulateCaseStarted;
8+
use ProcessMaker\Models\Process;
9+
use ProcessMaker\Models\ProcessRequest;
10+
use ProcessMaker\Models\ProcessRequestToken;
11+
use ProcessMaker\Models\User;
12+
use Tests\TestCase;
13+
14+
class PopulateCaseStartedTest extends TestCase
15+
{
16+
use RefreshDatabase;
17+
18+
protected function setUp(): void
19+
{
20+
require_once base_path('upgrades/2024_10_09_032151_populate_case_started.php');
21+
parent::setUp();
22+
}
23+
24+
protected function tearDown(): void
25+
{
26+
// Drop temporary tables and reset any specific configurations
27+
DB::statement('DROP TEMPORARY TABLE IF EXISTS process_requests_temp');
28+
DB::statement('DROP TEMPORARY TABLE IF EXISTS process_request_tokens_tmp');
29+
DB::table('cases_started')->delete();
30+
parent::tearDown();
31+
}
32+
33+
public function testUp()
34+
{
35+
// Instantiate PopulateCaseStarted
36+
$populateCaseStarted = new PopulateCaseStarted();
37+
38+
// Confirm initial empty state of cases_started table
39+
$initialCount = DB::table('cases_started')->count();
40+
$this->assertEquals(0, $initialCount, 'cases_started should be empty before migration');
41+
42+
// Create sample ProcessRequests with related data
43+
$processRequests = ProcessRequest::factory()->count(5)->create();
44+
45+
// Run the migration
46+
$populateCaseStarted->up();
47+
48+
// Confirm record insertion into cases_started
49+
$finalCount = DB::table('cases_started')->count();
50+
$this->assertEquals($processRequests->count(), $finalCount, 'cases_started count should match the number of ProcessRequests created');
51+
52+
foreach ($processRequests as $processRequest) {
53+
$casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest->case_number)->first();
54+
$this->assertNotNull($casesStartedRecord, 'Each ProcessRequest should have a corresponding record in cases_started');
55+
56+
// Validate field mapping and transformations
57+
$this->assertSame($processRequest->user_id, $casesStartedRecord->user_id);
58+
$this->assertSame($processRequest->case_number, $casesStartedRecord->case_number);
59+
$this->assertSame($processRequest->case_title, $casesStartedRecord->case_title);
60+
$this->assertSame($processRequest->case_title_formatted, $casesStartedRecord->case_title_formatted);
61+
$this->assertSame($this->mapStatus($processRequest->status), $casesStartedRecord->case_status);
62+
$this->assertEquals($processRequest->initiated_at, $casesStartedRecord->initiated_at);
63+
$this->assertEquals($processRequest->completed_at, $casesStartedRecord->completed_at);
64+
$this->assertEquals($processRequest->created_at, $casesStartedRecord->created_at);
65+
$this->assertEquals($processRequest->updated_at, $casesStartedRecord->updated_at);
66+
}
67+
}
68+
69+
public function testTokensColumn()
70+
{
71+
// Instantiate PopulateCaseStarted
72+
$populateCaseStarted = new PopulateCaseStarted();
73+
74+
// Confirm initial empty state of cases_started table
75+
$initialCount = DB::table('cases_started')->count();
76+
$this->assertEquals(0, $initialCount, 'cases_started should be empty before migration');
77+
78+
// Create user
79+
$user = User::factory()->create();
80+
$this->actingAs($user);
81+
// Create sample ProcessRequests with related data
82+
$processRequests = ProcessRequest::factory()->count(5)->create([
83+
'user_id' => $user->id,
84+
]);
85+
// Get the ID of the first process request to use as the shared process_request_id
86+
$processRequest = $processRequests->first();
87+
ProcessRequestToken::factory()->create([
88+
'process_request_id' => $processRequest->id,
89+
'element_type' => 'startEvent',
90+
]);
91+
$processRequestTokens = ProcessRequestToken::factory()->count(3)->create([
92+
'process_request_id' => $processRequest->id,
93+
'element_type' => 'task',
94+
]);
95+
$processRequestTokenIds = $processRequestTokens->pluck('id')->toArray();
96+
// Run the migration
97+
$populateCaseStarted->up();
98+
99+
// Confirm record insertion into cases_started
100+
$finalCount = DB::table('cases_started')->count();
101+
$this->assertEquals($processRequests->count(), $finalCount, 'cases_started count should match the number of ProcessRequests created');
102+
$casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest->case_number)->first();
103+
$this->assertNotNull($casesStartedRecord, 'Each ProcessRequest should have a corresponding record in cases_started');
104+
105+
$tokensArray = json_decode($casesStartedRecord->request_tokens, true);
106+
$this->assertEqualsCanonicalizing($tokensArray, $processRequestTokenIds);
107+
}
108+
109+
public function testParticipatedColumn()
110+
{
111+
// Instantiate PopulateCaseStarted
112+
$populateCaseStarted = new PopulateCaseStarted();
113+
114+
// Confirm initial empty state of cases_started table
115+
$initialCount = DB::table('cases_started')->count();
116+
$this->assertEquals(0, $initialCount, 'cases_started should be empty before migration');
117+
118+
// Create first user
119+
$user1 = User::factory()->create();
120+
$this->actingAs($user1);
121+
// Create second user
122+
$user2 = User::factory()->create();
123+
$this->actingAs($user2);
124+
125+
// Create sample ProcessRequests with related data
126+
$processRequests = ProcessRequest::factory()->create([
127+
'user_id' => $user1->id,
128+
]);
129+
$processRequests = ProcessRequest::factory()->create([
130+
'user_id' => $user2->id,
131+
]);
132+
// Get the ID of the first process request to use as the shared process_request_id
133+
$processRequest = $processRequests->first();
134+
135+
// Create ProcessRequestTokens for processRequest
136+
ProcessRequestToken::factory()->create([
137+
'process_request_id' => $processRequest->id,
138+
'element_type' => 'startEvent',
139+
'user_id' => $user1->id,
140+
]);
141+
ProcessRequestToken::factory()->count(2)->create([
142+
'process_request_id' => $processRequest->id,
143+
'element_type' => 'task',
144+
'user_id' => $user1->id,
145+
]);
146+
ProcessRequestToken::factory()->count(2)->create([
147+
'process_request_id' => $processRequest->id,
148+
'element_type' => 'task',
149+
'user_id' => $user2->id,
150+
]);
151+
$processRequestTokens = DB::table('process_request_tokens')->where('process_request_id', $processRequest->id);
152+
$participantIds = $processRequestTokens->pluck('user_id')->toArray();
153+
$uniqueParticipantIds = array_unique($participantIds);
154+
// Run the migration
155+
$populateCaseStarted->up();
156+
157+
// Confirm record insertion into cases_started
158+
$finalCount = DB::table('cases_started')->count();
159+
$this->assertEquals($processRequests->count(), $finalCount, 'cases_started count should match the number of ProcessRequests created');
160+
$casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest->case_number)->first();
161+
$this->assertNotNull($casesStartedRecord, 'Each ProcessRequest should have a corresponding record in cases_started');
162+
// Prepare the participants record
163+
$tokensArray = json_decode($casesStartedRecord->participants, true);
164+
// Assert both arrays contain the same items in any order
165+
$this->assertEqualsCanonicalizing($tokensArray, $uniqueParticipantIds);
166+
}
167+
168+
public function testCasesStartedProcessColumn()
169+
{
170+
// Instantiate the migration class
171+
$populateCaseStarted = new PopulateCaseStarted();
172+
173+
// Confirm the initial state of the `cases_started` table
174+
$initialCount = DB::table('cases_started')->count();
175+
$this->assertEquals(0, $initialCount, 'cases_started table should be empty before migration');
176+
177+
// Create test users
178+
$user1 = User::factory()->create();
179+
$user2 = User::factory()->create();
180+
// Create test processes
181+
$process1 = Process::factory()->create();
182+
$process2 = Process::factory()->create();
183+
// Create sample ProcessRequests for both users
184+
$processRequest1 = ProcessRequest::factory()->create([
185+
'user_id' => $user1->id,
186+
'name' => $process1->name,
187+
'process_id' => $process1->id,
188+
]);
189+
$processRequest2 = ProcessRequest::factory()->create([
190+
'user_id' => $user2->id,
191+
'parent_request_id' => $processRequest1->id,
192+
'name' => $process2->name,
193+
'process_id' => $process2->id,
194+
]);
195+
196+
// Create ProcessRequestTokens for processRequest1
197+
ProcessRequestToken::factory()->create([
198+
'process_request_id' => $processRequest1->id,
199+
'process_id' => $processRequest1->process_id,
200+
'element_type' => 'startEvent',
201+
'status' => 'TRIGGERED',
202+
'element_id' => 'node_1',
203+
'user_id' => $user1->id,
204+
]);
205+
ProcessRequestToken::factory()->create([
206+
'process_request_id' => $processRequest1->id,
207+
'process_id' => $processRequest1->process_id,
208+
'element_type' => 'callActivity',
209+
'status' => 'CLOSED',
210+
'element_id' => 'node_51',
211+
'user_id' => $user1->id,
212+
'subprocess_request_id' => $processRequest2->id,
213+
]);
214+
ProcessRequestToken::factory()->create([
215+
'process_request_id' => $processRequest1->id,
216+
'process_id' => $processRequest1->process_id,
217+
'element_type' => 'task',
218+
'status' => 'ACTIVE',
219+
'element_id' => 'node_12',
220+
'user_id' => $user1->id,
221+
]);
222+
223+
// Create ProcessRequestTokens for processRequest2
224+
ProcessRequestToken::factory()->create([
225+
'process_request_id' => $processRequest2->id,
226+
'process_id' => $processRequest2->process_id,
227+
'element_type' => 'startEvent',
228+
'status' => 'TRIGGERED',
229+
'element_id' => 'node_1',
230+
'user_id' => $user1->id,
231+
]);
232+
ProcessRequestToken::factory()->create([
233+
'process_request_id' => $processRequest2->id,
234+
'process_id' => $processRequest2->process_id,
235+
'element_type' => 'task',
236+
'status' => 'CLOSED',
237+
'element_id' => 'node_2',
238+
'user_id' => $user1->id,
239+
]);
240+
ProcessRequestToken::factory()->create([
241+
'process_request_id' => $processRequest2->id,
242+
'process_id' => $processRequest2->process_id,
243+
'element_type' => 'task',
244+
'status' => 'CLOSED',
245+
'element_id' => 'node_12',
246+
'user_id' => $user1->id,
247+
]);
248+
ProcessRequestToken::factory()->create([
249+
'process_request_id' => $processRequest2->id,
250+
'process_id' => $processRequest2->process_id,
251+
'element_type' => 'end_event',
252+
'status' => 'CLOSED',
253+
'element_id' => 'node_25',
254+
'user_id' => null,
255+
]);
256+
257+
// Run the migration
258+
$populateCaseStarted->up();
259+
260+
// Validate that the ProcessRequest1 has a corresponding entry in `cases_started`
261+
$casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest1->case_number)->first();
262+
$this->assertNotNull($casesStartedRecord, 'ProcessRequest should have a corresponding record in cases_started');
263+
264+
// Expected data structure for `cases_started.processes` column
265+
$expectedData = [
266+
(object) ['id' => $processRequest1->process_id, 'name' => $processRequest1->name],
267+
(object) ['id' => $processRequest2->process_id, 'name' => $processRequest2->name],
268+
];
269+
270+
// Decode the JSON data from `cases_started.processes`
271+
$processesArray = json_decode($casesStartedRecord->processes);
272+
273+
// Assert both arrays contain the same items in any order
274+
$this->assertEqualsCanonicalizing($expectedData, $processesArray, 'The processes data in cases_started should match the expected data');
275+
}
276+
277+
public function testCasesStartedRequestsColumn()
278+
{
279+
// Instantiate the migration class
280+
$populateCaseStarted = new PopulateCaseStarted();
281+
282+
// Confirm the initial state of the `cases_started` table
283+
$initialCount = DB::table('cases_started')->count();
284+
$this->assertEquals(0, $initialCount, 'cases_started table should be empty before migration');
285+
286+
// Create test users
287+
$user1 = User::factory()->create();
288+
$user2 = User::factory()->create();
289+
// Create test processes
290+
$process1 = Process::factory()->create();
291+
$process2 = Process::factory()->create();
292+
// Create sample ProcessRequests for both users
293+
$processRequest1 = ProcessRequest::factory()->create([
294+
'user_id' => $user1->id,
295+
'name' => $process1->name,
296+
'process_id' => $process1->id,
297+
]);
298+
$processRequest2 = ProcessRequest::factory()->create([
299+
'user_id' => $user2->id,
300+
'parent_request_id' => $processRequest1->id,
301+
'name' => $process2->name,
302+
'process_id' => $process2->id,
303+
]);
304+
305+
// Create ProcessRequestTokens for processRequest1
306+
ProcessRequestToken::factory()->create([
307+
'process_request_id' => $processRequest1->id,
308+
'process_id' => $processRequest1->process_id,
309+
'element_type' => 'startEvent',
310+
'status' => 'TRIGGERED',
311+
'element_id' => 'node_1',
312+
'user_id' => $user1->id,
313+
]);
314+
ProcessRequestToken::factory()->create([
315+
'process_request_id' => $processRequest1->id,
316+
'process_id' => $processRequest1->process_id,
317+
'element_type' => 'callActivity',
318+
'status' => 'CLOSED',
319+
'element_id' => 'node_51',
320+
'user_id' => $user1->id,
321+
'subprocess_request_id' => $processRequest2->id,
322+
]);
323+
ProcessRequestToken::factory()->create([
324+
'process_request_id' => $processRequest1->id,
325+
'process_id' => $processRequest1->process_id,
326+
'element_type' => 'task',
327+
'status' => 'ACTIVE',
328+
'element_id' => 'node_12',
329+
'user_id' => $user1->id,
330+
]);
331+
332+
// Create ProcessRequestTokens for processRequest2
333+
ProcessRequestToken::factory()->create([
334+
'process_request_id' => $processRequest2->id,
335+
'process_id' => $processRequest2->process_id,
336+
'element_type' => 'startEvent',
337+
'status' => 'TRIGGERED',
338+
'element_id' => 'node_1',
339+
'user_id' => $user1->id,
340+
]);
341+
ProcessRequestToken::factory()->create([
342+
'process_request_id' => $processRequest2->id,
343+
'process_id' => $processRequest2->process_id,
344+
'element_type' => 'task',
345+
'status' => 'CLOSED',
346+
'element_id' => 'node_2',
347+
'user_id' => $user1->id,
348+
]);
349+
ProcessRequestToken::factory()->create([
350+
'process_request_id' => $processRequest2->id,
351+
'process_id' => $processRequest2->process_id,
352+
'element_type' => 'task',
353+
'status' => 'CLOSED',
354+
'element_id' => 'node_12',
355+
'user_id' => $user1->id,
356+
]);
357+
ProcessRequestToken::factory()->create([
358+
'process_request_id' => $processRequest2->id,
359+
'process_id' => $processRequest2->process_id,
360+
'element_type' => 'end_event',
361+
'status' => 'CLOSED',
362+
'element_id' => 'node_25',
363+
'user_id' => null,
364+
]);
365+
366+
// Run the migration
367+
$populateCaseStarted->up();
368+
369+
// Validate that the ProcessRequest1 has a corresponding entry in `cases_started`
370+
$casesStartedRecord = DB::table('cases_started')->where('case_number', $processRequest1->case_number)->first();
371+
$this->assertNotNull($casesStartedRecord, 'ProcessRequest should have a corresponding record in cases_started');
372+
373+
// Expected data structure for `cases_started.processes` column
374+
$expectedData = [
375+
(object) ['id' => $processRequest1->id, 'name' => $processRequest1->name, 'parent_request_id' => $processRequest1->parent_request_id],
376+
(object) ['id' => $processRequest2->id, 'name' => $processRequest2->name, 'parent_request_id' => $processRequest2->parent_request_id],
377+
];
378+
379+
// Decode the JSON data from `cases_started.requests`
380+
$requestsArray = json_decode($casesStartedRecord->requests);
381+
382+
// Assert both arrays contain the same items in any order
383+
$this->assertEqualsCanonicalizing($expectedData, $requestsArray, 'The requests data in cases_started should match the expected data');
384+
}
385+
386+
/**
387+
* Helper function to map ProcessRequest status to cases_started status
388+
*
389+
* @param string $status ProcessRequest status
390+
* @return string cases_started status
391+
*/
392+
private function mapStatus($status)
393+
{
394+
return $status === 'ACTIVE' ? 'IN_PROGRESS' : $status;
395+
}
396+
}

0 commit comments

Comments
 (0)