@@ -242,6 +242,70 @@ public function testGenerateResponse_executesComponentAndPageLogicAndAppliesHead
242242 self ::assertSame ([], $ invocations [4 ]["extraArgs " ]);
243243 }
244244
245+ public function testGenerateResponse_componentFormDoActionDoesNotRunPageDoAction ():void {
246+ $ html = <<<HTML
247+ <!doctype html>
248+ <body>
249+ <form method="post"><button name="do" value="save-item">Save</button></form>
250+ <widget-one>
251+ <form method="post">
252+ <input type="hidden" name="__component" value="widget-one">
253+ <button name="do" value="save-item">Save</button>
254+ </form>
255+ </widget-one>
256+ </body>
257+ HTML ;
258+
259+ $ viewModel = new HTMLDocument ($ html );
260+ $ component = $ viewModel ->querySelector ("widget-one " );
261+ self ::assertInstanceOf (Element::class, $ component );
262+
263+ $ componentAssembly = $ this ->createAssembly ("/tmp/component.php " );
264+ $ componentList = new LogicAssemblyComponentList ();
265+ $ componentList ->addAssemblyComponent ($ componentAssembly , $ component );
266+
267+ $ processor = $ this ->createMock (ViewModelProcessor::class);
268+ $ processor ->method ("processDynamicPath " );
269+ $ processor ->method ("processPartialContent " )
270+ ->willReturn ($ componentList );
271+
272+ $ invocations = [];
273+ $ logicAssembly = $ this ->createAssembly ("/tmp/page.php " );
274+ $ logicExecutor = $ this ->createMock (LogicExecutor::class);
275+ $ logicExecutor ->method ("invoke " )
276+ ->willReturnCallback (function (Assembly $ assembly , string $ name )use (&$ invocations , $ componentAssembly ):\Generator {
277+ $ invocations [] = [
278+ "assembly " => $ assembly === $ componentAssembly ? "component " : "page " ,
279+ "name " => $ name ,
280+ ];
281+ yield ($ assembly === $ componentAssembly ? "/tmp/component.php " : "/tmp/page.php " ) . ":: $ name() " ;
282+ });
283+
284+ $ sut = $ this ->createDispatcher (
285+ input: new Input ([], [
286+ "__component " => "widget-one " ,
287+ "do " => "save-item " ,
288+ ]),
289+ viewModel: $ viewModel ,
290+ logicAssembly: $ logicAssembly ,
291+ viewModelInit: $ this ->createViewModelInit ($ processor , true ),
292+ logicExecutor: $ logicExecutor ,
293+ );
294+
295+ $ response = $ sut ->generateResponse ();
296+
297+ self ::assertSame (StatusCode::OK , $ response ->getStatusCode ());
298+ self ::assertSame ([
299+ ["assembly " => "component " , "name " => "go_before " ],
300+ ["assembly " => "component " , "name " => "do_save_item " ],
301+ ["assembly " => "component " , "name " => "go " ],
302+ ["assembly " => "component " , "name " => "go_after " ],
303+ ["assembly " => "page " , "name " => "go_before " ],
304+ ["assembly " => "page " , "name " => "go " ],
305+ ["assembly " => "page " , "name " => "go_after " ],
306+ ], $ invocations );
307+ }
308+
245309 public function testProcessResponse_rethrowsComponentThrowableOutsideErrorMode ():void {
246310 $ viewModel = new HTMLDocument ('<!doctype html><body><widget-one data-element="widget-one"></widget-one></body> ' );
247311 $ component = $ viewModel ->querySelector ("widget-one " );
0 commit comments