22
33namespace Tests \Feature ;
44
5- use Tests \TestCase ;
6- use ProcessMaker \Models \User ;
75use ProcessMaker \Models \Group ;
6+ use ProcessMaker \Models \User ;
87use ProcessMaker \Package \PackageDynamicUI \Models \DynamicUI ;
98use Tests \Feature \Shared \RequestHelper ;
9+ use Tests \TestCase ;
1010
1111class HomeControllerTest extends TestCase
1212{
1313 use RequestHelper;
1414
15+ /**
16+ * Sample deep-link URL used as the "originally requested" page for the
17+ * redirect-to-intended tests.
18+ */
19+ private const INTENDED_DEEP_LINK = '/designer/scripts/123/edit ' ;
20+
1521 protected function setUp (): void
1622 {
1723 parent ::setUp ();
@@ -32,7 +38,7 @@ public function testRedirectsToLoginWhenNotAuthenticated()
3238 public function testRedirectsToCustomDashboardWhenUserHasDashboard ()
3339 {
3440 $ user = User::factory ()->create ();
35-
41+
3642 // Create a custom dashboard for the user
3743 DynamicUI::create ([
3844 'type ' => 'DASHBOARD ' ,
@@ -68,7 +74,7 @@ public function testRedirectsToCustomDashboardWhenGroupHasDashboard()
6874 public function testRedirectsToTasksOnMobileWithoutCustomDashboard ()
6975 {
7076 $ user = User::factory ()->create ();
71-
77+
7278 // Mock MobileHelper to return true
7379 $ _SERVER ['HTTP_USER_AGENT ' ] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1 ' ;
7480 $ _COOKIE ['isMobile ' ] = 'true ' ;
@@ -84,7 +90,7 @@ public function testRedirectsToTasksOnMobileWithoutCustomDashboard()
8490 public function testRedirectsToInboxOnDesktopWithoutCustomDashboard ()
8591 {
8692 $ user = User::factory ()->create ();
87-
93+
8894 // Mock MobileHelper to return false
8995 $ _SERVER ['HTTP_USER_AGENT ' ] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 ' ;
9096 $ _COOKIE ['isMobile ' ] = 'false ' ;
@@ -131,4 +137,76 @@ public function testRedirectsToGroupUrlRedirect()
131137 $ response = $ this ->actingAs ($ user )->get ('/ ' );
132138 $ response ->assertRedirect ('https://processmaker.com/home ' );
133139 }
140+
141+ /** @test */
142+ public function testRedirectToIntendedHonorsCookie ()
143+ {
144+ $ user = User::factory ()->create ();
145+ $ response = $ this ->actingAs ($ user )
146+ ->withCookie ('processmaker_intended ' , self ::INTENDED_DEEP_LINK )
147+ ->get (route ('redirect_to_intended ' ));
148+ $ response ->assertRedirect (self ::INTENDED_DEEP_LINK );
149+ }
150+
151+ /**
152+ * Regression test for the SAML "land on home instead of intended URL"
153+ * bug: when the user comes back from the SSO callback through the
154+ * /redirect-to-intended recovery hop with a valid `processmaker_intended`
155+ * cookie, the cookie wins -- the configured Dynamic UI home page does
156+ * not preempt it.
157+ *
158+ * @test
159+ */
160+ public function testRedirectToIntendedCookieTakesPrecedenceOverDynamicUiHome ()
161+ {
162+ $ user = User::factory ()->create ();
163+
164+ DynamicUI::create ([
165+ 'type ' => 'URL ' ,
166+ 'assignable_id ' => $ user ->id ,
167+ 'assignable_type ' => User::class,
168+ 'homepage ' => 'https://processmaker.com/configured-landing ' ,
169+ ]);
170+
171+ $ response = $ this ->actingAs ($ user )
172+ ->withCookie ('processmaker_intended ' , self ::INTENDED_DEEP_LINK )
173+ ->get (route ('redirect_to_intended ' ));
174+
175+ $ response ->assertRedirect (self ::INTENDED_DEEP_LINK );
176+ }
177+
178+ /**
179+ * The intended-URL cookie is single-use: once we've consumed it we must
180+ * tell the browser to drop it, otherwise it would keep deflecting every
181+ * subsequent SSO callback to the same stale URL.
182+ *
183+ * @test
184+ */
185+ public function testRedirectToIntendedClearsCookieAfterUse ()
186+ {
187+ $ user = User::factory ()->create ();
188+
189+ $ response = $ this ->actingAs ($ user )
190+ ->withCookie ('processmaker_intended ' , self ::INTENDED_DEEP_LINK )
191+ ->get (route ('redirect_to_intended ' ));
192+
193+ $ response ->assertRedirect (self ::INTENDED_DEEP_LINK );
194+ $ response ->assertCookieExpired ('processmaker_intended ' );
195+ }
196+
197+ /**
198+ * When there's no intended URL at all we still need to send the user somewhere.
199+ * With no dashboard configured, DynamicUI::getHomePage() falls through to route('home')
200+ * which HomeController::index() will then re-route to /inbox (or /tasks on mobile) on the next request.
201+ *
202+ * @test
203+ */
204+ public function testRedirectToIntendedFallsBackToHomeWhenNoCookieAndNoDashboard ()
205+ {
206+ $ user = User::factory ()->create ();
207+
208+ $ response = $ this ->actingAs ($ user )->get (route ('redirect_to_intended ' ));
209+
210+ $ response ->assertRedirect (route ('home ' ));
211+ }
134212}
0 commit comments