@@ -5,17 +5,24 @@ import {
55} from '@theia/core/shared/inversify' ;
66import { assert , expect } from 'chai' ;
77import fetch from 'cross-fetch' ;
8+ import { rejects } from 'node:assert' ;
89import { posix } from 'node:path' ;
10+ import PQueue from 'p-queue' ;
11+ import queryString from 'query-string' ;
912import { v4 } from 'uuid' ;
1013import { ArduinoPreferences } from '../../browser/arduino-preferences' ;
1114import { AuthenticationClientService } from '../../browser/auth/authentication-client-service' ;
1215import { CreateApi } from '../../browser/create/create-api' ;
1316import { splitSketchPath } from '../../browser/create/create-paths' ;
14- import { Create , CreateError } from '../../browser/create/typings' ;
17+ import {
18+ Create ,
19+ CreateError ,
20+ isNotFound ,
21+ isUnprocessableContent ,
22+ } from '../../browser/create/typings' ;
1523import { SketchCache } from '../../browser/widgets/cloud-sketchbook/cloud-sketch-cache' ;
1624import { SketchesService } from '../../common/protocol' ;
1725import { AuthenticationSession } from '../../node/auth/types' ;
18- import queryString from 'query-string' ;
1926
2027/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
2128/* eslint-disable @typescript-eslint/no-non-null-assertion */
@@ -44,6 +51,11 @@ describe('create-api', () => {
4451 await cleanAllSketches ( ) ;
4552 } ) ;
4653
54+ afterEach ( async function ( ) {
55+ this . timeout ( timeout ) ;
56+ await cleanAllSketches ( ) ;
57+ } ) ;
58+
4759 function createContainer ( accessToken : string ) : Container {
4860 const container = new Container ( { defaultScope : 'Singleton' } ) ;
4961 container . load (
@@ -120,13 +132,14 @@ describe('create-api', () => {
120132
121133 async function cleanAllSketches ( ) : Promise < void > {
122134 let sketches = await createApi . sketches ( ) ;
123- // Cannot delete the sketches with `await Promise.all` as all delete promise successfully resolve, but the sketch is not deleted from the server.
124- await sketches
125- . map ( ( { path } ) => createApi . deleteSketch ( path ) )
126- . reduce ( async ( acc , curr ) => {
127- await acc ;
128- return curr ;
129- } , Promise . resolve ( ) ) ;
135+ const deleteExecutionQueue = new PQueue ( {
136+ concurrency : 5 ,
137+ autoStart : true ,
138+ } ) ;
139+ sketches . forEach ( ( { path } ) =>
140+ deleteExecutionQueue . add ( ( ) => createApi . deleteSketch ( path ) )
141+ ) ;
142+ await deleteExecutionQueue . onIdle ( ) ;
130143 sketches = await createApi . sketches ( ) ;
131144 expect ( sketches ) . to . be . empty ;
132145 }
@@ -229,8 +242,52 @@ describe('create-api', () => {
229242 expect ( findByName ( otherName , sketches ) ) . to . be . not . undefined ;
230243 } ) ;
231244
245+ it ( 'should error with HTTP 422 when reading a file but is a directory' , async ( ) => {
246+ const name = v4 ( ) ;
247+ const content = 'void setup(){} void loop(){}' ;
248+ const posixPath = toPosix ( name ) ;
249+
250+ await createApi . createSketch ( posixPath , content ) ;
251+ const resources = await createApi . readDirectory ( posixPath ) ;
252+ expect ( resources ) . to . be . not . empty ;
253+
254+ await rejects ( createApi . readFile ( posixPath ) , ( thrown ) =>
255+ isUnprocessableContent ( thrown )
256+ ) ;
257+ } ) ;
258+
259+ it ( 'should error with HTTP 422 when listing a directory but is a file' , async ( ) => {
260+ const name = v4 ( ) ;
261+ const content = 'void setup(){} void loop(){}' ;
262+ const posixPath = toPosix ( name ) ;
263+
264+ await createApi . createSketch ( posixPath , content ) ;
265+ const mainSketchFilePath = posixPath + posixPath + '.ino' ;
266+ const sketchContent = await createApi . readFile ( mainSketchFilePath ) ;
267+ expect ( sketchContent ) . to . be . equal ( content ) ;
268+
269+ await rejects ( createApi . readDirectory ( mainSketchFilePath ) , ( thrown ) =>
270+ isUnprocessableContent ( thrown )
271+ ) ;
272+ } ) ;
273+
274+ it ( "should error with HTTP 404 when deleting a non-existing directory via the '/files/d' endpoint" , async ( ) => {
275+ const name = v4 ( ) ;
276+ const posixPath = toPosix ( name ) ;
277+
278+ const sketches = await createApi . sketches ( ) ;
279+ const sketch = findByName ( name , sketches ) ;
280+ expect ( sketch ) . to . be . undefined ;
281+
282+ await rejects ( createApi . deleteDirectory ( posixPath ) , ( thrown ) =>
283+ isNotFound ( thrown )
284+ ) ;
285+ } ) ;
286+
232287 [ '.' , '-' , '_' ] . map ( ( char ) => {
233- it ( `should create a new sketch with '${ char } ' in the sketch folder name although it's disallowed from the Create Editor` , async ( ) => {
288+ it ( `should create a new sketch with '${ char } ' (character code: ${ char . charCodeAt (
289+ 0
290+ ) } ) in the sketch folder name although it's disallowed from the Create Editor`, async ( ) => {
234291 const name = `sketch${ char } ` ;
235292 const posixPath = toPosix ( name ) ;
236293 const newSketch = await createApi . createSketch (
@@ -300,19 +357,23 @@ describe('create-api', () => {
300357 diff < 0 ? '<' : diff > 0 ? '>' : '='
301358 } limit)`, async ( ) => {
302359 const content = 'void setup(){} void loop(){}' ;
303- const maxLimit = 50 ; // https://github.com/arduino/arduino-ide/pull/875
360+ const maxLimit = 10 ;
304361 const sketchCount = maxLimit + diff ;
305362 const sketchNames = [ ...Array ( sketchCount ) . keys ( ) ] . map ( ( ) => v4 ( ) ) ;
306363
307- await sketchNames
308- . map ( ( name ) => createApi . createSketch ( toPosix ( name ) , content ) )
309- . reduce ( async ( acc , curr ) => {
310- await acc ;
311- return curr ;
312- } , Promise . resolve ( ) as Promise < unknown > ) ;
364+ const createExecutionQueue = new PQueue ( {
365+ concurrency : 5 ,
366+ autoStart : true ,
367+ } ) ;
368+ sketchNames . forEach ( ( name ) =>
369+ createExecutionQueue . add ( ( ) =>
370+ createApi . createSketch ( toPosix ( name ) , content )
371+ )
372+ ) ;
373+ await createExecutionQueue . onIdle ( ) ;
313374
314375 createApi . resetRequestRecording ( ) ;
315- const sketches = await createApi . sketches ( ) ;
376+ const sketches = await createApi . sketches ( maxLimit ) ;
316377 const allRequests = createApi . requestRecording . slice ( ) ;
317378
318379 expect ( sketches . length ) . to . be . equal ( sketchCount ) ;
0 commit comments