@@ -296,5 +296,53 @@ test.describe('Control Templates', () => {
296296 mockedPage . getByTestId ( 'control-json-textarea' )
297297 ) . toBeVisible ( ) ;
298298 } ) ;
299+
300+ test ( 'switching to Form mode is blocked when JSON contains a template payload' , async ( {
301+ mockedPage,
302+ } ) => {
303+ // Given: the JSON editor is open with a template payload pasted
304+ await mockedPage . goto ( controlsUrl ) ;
305+ await mockedPage . getByTestId ( 'add-control-button' ) . click ( ) ;
306+ await mockedPage . getByRole ( 'button' , { name : 'Create Control' } ) . click ( ) ;
307+ await mockedPage . getByTestId ( 'from-json-button' ) . click ( ) ;
308+
309+ const jsonEditor = mockedPage . getByTestId ( 'control-json-textarea' ) ;
310+ await expect ( jsonEditor ) . toBeVisible ( ) ;
311+
312+ const templateJson = JSON . stringify ( {
313+ template : {
314+ parameters : {
315+ pattern : { type : 'regex_re2' , label : 'Pattern' } ,
316+ } ,
317+ definition_template : {
318+ execution : 'server' ,
319+ scope : { stages : [ 'pre' ] } ,
320+ condition : {
321+ selector : { path : 'input' } ,
322+ evaluator : {
323+ name : 'regex' ,
324+ config : { pattern : { $param : 'pattern' } } ,
325+ } ,
326+ } ,
327+ action : { decision : 'deny' } ,
328+ } ,
329+ } ,
330+ template_values : { } ,
331+ } ) ;
332+ await jsonEditor . fill ( templateJson ) ;
333+
334+ // When: attempting to switch to Form mode
335+ await mockedPage . locator ( 'label' ) . getByText ( 'Form' ) . click ( ) ;
336+
337+ // Then: an error message is shown explaining templates can't use Form mode
338+ await expect (
339+ mockedPage . getByText (
340+ 'Template-backed controls cannot be edited in Form mode'
341+ )
342+ ) . toBeVisible ( ) ;
343+
344+ // And: the JSON editor is still visible (did not switch)
345+ await expect ( jsonEditor ) . toBeVisible ( ) ;
346+ } ) ;
299347 } ) ;
300348} ) ;
0 commit comments