@@ -155,3 +155,70 @@ test('user can create folders', async ({ page }) => {
155155 await expect ( terminalOutput ) . toContainText ( folder , { useInnerText : true } ) ;
156156 }
157157} ) ;
158+
159+ test ( 'user can create files and folders in allowed directories' , async ( { page } ) => {
160+ await page . goto ( `${ BASE_URL } /allow-edits-glob` ) ;
161+ await expect ( page . getByRole ( 'heading' , { level : 1 , name : 'File Tree test - Allow Edits Glob' } ) ) . toBeVisible ( ) ;
162+
163+ // wait for terminal to start
164+ const terminal = page . getByRole ( 'textbox' , { name : 'Terminal input' } ) ;
165+ const terminalOutput = page . getByRole ( 'tabpanel' , { name : 'Terminal' } ) ;
166+ await expect ( terminalOutput ) . toContainText ( '~/tutorial' , { useInnerText : true } ) ;
167+
168+ // can create files in root and inside "second-level"
169+ for ( const [ locator , name , type ] of [
170+ [ page . getByTestId ( 'file-tree-root-context-menu' ) , 'new-file.js' , 'file' ] ,
171+ [ page . getByRole ( 'button' , { name : 'second-level' } ) , 'new-folder.js' , 'folder' ] ,
172+ ] as const ) {
173+ await locator . click ( { button : 'right' } ) ;
174+ await page . getByRole ( 'menuitem' , { name : `Create ${ type } ` } ) . click ( ) ;
175+
176+ await page . locator ( '*:focus' ) . fill ( name ) ;
177+ await page . locator ( '*:focus' ) . press ( 'Enter' ) ;
178+ await expect ( page . getByRole ( 'button' , { name } ) ) . toBeVisible ( ) ;
179+ }
180+
181+ await expect ( page . getByRole ( 'button' , { name : 'new-file.js' } ) ) . toBeVisible ( ) ;
182+ await expect ( page . getByRole ( 'button' , { name : 'new-folder' } ) ) . toBeVisible ( ) ;
183+
184+ // verify that files are present on file system via terminal
185+ for ( const [ directory , folder ] of [
186+ [ './' , 'new-file.js' ] ,
187+ [ './first-level/second-level/' , 'new-folder' ] ,
188+ ] ) {
189+ await terminal . fill ( `clear; ls ${ directory } ` ) ;
190+ await terminal . press ( 'Enter' ) ;
191+
192+ await expect ( terminalOutput ) . toContainText ( folder , { useInnerText : true } ) ;
193+ }
194+ } ) ;
195+
196+ test ( 'user cannot create files or folders in disallowed directories' , async ( { page } ) => {
197+ await page . goto ( `${ BASE_URL } /allow-edits-glob` ) ;
198+ await expect ( page . getByRole ( 'heading' , { level : 1 , name : 'File Tree test - Allow Edits Glob' } ) ) . toBeVisible ( ) ;
199+
200+ // wait for terminal to start
201+ const terminalOutput = page . getByRole ( 'tabpanel' , { name : 'Terminal' } ) ;
202+ await expect ( terminalOutput ) . toContainText ( '~/tutorial' , { useInnerText : true } ) ;
203+
204+ for ( const [ name , type ] of [
205+ [ 'new-file.js' , 'file' ] ,
206+ [ 'new-folder' , 'folder' ] ,
207+ ] as const ) {
208+ await page . getByRole ( 'button' , { name : 'first-level' } ) . click ( { button : 'right' } ) ;
209+ await page . getByRole ( 'menuitem' , { name : `Create ${ type } ` } ) . click ( ) ;
210+
211+ await page . locator ( '*:focus' ) . fill ( name ) ;
212+ await page . locator ( '*:focus' ) . press ( 'Enter' ) ;
213+
214+ const dialog = page . getByRole ( 'dialog' , { name : 'This action is not allowed' } ) ;
215+
216+ await expect ( dialog . getByText ( 'Created files and folders must match following patterns:' ) ) . toBeVisible ( ) ;
217+ await expect ( dialog . getByRole ( 'listitem' ) . nth ( 0 ) ) . toHaveText ( '/*' ) ;
218+ await expect ( dialog . getByRole ( 'listitem' ) . nth ( 1 ) ) . toHaveText ( '/first-level/allowed-filename-only.js' ) ;
219+ await expect ( dialog . getByRole ( 'listitem' ) . nth ( 2 ) ) . toHaveText ( '**/second-level/**' ) ;
220+
221+ await dialog . getByRole ( 'button' , { name : 'OK' } ) . click ( ) ;
222+ await expect ( dialog ) . not . toBeVisible ( ) ;
223+ }
224+ } ) ;
0 commit comments