@@ -72,3 +72,163 @@ test.describe('Console (terminal mode)', () => {
7272 await expect ( executedCell ) . toContainText ( '4194304' ) ;
7373 } ) ;
7474} ) ;
75+
76+ test . describe ( 'Console Input Auto-Resize' , ( ) => {
77+ test . beforeEach ( async ( { page } ) => setupConsole ( page ) ) ;
78+
79+ test ( 'Input prompt auto-resizes with multiple lines of text' , async ( {
80+ page
81+ } ) => {
82+ const codeConsoleInput = page . locator ( '.jp-CodeConsole-input' ) ;
83+
84+ const initialHeight = await codeConsoleInput . boundingBox ( ) ;
85+ expect ( initialHeight ) . not . toBeNull ( ) ;
86+
87+ const multiLineCode = `def hello_world():
88+ print("Hello")
89+ print("World")
90+ return "Done"` ;
91+
92+ await page . keyboard . type ( multiLineCode ) ;
93+
94+ const afterTypingHeight = await codeConsoleInput . boundingBox ( ) ;
95+ expect ( afterTypingHeight ) . not . toBeNull ( ) ;
96+ expect ( afterTypingHeight ! . height ) . toBeGreaterThan ( initialHeight ! . height ) ;
97+ } ) ;
98+
99+ test ( 'Input prompt auto-resize works with paste operations' , async ( {
100+ page
101+ } ) => {
102+ const codeConsoleInput = page . locator ( '.jp-CodeConsole-input' ) ;
103+
104+ const initialHeight = await codeConsoleInput . boundingBox ( ) ;
105+ expect ( initialHeight ) . not . toBeNull ( ) ;
106+
107+ const pastedCode = `import numpy as np
108+ import pandas as pd
109+
110+ data = pd.DataFrame({
111+ 'x': [1, 2, 3, 4, 5],
112+ 'y': [2, 4, 6, 8, 10]
113+ })
114+
115+ print(data.head())` ;
116+
117+ await page . evaluate ( async code => {
118+ await navigator . clipboard . writeText ( code ) ;
119+ } , pastedCode ) ;
120+
121+ await page . keyboard . press ( 'ControlOrMeta+v' ) ;
122+
123+ const afterPasteHeight = await codeConsoleInput . boundingBox ( ) ;
124+ expect ( afterPasteHeight ) . not . toBeNull ( ) ;
125+ expect ( afterPasteHeight ! . height ) . toBeGreaterThan ( initialHeight ! . height ) ;
126+ } ) ;
127+
128+ test ( 'Input prompt maintains auto-resize height when moved from bottom to top' , async ( {
129+ page
130+ } ) => {
131+ const codeConsoleInput = page . locator ( '.jp-CodeConsole-input' ) ;
132+
133+ const pastedCode = `def complex_function():
134+ for i in range(10):
135+ if i % 2 == 0:
136+ print(f"Even: {i}")
137+ else:
138+ print(f"Odd: {i}")
139+ return "Completed"` ;
140+
141+ await page . evaluate ( async code => {
142+ await navigator . clipboard . writeText ( code ) ;
143+ } , pastedCode ) ;
144+
145+ await page . keyboard . press ( 'ControlOrMeta+v' ) ;
146+
147+ const heightAtBottom = await codeConsoleInput . boundingBox ( ) ;
148+ expect ( heightAtBottom ) . not . toBeNull ( ) ;
149+
150+ await page . getByLabel ( 'Change Console Prompt Position' ) . first ( ) . click ( ) ;
151+ await page . getByText ( 'Prompt to top' ) . click ( ) ;
152+
153+ const heightAtTop = await codeConsoleInput . boundingBox ( ) ;
154+ expect ( heightAtTop ) . not . toBeNull ( ) ;
155+ expect ( heightAtTop ! . height ) . toBeCloseTo ( heightAtBottom ! . height , 1 ) ;
156+ } ) ;
157+
158+ test ( 'Input prompt continues to auto-resize after code execution' , async ( {
159+ page
160+ } ) => {
161+ const codeConsoleInput = page . locator ( '.jp-CodeConsole-input' ) ;
162+
163+ const initialHeight = await codeConsoleInput . boundingBox ( ) ;
164+ expect ( initialHeight ) . not . toBeNull ( ) ;
165+
166+ const multiLineCode = `def test_function():
167+ print("Line 1")
168+ print("Line 2")
169+ return "Done"` ;
170+
171+ await page . keyboard . type ( multiLineCode ) ;
172+
173+ const heightBeforeExecution = await codeConsoleInput . boundingBox ( ) ;
174+ expect ( heightBeforeExecution ) . not . toBeNull ( ) ;
175+ expect ( heightBeforeExecution ! . height ) . toBeGreaterThan (
176+ initialHeight ! . height
177+ ) ;
178+
179+ // Execute the code
180+ await page . keyboard . press ( 'Shift+Enter' ) ;
181+
182+ await page . locator ( 'text=| Idle' ) . waitFor ( ) ;
183+
184+ // Check that the new empty input cell has shrunk back to original size
185+ const heightAfterExecution = await codeConsoleInput . boundingBox ( ) ;
186+ expect ( heightAfterExecution ) . not . toBeNull ( ) ;
187+ expect ( heightAfterExecution ! . height ) . toBe ( initialHeight ! . height ) ;
188+
189+ // Type new multi-line code in the new prompt cell
190+ const moreCode = `import os
191+ import sys
192+ print("Testing auto-resize")
193+ print("After execution")` ;
194+
195+ await page . keyboard . type ( moreCode ) ;
196+
197+ const heightAfterTyping = await codeConsoleInput . boundingBox ( ) ;
198+ expect ( heightAfterTyping ) . not . toBeNull ( ) ;
199+
200+ // The input should have grown again for the new multi-line content
201+ expect ( heightAfterTyping ! . height ) . toBeGreaterThan (
202+ heightAfterExecution ! . height
203+ ) ;
204+ } ) ;
205+
206+ test ( 'Input prompt shrinks when content is cleared' , async ( { page } ) => {
207+ const codeConsoleInput = page . locator ( '.jp-CodeConsole-input' ) ;
208+
209+ const initialHeight = await codeConsoleInput . boundingBox ( ) ;
210+ expect ( initialHeight ) . not . toBeNull ( ) ;
211+
212+ const multiLineCode = `def multi_line_function():
213+ print("This is line 1")
214+ print("This is line 2")
215+ print("This is line 3")
216+ for i in range(5):
217+ print(f"Loop iteration {i}")
218+ return "Finished"` ;
219+
220+ await page . keyboard . type ( multiLineCode ) ;
221+
222+ const expandedHeight = await codeConsoleInput . boundingBox ( ) ;
223+ expect ( expandedHeight ) . not . toBeNull ( ) ;
224+ expect ( expandedHeight ! . height ) . toBeGreaterThan ( initialHeight ! . height ) ;
225+
226+ // Clear the input using Ctrl+A followed by Delete
227+ await page . keyboard . press ( 'ControlOrMeta+a' ) ;
228+ await page . keyboard . press ( 'Delete' ) ;
229+
230+ const shrunkHeight = await codeConsoleInput . boundingBox ( ) ;
231+ expect ( shrunkHeight ) . not . toBeNull ( ) ;
232+ expect ( shrunkHeight ! . height ) . toBe ( initialHeight ! . height ) ;
233+ } ) ;
234+ } ) ;
0 commit comments