@@ -11,6 +11,14 @@ const createForm = (html: string) => {
1111 return form ;
1212} ;
1313
14+ const appendToBody = < T extends Element = HTMLElement > ( html : string ) => {
15+ const wrapper = document . createElement ( 'div' ) ;
16+ wrapper . innerHTML = html ;
17+ const el = wrapper . firstElementChild as T ;
18+ document . body . appendChild ( el ) ;
19+ return el ;
20+ } ;
21+
1422const submitForm = ( form : HTMLFormElement , submitter ?: HTMLButtonElement | null , key ?: string ) => {
1523 if ( key ) {
1624 document . dispatchEvent ( new KeyboardEvent ( 'keydown' , { key } ) ) ;
@@ -45,6 +53,7 @@ describe('SwupFormsPlugin', () => {
4553 afterEach ( ( ) => {
4654 swup . unuse ( plugin ) ;
4755 swup . destroy ( ) ;
56+ document . body . innerHTML = '' ;
4857 } ) ;
4958
5059 it ( 'does not call beforeFormSubmit for ignored forms' , async ( ) => {
@@ -79,6 +88,52 @@ describe('SwupFormsPlugin', () => {
7988 expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { submitter } ) ) ;
8089 } ) ;
8190
91+ it ( 'calls beforeFormSubmit for an externally associated submit button' , async ( ) => {
92+ const spy = vitest . spyOn ( plugin , 'beforeFormSubmit' ) . mockImplementation ( ( ) => { } ) ;
93+ swup . use ( plugin ) ;
94+
95+ const form = createForm ( '<form id="ext-form" action="/path" data-swup-form></form>' ) ;
96+ const submitter = appendToBody < HTMLButtonElement > ( '<button type="submit" form="ext-form"></button>' ) ;
97+ submitForm ( form , submitter ) ;
98+
99+ expect ( spy ) . toHaveBeenCalledWith ( expect . objectContaining ( { delegateTarget : form , submitter } ) ) ;
100+ } ) ;
101+
102+ it ( 'navigates to the formaction of an externally associated submitter' , async ( ) => {
103+ swup . use ( plugin ) ;
104+
105+ const navigateSpy = vitest . spyOn ( swup , 'navigate' ) . mockImplementation ( ( ) => { } ) ;
106+
107+ const form = createForm ( '<form id="ext-form" action="/path" data-swup-form></form>' ) ;
108+ const submitter = appendToBody < HTMLButtonElement > (
109+ '<button type="submit" form="ext-form" formaction="/other"></button>'
110+ ) ;
111+ submitForm ( form , submitter ) ;
112+
113+ expect ( navigateSpy ) . toHaveBeenCalledWith (
114+ 'http://localhost:3000/other' ,
115+ expect . objectContaining ( { method : 'GET' , cache : { read : false , write : true } } ) ,
116+ expect . objectContaining ( { el : form } )
117+ ) ;
118+ } ) ;
119+
120+ it ( 'includes externally associated inputs when navigating' , async ( ) => {
121+ swup . use ( plugin ) ;
122+
123+ const navigateSpy = vitest . spyOn ( swup , 'navigate' ) . mockImplementation ( ( ) => { } ) ;
124+
125+ const form = createForm ( '<form id="ext-form" action="/path" data-swup-form></form>' ) ;
126+ appendToBody ( '<input type="hidden" name="a" value="b" form="ext-form">' ) ;
127+ const submitter = appendToBody < HTMLButtonElement > ( '<button type="submit" form="ext-form"></button>' ) ;
128+ submitForm ( form , submitter ) ;
129+
130+ expect ( navigateSpy ) . toHaveBeenCalledWith (
131+ 'http://localhost:3000/path?a=b' ,
132+ expect . objectContaining ( { method : 'GET' } ) ,
133+ expect . objectContaining ( { el : form } )
134+ ) ;
135+ } ) ;
136+
82137 it ( 'calls the form:submit hook' , async ( ) => {
83138 swup . use ( plugin ) ;
84139
0 commit comments