66
77use Drupal \Core \Config \ConfigFactoryInterface ;
88use Drupal \Core \Extension \ModuleHandlerInterface ;
9+ use Drupal \Core \Language \LanguageInterface ;
910use Drupal \Core \Language \LanguageManagerInterface ;
1011use Drupal \Core \Path \PathValidatorInterface ;
1112use Drupal \Core \Url ;
1213use Drupal \jsonapi_frontend \Service \PathResolverInterface ;
1314use Drupal \jsonapi_frontend_webform \Service \WebformPathResolver ;
1415use Drupal \path_alias \AliasManagerInterface ;
1516use PHPUnit \Framework \TestCase ;
17+ use Symfony \Component \HttpFoundation \Request ;
1618use Symfony \Component \HttpFoundation \RequestStack ;
1719
1820/**
@@ -36,6 +38,21 @@ private function notFound(): array {
3638 ];
3739 }
3840
41+ private function createConfigFactory (array $ values ): ConfigFactoryInterface {
42+ $ config = new class ($ values ) {
43+ public function __construct (private readonly array $ values ) {}
44+
45+ public function get (string $ key ): mixed {
46+ return $ this ->values [$ key ] ?? NULL ;
47+ }
48+ };
49+
50+ $ factory = $ this ->createMock (ConfigFactoryInterface::class);
51+ $ factory ->method ('get ' )->with ('jsonapi_frontend.settings ' )->willReturn ($ config );
52+
53+ return $ factory ;
54+ }
55+
3956 public function testReturnsInnerResultWhenAlreadyResolved (): void {
4057 $ inner = $ this ->createMock (PathResolverInterface::class);
4158 $ inner ->expects (self ::once ())
@@ -88,6 +105,286 @@ public function testNoWebformModuleReturnsInnerResult(): void {
88105 $ this ->assertFalse ($ result ['resolved ' ]);
89106 }
90107
108+ public function testReturnsInnerResultWhenPathTooLong (): void {
109+ $ inner = $ this ->createMock (PathResolverInterface::class);
110+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
111+
112+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
113+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
114+
115+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
116+ $ alias_manager ->expects (self ::never ())->method ('getPathByAlias ' );
117+
118+ $ resolver = new WebformPathResolver (
119+ $ inner ,
120+ $ alias_manager ,
121+ $ this ->createMock (PathValidatorInterface::class),
122+ $ this ->createMock (LanguageManagerInterface::class),
123+ $ module_handler ,
124+ $ this ->createMock (ConfigFactoryInterface::class),
125+ $ this ->createMock (RequestStack::class),
126+ );
127+
128+ $ result = $ resolver ->resolve (str_repeat ('a ' , 2050 ), 'en ' );
129+ $ this ->assertFalse ($ result ['resolved ' ]);
130+ }
131+
132+ public function testResolvesWebformRouteUsingSiteDefaultLanguageFallbackAndRequestBaseUrl (): void {
133+ $ inner = $ this ->createMock (PathResolverInterface::class);
134+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
135+
136+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
137+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
138+
139+ $ language = $ this ->createMock (LanguageInterface::class);
140+ $ language ->method ('getId ' )->willReturn ('en ' );
141+
142+ $ language_manager = $ this ->createMock (LanguageManagerInterface::class);
143+ $ language_manager ->expects (self ::once ())->method ('getDefaultLanguage ' )->willReturn ($ language );
144+
145+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
146+ $ alias_manager ->expects (self ::once ())
147+ ->method ('getPathByAlias ' )
148+ ->with ('/contact ' , 'en ' )
149+ ->willReturn ('/form/contact ' );
150+ $ alias_manager ->expects (self ::once ())
151+ ->method ('getAliasByPath ' )
152+ ->with ('/form/contact ' , 'en ' )
153+ ->willReturn ('' );
154+
155+ $ url = $ this ->createMock (Url::class);
156+ $ url ->method ('access ' )->willReturn (TRUE );
157+
158+ $ path_validator = $ this ->createMock (PathValidatorInterface::class);
159+ $ path_validator ->expects (self ::once ())->method ('getUrlIfValid ' )->with ('/form/contact ' )->willReturn ($ url );
160+
161+ $ config_factory = $ this ->createConfigFactory ([
162+ 'resolver.langcode_fallback ' => 'site_default ' ,
163+ 'drupal_base_url ' => '' ,
164+ ]);
165+
166+ $ request_stack = $ this ->createMock (RequestStack::class);
167+ $ request_stack ->method ('getCurrentRequest ' )->willReturn (Request::create ('https://cms.example.com ' ));
168+
169+ $ resolver = new WebformPathResolver (
170+ $ inner ,
171+ $ alias_manager ,
172+ $ path_validator ,
173+ $ language_manager ,
174+ $ module_handler ,
175+ $ config_factory ,
176+ $ request_stack ,
177+ );
178+
179+ $ result = $ resolver ->resolve ('contact/?utm=1#frag ' );
180+
181+ $ this ->assertTrue ($ result ['resolved ' ]);
182+ $ this ->assertSame ('route ' , $ result ['kind ' ]);
183+ $ this ->assertSame ('/contact ' , $ result ['canonical ' ]);
184+ $ this ->assertSame ('https://cms.example.com/contact ' , $ result ['drupal_url ' ]);
185+ }
186+
187+ public function testResolvesWebformRouteUsingCurrentLanguageFallback (): void {
188+ $ inner = $ this ->createMock (PathResolverInterface::class);
189+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
190+
191+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
192+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
193+
194+ $ language = $ this ->createMock (LanguageInterface::class);
195+ $ language ->method ('getId ' )->willReturn ('fr ' );
196+
197+ $ language_manager = $ this ->createMock (LanguageManagerInterface::class);
198+ $ language_manager ->expects (self ::once ())
199+ ->method ('getCurrentLanguage ' )
200+ ->with (LanguageInterface::TYPE_CONTENT )
201+ ->willReturn ($ language );
202+
203+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
204+ $ alias_manager ->expects (self ::once ())
205+ ->method ('getPathByAlias ' )
206+ ->with ('/contact ' , 'fr ' )
207+ ->willReturn ('/form/contact ' );
208+ $ alias_manager ->expects (self ::once ())
209+ ->method ('getAliasByPath ' )
210+ ->with ('/form/contact ' , 'fr ' )
211+ ->willReturn ('/contact ' );
212+
213+ $ url = $ this ->createMock (Url::class);
214+ $ url ->method ('access ' )->willReturn (TRUE );
215+
216+ $ path_validator = $ this ->createMock (PathValidatorInterface::class);
217+ $ path_validator ->expects (self ::once ())->method ('getUrlIfValid ' )->with ('/form/contact ' )->willReturn ($ url );
218+
219+ $ config_factory = $ this ->createConfigFactory ([
220+ 'resolver.langcode_fallback ' => 'current ' ,
221+ 'drupal_base_url ' => 'https://cms.example.com ' ,
222+ ]);
223+
224+ $ resolver = new WebformPathResolver (
225+ $ inner ,
226+ $ alias_manager ,
227+ $ path_validator ,
228+ $ language_manager ,
229+ $ module_handler ,
230+ $ config_factory ,
231+ $ this ->createMock (RequestStack::class),
232+ );
233+
234+ $ result = $ resolver ->resolve ('/contact ' );
235+
236+ $ this ->assertTrue ($ result ['resolved ' ]);
237+ $ this ->assertSame ('/contact ' , $ result ['canonical ' ]);
238+ }
239+
240+ public function testReturnsInnerResultWhenInternalPathIsNotAWebformRoute (): void {
241+ $ inner = $ this ->createMock (PathResolverInterface::class);
242+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
243+
244+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
245+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
246+
247+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
248+ $ alias_manager ->expects (self ::once ())->method ('getPathByAlias ' )->with ('/contact ' , 'en ' )->willReturn ('/node/1 ' );
249+ $ alias_manager ->expects (self ::never ())->method ('getAliasByPath ' );
250+
251+ $ path_validator = $ this ->createMock (PathValidatorInterface::class);
252+ $ path_validator ->expects (self ::never ())->method ('getUrlIfValid ' );
253+
254+ $ resolver = new WebformPathResolver (
255+ $ inner ,
256+ $ alias_manager ,
257+ $ path_validator ,
258+ $ this ->createMock (LanguageManagerInterface::class),
259+ $ module_handler ,
260+ $ this ->createConfigFactory ([]),
261+ $ this ->createMock (RequestStack::class),
262+ );
263+
264+ $ result = $ resolver ->resolve ('/contact ' , 'en ' );
265+ $ this ->assertFalse ($ result ['resolved ' ]);
266+ }
267+
268+ public function testReturnsInnerResultWhenAliasResolutionFails (): void {
269+ $ inner = $ this ->createMock (PathResolverInterface::class);
270+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
271+
272+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
273+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
274+
275+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
276+ $ alias_manager ->expects (self ::once ())->method ('getPathByAlias ' )->willReturn (NULL );
277+
278+ $ resolver = new WebformPathResolver (
279+ $ inner ,
280+ $ alias_manager ,
281+ $ this ->createMock (PathValidatorInterface::class),
282+ $ this ->createMock (LanguageManagerInterface::class),
283+ $ module_handler ,
284+ $ this ->createConfigFactory ([]),
285+ $ this ->createMock (RequestStack::class),
286+ );
287+
288+ $ result = $ resolver ->resolve ('/contact ' , 'en ' );
289+ $ this ->assertFalse ($ result ['resolved ' ]);
290+ }
291+
292+ public function testReturnsInnerResultWhenUrlIsInvalid (): void {
293+ $ inner = $ this ->createMock (PathResolverInterface::class);
294+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
295+
296+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
297+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
298+
299+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
300+ $ alias_manager ->method ('getPathByAlias ' )->with ('/contact ' , 'en ' )->willReturn ('/form/contact ' );
301+
302+ $ path_validator = $ this ->createMock (PathValidatorInterface::class);
303+ $ path_validator ->method ('getUrlIfValid ' )->with ('/form/contact ' )->willReturn (NULL );
304+
305+ $ resolver = new WebformPathResolver (
306+ $ inner ,
307+ $ alias_manager ,
308+ $ path_validator ,
309+ $ this ->createMock (LanguageManagerInterface::class),
310+ $ module_handler ,
311+ $ this ->createConfigFactory ([]),
312+ $ this ->createMock (RequestStack::class),
313+ );
314+
315+ $ result = $ resolver ->resolve ('/contact ' , 'en ' );
316+ $ this ->assertFalse ($ result ['resolved ' ]);
317+ }
318+
319+ public function testReturnsInnerResultWhenAccessDenied (): void {
320+ $ inner = $ this ->createMock (PathResolverInterface::class);
321+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
322+
323+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
324+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
325+
326+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
327+ $ alias_manager ->method ('getPathByAlias ' )->with ('/contact ' , 'en ' )->willReturn ('/form/contact ' );
328+
329+ $ url = $ this ->createMock (Url::class);
330+ $ url ->method ('access ' )->willReturn (FALSE );
331+
332+ $ path_validator = $ this ->createMock (PathValidatorInterface::class);
333+ $ path_validator ->method ('getUrlIfValid ' )->with ('/form/contact ' )->willReturn ($ url );
334+
335+ $ resolver = new WebformPathResolver (
336+ $ inner ,
337+ $ alias_manager ,
338+ $ path_validator ,
339+ $ this ->createMock (LanguageManagerInterface::class),
340+ $ module_handler ,
341+ $ this ->createConfigFactory ([]),
342+ $ this ->createMock (RequestStack::class),
343+ );
344+
345+ $ result = $ resolver ->resolve ('/contact ' , 'en ' );
346+ $ this ->assertFalse ($ result ['resolved ' ]);
347+ }
348+
349+ public function testDrupalUrlFallsBackToPathWhenNoConfiguredBaseUrlAndNoRequest (): void {
350+ $ inner = $ this ->createMock (PathResolverInterface::class);
351+ $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
352+
353+ $ module_handler = $ this ->createMock (ModuleHandlerInterface::class);
354+ $ module_handler ->method ('moduleExists ' )->with ('webform ' )->willReturn (TRUE );
355+
356+ $ alias_manager = $ this ->createMock (AliasManagerInterface::class);
357+ $ alias_manager ->method ('getPathByAlias ' )->with ('/contact ' , 'en ' )->willReturn ('/form/contact ' );
358+ $ alias_manager ->method ('getAliasByPath ' )->with ('/form/contact ' , 'en ' )->willReturn ('/contact ' );
359+
360+ $ url = $ this ->createMock (Url::class);
361+ $ url ->method ('access ' )->willReturn (TRUE );
362+
363+ $ path_validator = $ this ->createMock (PathValidatorInterface::class);
364+ $ path_validator ->method ('getUrlIfValid ' )->with ('/form/contact ' )->willReturn ($ url );
365+
366+ $ config_factory = $ this ->createConfigFactory ([
367+ 'drupal_base_url ' => '' ,
368+ ]);
369+
370+ $ request_stack = $ this ->createMock (RequestStack::class);
371+ $ request_stack ->method ('getCurrentRequest ' )->willReturn (NULL );
372+
373+ $ resolver = new WebformPathResolver (
374+ $ inner ,
375+ $ alias_manager ,
376+ $ path_validator ,
377+ $ this ->createMock (LanguageManagerInterface::class),
378+ $ module_handler ,
379+ $ config_factory ,
380+ $ request_stack ,
381+ );
382+
383+ $ result = $ resolver ->resolve ('/contact ' , 'en ' );
384+ $ this ->assertTrue ($ result ['resolved ' ]);
385+ $ this ->assertSame ('/contact ' , $ result ['drupal_url ' ]);
386+ }
387+
91388 public function testResolvesWebformRouteFromAlias (): void {
92389 $ inner = $ this ->createMock (PathResolverInterface::class);
93390 $ inner ->expects (self ::once ())->method ('resolve ' )->willReturn ($ this ->notFound ());
@@ -137,4 +434,3 @@ public function get(string $key): mixed {
137434 }
138435
139436}
140-
0 commit comments