@@ -5,17 +5,24 @@ import {
5
5
} from '@theia/core/shared/inversify' ;
6
6
import { assert , expect } from 'chai' ;
7
7
import fetch from 'cross-fetch' ;
8
+ import { rejects } from 'node:assert' ;
8
9
import { posix } from 'node:path' ;
10
+ import PQueue from 'p-queue' ;
11
+ import queryString from 'query-string' ;
9
12
import { v4 } from 'uuid' ;
10
13
import { ArduinoPreferences } from '../../browser/arduino-preferences' ;
11
14
import { AuthenticationClientService } from '../../browser/auth/authentication-client-service' ;
12
15
import { CreateApi } from '../../browser/create/create-api' ;
13
16
import { 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' ;
15
23
import { SketchCache } from '../../browser/widgets/cloud-sketchbook/cloud-sketch-cache' ;
16
24
import { SketchesService } from '../../common/protocol' ;
17
25
import { AuthenticationSession } from '../../node/auth/types' ;
18
- import queryString from 'query-string' ;
19
26
20
27
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
21
28
/* eslint-disable @typescript-eslint/no-non-null-assertion */
@@ -44,6 +51,11 @@ describe('create-api', () => {
44
51
await cleanAllSketches ( ) ;
45
52
} ) ;
46
53
54
+ afterEach ( async function ( ) {
55
+ this . timeout ( timeout ) ;
56
+ await cleanAllSketches ( ) ;
57
+ } ) ;
58
+
47
59
function createContainer ( accessToken : string ) : Container {
48
60
const container = new Container ( { defaultScope : 'Singleton' } ) ;
49
61
container . load (
@@ -120,13 +132,14 @@ describe('create-api', () => {
120
132
121
133
async function cleanAllSketches ( ) : Promise < void > {
122
134
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 ( ) ;
130
143
sketches = await createApi . sketches ( ) ;
131
144
expect ( sketches ) . to . be . empty ;
132
145
}
@@ -229,8 +242,52 @@ describe('create-api', () => {
229
242
expect ( findByName ( otherName , sketches ) ) . to . be . not . undefined ;
230
243
} ) ;
231
244
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
+
232
287
[ '.' , '-' , '_' ] . 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 ( ) => {
234
291
const name = `sketch${ char } ` ;
235
292
const posixPath = toPosix ( name ) ;
236
293
const newSketch = await createApi . createSketch (
@@ -300,19 +357,23 @@ describe('create-api', () => {
300
357
diff < 0 ? '<' : diff > 0 ? '>' : '='
301
358
} limit)`, async ( ) => {
302
359
const content = 'void setup(){} void loop(){}' ;
303
- const maxLimit = 50 ; // https://github.com/arduino/arduino-ide/pull/875
360
+ const maxLimit = 10 ;
304
361
const sketchCount = maxLimit + diff ;
305
362
const sketchNames = [ ...Array ( sketchCount ) . keys ( ) ] . map ( ( ) => v4 ( ) ) ;
306
363
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 ( ) ;
313
374
314
375
createApi . resetRequestRecording ( ) ;
315
- const sketches = await createApi . sketches ( ) ;
376
+ const sketches = await createApi . sketches ( maxLimit ) ;
316
377
const allRequests = createApi . requestRecording . slice ( ) ;
317
378
318
379
expect ( sketches . length ) . to . be . equal ( sketchCount ) ;
0 commit comments