cozy-client 25.0.2 → 25.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/CozyClient.js +1 -1
- package/dist/RealTimeQueries.js +1 -0
- package/dist/RealTimeQueries.spec.jsx +8 -0
- package/dist/models/file.js +561 -11
- package/dist/models/file.spec.js +414 -48
- package/dist/types.js +1 -0
- package/package.json +2 -2
- package/types/models/file.d.ts +33 -0
- package/types/types.d.ts +4 -0
package/dist/models/file.spec.js
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as fileModel from './file'
|
|
2
2
|
import { Qualification } from './document'
|
|
3
|
+
import { QueryDefinition } from '../queries/dsl'
|
|
4
|
+
const CozyClient = require('cozy-client/dist/CozyClient').default
|
|
5
|
+
const CozyStackClient = require('cozy-stack-client').default
|
|
6
|
+
|
|
7
|
+
jest.mock('cozy-stack-client')
|
|
8
|
+
|
|
9
|
+
const cozyClient = new CozyClient({
|
|
10
|
+
stackClient: new CozyStackClient()
|
|
11
|
+
})
|
|
12
|
+
const destroySpy = jest.fn().mockName('destroy')
|
|
13
|
+
const getSpy = jest.fn().mockName('get')
|
|
14
|
+
const statByPathSpy = jest.fn().mockName('statByPath')
|
|
15
|
+
const updateFileMetadataSpy = jest.fn().mockName('updateFileMetadata')
|
|
16
|
+
const createFileSpy = jest.fn().mockName('createFileSpy')
|
|
17
|
+
const updateFileSpy = jest.fn().mockName('updateFileSpy')
|
|
18
|
+
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
cozyClient.stackClient.collection.mockReturnValue({
|
|
21
|
+
destroy: destroySpy,
|
|
22
|
+
get: getSpy,
|
|
23
|
+
statByPath: statByPathSpy,
|
|
24
|
+
updateFileMetadata: updateFileMetadataSpy,
|
|
25
|
+
createFile: createFileSpy,
|
|
26
|
+
updateFile: updateFileSpy
|
|
27
|
+
})
|
|
28
|
+
})
|
|
3
29
|
|
|
4
30
|
describe('File Model', () => {
|
|
5
31
|
it('should test if a file is a note or not', () => {
|
|
@@ -7,7 +33,7 @@ describe('File Model', () => {
|
|
|
7
33
|
type: 'file',
|
|
8
34
|
_id: 1
|
|
9
35
|
}
|
|
10
|
-
expect(
|
|
36
|
+
expect(fileModel.isNote(fileDocument)).toBe(false)
|
|
11
37
|
const note = {
|
|
12
38
|
type: 'file',
|
|
13
39
|
name: 'test.cozy-note',
|
|
@@ -18,7 +44,7 @@ describe('File Model', () => {
|
|
|
18
44
|
version: 1
|
|
19
45
|
}
|
|
20
46
|
}
|
|
21
|
-
expect(
|
|
47
|
+
expect(fileModel.isNote(note)).toBe(true)
|
|
22
48
|
const note2 = {
|
|
23
49
|
type: 'file',
|
|
24
50
|
name: 'test.cozy-note',
|
|
@@ -29,7 +55,7 @@ describe('File Model', () => {
|
|
|
29
55
|
version: 0
|
|
30
56
|
}
|
|
31
57
|
}
|
|
32
|
-
expect(
|
|
58
|
+
expect(fileModel.isNote(note2)).toBe(true)
|
|
33
59
|
})
|
|
34
60
|
|
|
35
61
|
it('should test if a file is a shortcut or not', () => {
|
|
@@ -43,8 +69,8 @@ describe('File Model', () => {
|
|
|
43
69
|
class: 'image'
|
|
44
70
|
}
|
|
45
71
|
|
|
46
|
-
expect(
|
|
47
|
-
expect(
|
|
72
|
+
expect(fileModel.isShortcut(shortcut)).toBe(true)
|
|
73
|
+
expect(fileModel.isShortcut(image)).toBe(false)
|
|
48
74
|
})
|
|
49
75
|
|
|
50
76
|
it('should test if a file is an onlyoffice file or not', () => {
|
|
@@ -88,13 +114,13 @@ describe('File Model', () => {
|
|
|
88
114
|
class: 'spreadsheet'
|
|
89
115
|
}
|
|
90
116
|
|
|
91
|
-
expect(
|
|
92
|
-
expect(
|
|
93
|
-
expect(
|
|
94
|
-
expect(
|
|
95
|
-
expect(
|
|
96
|
-
expect(
|
|
97
|
-
expect(
|
|
117
|
+
expect(fileModel.isOnlyOfficeFile(text)).toBe(true)
|
|
118
|
+
expect(fileModel.isOnlyOfficeFile(slide)).toBe(true)
|
|
119
|
+
expect(fileModel.isOnlyOfficeFile(spreadsheet)).toBe(true)
|
|
120
|
+
expect(fileModel.isOnlyOfficeFile(directory)).toBe(false)
|
|
121
|
+
expect(fileModel.isOnlyOfficeFile(shortcut)).toBe(false)
|
|
122
|
+
expect(fileModel.isOnlyOfficeFile(image)).toBe(false)
|
|
123
|
+
expect(fileModel.isOnlyOfficeFile(note)).toBe(false)
|
|
98
124
|
})
|
|
99
125
|
|
|
100
126
|
it('should test if a file should be opened by only office', () => {
|
|
@@ -108,9 +134,9 @@ describe('File Model', () => {
|
|
|
108
134
|
|
|
109
135
|
const mdFile = { ...docxFile, name: 'test.md' }
|
|
110
136
|
|
|
111
|
-
expect(
|
|
112
|
-
expect(
|
|
113
|
-
expect(
|
|
137
|
+
expect(fileModel.shouldBeOpenedByOnlyOffice(docxFile)).toBe(true)
|
|
138
|
+
expect(fileModel.shouldBeOpenedByOnlyOffice(txtFile)).toBe(false)
|
|
139
|
+
expect(fileModel.shouldBeOpenedByOnlyOffice(mdFile)).toBe(false)
|
|
114
140
|
})
|
|
115
141
|
|
|
116
142
|
it('should test if a file has a specific metadata', () => {
|
|
@@ -121,10 +147,10 @@ describe('File Model', () => {
|
|
|
121
147
|
}
|
|
122
148
|
|
|
123
149
|
expect(
|
|
124
|
-
|
|
150
|
+
fileModel.hasMetadataAttribute({ file: doc, attribute: 'carbonCopy' })
|
|
125
151
|
).toBe(true)
|
|
126
152
|
expect(
|
|
127
|
-
|
|
153
|
+
fileModel.hasMetadataAttribute({ file: doc, attribute: 'electronicSafe' })
|
|
128
154
|
).toBe(false)
|
|
129
155
|
})
|
|
130
156
|
|
|
@@ -134,25 +160,25 @@ describe('File Model', () => {
|
|
|
134
160
|
|
|
135
161
|
it('should allow both `id` and `_id`', () => {
|
|
136
162
|
const doc = { id, type }
|
|
137
|
-
expect(
|
|
163
|
+
expect(fileModel.normalize(doc)).toHaveProperty('_id', id)
|
|
138
164
|
|
|
139
165
|
const _doc = { _id: id, type }
|
|
140
|
-
expect(
|
|
166
|
+
expect(fileModel.normalize(_doc)).toHaveProperty('_id', id)
|
|
141
167
|
})
|
|
142
168
|
|
|
143
169
|
it('should enforce a `_type`', () => {
|
|
144
170
|
const doc = { id, type }
|
|
145
|
-
expect(
|
|
146
|
-
expect(
|
|
171
|
+
expect(fileModel.normalize(doc)).toHaveProperty('_type', 'io.cozy.files')
|
|
172
|
+
expect(fileModel.normalize(doc)).toHaveProperty('type', type)
|
|
147
173
|
|
|
148
174
|
const doc2 = { id, _type: 'io.cozy.something.else' }
|
|
149
|
-
expect(
|
|
175
|
+
expect(fileModel.normalize(doc2)).toHaveProperty(
|
|
150
176
|
'_type',
|
|
151
177
|
'io.cozy.something.else'
|
|
152
178
|
)
|
|
153
179
|
|
|
154
180
|
const doc3 = { id }
|
|
155
|
-
expect(
|
|
181
|
+
expect(fileModel.normalize(doc3)).toHaveProperty('_type', 'io.cozy.files')
|
|
156
182
|
})
|
|
157
183
|
})
|
|
158
184
|
|
|
@@ -179,21 +205,23 @@ describe('File Model', () => {
|
|
|
179
205
|
it(`splits ${stringify(joinName(expectation))} into ${stringify(
|
|
180
206
|
expectation
|
|
181
207
|
)}`, () => {
|
|
182
|
-
expect(
|
|
208
|
+
expect(fileModel.splitFilename(mkFile(expectation))).toEqual(
|
|
209
|
+
expectation
|
|
210
|
+
)
|
|
183
211
|
})
|
|
184
212
|
}
|
|
185
213
|
|
|
186
214
|
it('should throw an error if the file is not correct', () => {
|
|
187
|
-
expect(() =>
|
|
188
|
-
expect(() =>
|
|
189
|
-
expect(() =>
|
|
215
|
+
expect(() => fileModel.splitFilename({})).toThrow()
|
|
216
|
+
expect(() => fileModel.splitFilename({ name: null })).toThrow()
|
|
217
|
+
expect(() => fileModel.splitFilename({ name: '' })).not.toThrow()
|
|
190
218
|
})
|
|
191
219
|
it('should return only the folder name if its a folder', () => {
|
|
192
220
|
const dir = {
|
|
193
221
|
name: 'foo',
|
|
194
222
|
type: 'directory'
|
|
195
223
|
}
|
|
196
|
-
const result =
|
|
224
|
+
const result = fileModel.splitFilename(dir)
|
|
197
225
|
expect(result).toEqual({
|
|
198
226
|
filename: 'foo',
|
|
199
227
|
extension: ''
|
|
@@ -208,7 +236,7 @@ describe('File Model', () => {
|
|
|
208
236
|
it('should define the path if parent is provided', () => {
|
|
209
237
|
const doc = { id, name: 'myfile.ext' }
|
|
210
238
|
const parent = { path: '/my/path' }
|
|
211
|
-
expect(
|
|
239
|
+
expect(fileModel.ensureFilePath(doc, parent)).toHaveProperty(
|
|
212
240
|
'path',
|
|
213
241
|
'/my/path/myfile.ext'
|
|
214
242
|
)
|
|
@@ -216,13 +244,13 @@ describe('File Model', () => {
|
|
|
216
244
|
|
|
217
245
|
it('should not require a `parent` parameter if one is present', () => {
|
|
218
246
|
const doc = { id, type, path: '/test/file' }
|
|
219
|
-
expect(
|
|
247
|
+
expect(fileModel.ensureFilePath(doc)).toHaveProperty('path', '/test/file')
|
|
220
248
|
})
|
|
221
249
|
|
|
222
250
|
it('should not buid a `path` if the one is already present', () => {
|
|
223
251
|
const doc = { id, type, path: '/test/file' }
|
|
224
252
|
const parent = { id, type, path: '/test/parent' }
|
|
225
|
-
expect(
|
|
253
|
+
expect(fileModel.ensureFilePath(doc, parent)).toHaveProperty(
|
|
226
254
|
'path',
|
|
227
255
|
'/test/file'
|
|
228
256
|
)
|
|
@@ -256,47 +284,385 @@ describe('File Model', () => {
|
|
|
256
284
|
}
|
|
257
285
|
|
|
258
286
|
it('identifies a sharing shortcut', () => {
|
|
259
|
-
expect(
|
|
260
|
-
expect(
|
|
287
|
+
expect(fileModel.isSharingShortcut(sharingShortcutDocument)).toBe(true)
|
|
288
|
+
expect(fileModel.isSharingShortcut(nonSharingShortcutDocument)).toBe(
|
|
289
|
+
false
|
|
290
|
+
)
|
|
261
291
|
})
|
|
262
292
|
|
|
263
293
|
it('detects if a sharing shortcut is new', () => {
|
|
264
|
-
expect(
|
|
265
|
-
expect(
|
|
266
|
-
|
|
294
|
+
expect(fileModel.isSharingShortcutNew(newShortcutDocument)).toBe(true)
|
|
295
|
+
expect(fileModel.isSharingShortcutNew(nonSharingShortcutDocument)).toBe(
|
|
296
|
+
false
|
|
297
|
+
)
|
|
298
|
+
expect(fileModel.isSharingShortcutNew(sharingShortcutDocument)).toBe(
|
|
299
|
+
false
|
|
300
|
+
)
|
|
267
301
|
})
|
|
268
302
|
|
|
269
303
|
it('returns the sharring shortcut status', () => {
|
|
270
|
-
expect(
|
|
271
|
-
|
|
304
|
+
expect(fileModel.getSharingShortcutStatus(newShortcutDocument)).toBe(
|
|
305
|
+
'new'
|
|
306
|
+
)
|
|
307
|
+
expect(fileModel.getSharingShortcutStatus(sharingShortcutDocument)).toBe(
|
|
272
308
|
'seen'
|
|
273
309
|
)
|
|
274
310
|
expect(
|
|
275
|
-
|
|
311
|
+
fileModel.getSharingShortcutStatus(nonSharingShortcutDocument)
|
|
276
312
|
).toBeUndefined()
|
|
277
313
|
})
|
|
278
314
|
|
|
279
315
|
it('returns the sharring shortcut target mime type', () => {
|
|
280
|
-
expect(
|
|
316
|
+
expect(fileModel.getSharingShortcutTargetMime(newShortcutDocument)).toBe(
|
|
281
317
|
'target-mimetype-2'
|
|
282
318
|
)
|
|
283
|
-
expect(file.getSharingShortcutTargetMime(sharingShortcutDocument)).toBe(
|
|
284
|
-
'target-mimetype'
|
|
285
|
-
)
|
|
286
319
|
expect(
|
|
287
|
-
|
|
320
|
+
fileModel.getSharingShortcutTargetMime(sharingShortcutDocument)
|
|
321
|
+
).toBe('target-mimetype')
|
|
322
|
+
expect(
|
|
323
|
+
fileModel.getSharingShortcutTargetMime(nonSharingShortcutDocument)
|
|
288
324
|
).toBeUndefined()
|
|
289
325
|
})
|
|
290
326
|
|
|
291
327
|
it('returns the sharring shortcut target doctype', () => {
|
|
292
328
|
expect(
|
|
293
|
-
|
|
329
|
+
fileModel.getSharingShortcutTargetDoctype(sharingShortcutDocument)
|
|
294
330
|
).toBe('io.cozy.files')
|
|
295
331
|
expect(
|
|
296
|
-
|
|
332
|
+
fileModel.getSharingShortcutTargetMime(nonSharingShortcutDocument)
|
|
297
333
|
).toBeUndefined()
|
|
298
334
|
})
|
|
299
335
|
})
|
|
336
|
+
describe('getFullpath', () => {
|
|
337
|
+
let parentDirPath
|
|
338
|
+
|
|
339
|
+
beforeEach(() => {
|
|
340
|
+
getSpy.mockImplementation(() =>
|
|
341
|
+
Promise.resolve({
|
|
342
|
+
data: {
|
|
343
|
+
_id: '123',
|
|
344
|
+
_type: 'io.cozy.files',
|
|
345
|
+
path: parentDirPath
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
)
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
afterEach(() => {
|
|
352
|
+
jest.restoreAllMocks()
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('should return the full path of the file', async () => {
|
|
356
|
+
parentDirPath = '/GrandParent/Parent'
|
|
357
|
+
const result = await fileModel.getFullpath(
|
|
358
|
+
cozyClient,
|
|
359
|
+
'parent',
|
|
360
|
+
'mydoc.odt'
|
|
361
|
+
)
|
|
362
|
+
expect(cozyClient.stackClient.collection).toHaveBeenCalledWith(
|
|
363
|
+
'io.cozy.files'
|
|
364
|
+
)
|
|
365
|
+
expect(getSpy).toHaveBeenCalledWith(
|
|
366
|
+
'parent',
|
|
367
|
+
new QueryDefinition({ doctype: 'io.cozy.files', id: 'parent' })
|
|
368
|
+
)
|
|
369
|
+
expect(result).toEqual('/GrandParent/Parent/mydoc.odt')
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
it('should return the full path of the file if it is in root directory', async () => {
|
|
373
|
+
parentDirPath = '/'
|
|
374
|
+
const result = await fileModel.getFullpath(
|
|
375
|
+
cozyClient,
|
|
376
|
+
'parent',
|
|
377
|
+
'mydoc.odt'
|
|
378
|
+
)
|
|
379
|
+
expect(cozyClient.stackClient.collection).toHaveBeenCalledWith(
|
|
380
|
+
'io.cozy.files'
|
|
381
|
+
)
|
|
382
|
+
expect(getSpy).toHaveBeenCalledWith(
|
|
383
|
+
'parent',
|
|
384
|
+
new QueryDefinition({ doctype: 'io.cozy.files', id: 'parent' })
|
|
385
|
+
)
|
|
386
|
+
expect(result).toEqual('/mydoc.odt')
|
|
387
|
+
})
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
describe('move', () => {
|
|
391
|
+
const fileId = 'file-2295478c'
|
|
392
|
+
const folderId = 'dir-b1e1c256'
|
|
393
|
+
|
|
394
|
+
afterEach(() => {
|
|
395
|
+
jest.restoreAllMocks()
|
|
396
|
+
jest.clearAllMocks()
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
it('should move a file to another destination', async () => {
|
|
400
|
+
updateFileMetadataSpy.mockResolvedValue({
|
|
401
|
+
data: {
|
|
402
|
+
id: fileId,
|
|
403
|
+
dir_id: folderId,
|
|
404
|
+
_type: 'io.cozy.files'
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
const result = await fileModel.move(cozyClient, fileId, { folderId })
|
|
408
|
+
expect(updateFileMetadataSpy).toHaveBeenCalled()
|
|
409
|
+
expect(result).toEqual({
|
|
410
|
+
deleted: null,
|
|
411
|
+
moved: {
|
|
412
|
+
id: 'file-2295478c',
|
|
413
|
+
dir_id: 'dir-b1e1c256',
|
|
414
|
+
_type: 'io.cozy.files'
|
|
415
|
+
}
|
|
416
|
+
})
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
it('should fail with an error if there is a conflict and force is false', async () => {
|
|
420
|
+
updateFileMetadataSpy.mockRejectedValueOnce({
|
|
421
|
+
status: 409
|
|
422
|
+
})
|
|
423
|
+
try {
|
|
424
|
+
await fileModel.move(cozyClient, fileId, { folderId })
|
|
425
|
+
} catch (e) {
|
|
426
|
+
expect(e).toEqual({ status: 409 })
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
it('should overwrite the destination if there is a conflict and force is true', async () => {
|
|
431
|
+
const DELETED_FILE_ID = 'deleted-c097ffca'
|
|
432
|
+
|
|
433
|
+
updateFileMetadataSpy.mockRejectedValueOnce({
|
|
434
|
+
status: 409
|
|
435
|
+
})
|
|
436
|
+
updateFileMetadataSpy.mockResolvedValue({
|
|
437
|
+
data: {
|
|
438
|
+
id: fileId,
|
|
439
|
+
dir_id: folderId,
|
|
440
|
+
_type: 'io.cozy.files'
|
|
441
|
+
}
|
|
442
|
+
})
|
|
443
|
+
getSpy.mockResolvedValue({
|
|
444
|
+
data: {
|
|
445
|
+
id: fileId,
|
|
446
|
+
name: 'mydoc.odt',
|
|
447
|
+
_type: 'io.cozy.files'
|
|
448
|
+
}
|
|
449
|
+
})
|
|
450
|
+
statByPathSpy.mockResolvedValue({
|
|
451
|
+
data: {
|
|
452
|
+
id: DELETED_FILE_ID,
|
|
453
|
+
_type: 'io.cozy.files'
|
|
454
|
+
}
|
|
455
|
+
})
|
|
456
|
+
const result = await fileModel.move(
|
|
457
|
+
cozyClient,
|
|
458
|
+
fileId,
|
|
459
|
+
{ folderId },
|
|
460
|
+
true
|
|
461
|
+
)
|
|
462
|
+
expect(updateFileMetadataSpy).toHaveBeenCalled()
|
|
463
|
+
expect(destroySpy).toHaveBeenCalled()
|
|
464
|
+
expect(result).toEqual({
|
|
465
|
+
deleted: DELETED_FILE_ID,
|
|
466
|
+
moved: {
|
|
467
|
+
id: 'file-2295478c',
|
|
468
|
+
dir_id: 'dir-b1e1c256',
|
|
469
|
+
_type: 'io.cozy.files'
|
|
470
|
+
}
|
|
471
|
+
})
|
|
472
|
+
})
|
|
473
|
+
|
|
474
|
+
it('should use destination.path if it is given', async () => {
|
|
475
|
+
const DELETED_FILE_ID = 'deleted-c097ffca'
|
|
476
|
+
|
|
477
|
+
updateFileMetadataSpy.mockRejectedValueOnce({
|
|
478
|
+
status: 409
|
|
479
|
+
})
|
|
480
|
+
updateFileMetadataSpy.mockResolvedValue({
|
|
481
|
+
data: {
|
|
482
|
+
id: fileId,
|
|
483
|
+
dir_id: folderId,
|
|
484
|
+
_type: 'io.cozy.files'
|
|
485
|
+
}
|
|
486
|
+
})
|
|
487
|
+
statByPathSpy.mockResolvedValue({
|
|
488
|
+
data: {
|
|
489
|
+
id: DELETED_FILE_ID,
|
|
490
|
+
_type: 'io.cozy.files'
|
|
491
|
+
}
|
|
492
|
+
})
|
|
493
|
+
const result = await fileModel.move(
|
|
494
|
+
cozyClient,
|
|
495
|
+
fileId,
|
|
496
|
+
{ folderId, path: '/mydir/mydoc.odt' },
|
|
497
|
+
true
|
|
498
|
+
)
|
|
499
|
+
expect(getSpy).not.toHaveBeenCalled()
|
|
500
|
+
expect(updateFileMetadataSpy).toHaveBeenCalled()
|
|
501
|
+
expect(destroySpy).toHaveBeenCalled()
|
|
502
|
+
expect(result).toEqual({
|
|
503
|
+
deleted: DELETED_FILE_ID,
|
|
504
|
+
moved: {
|
|
505
|
+
id: 'file-2295478c',
|
|
506
|
+
dir_id: 'dir-b1e1c256',
|
|
507
|
+
_type: 'io.cozy.files'
|
|
508
|
+
}
|
|
509
|
+
})
|
|
510
|
+
})
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
describe('splitFilename', () => {
|
|
514
|
+
const name = ({ filename, extension }) => filename + extension
|
|
515
|
+
const file = expectation => ({ type: 'file', name: name(expectation) })
|
|
516
|
+
const { stringify } = JSON
|
|
517
|
+
|
|
518
|
+
const scenarios = [
|
|
519
|
+
{ filename: 'file', extension: '.ext' },
|
|
520
|
+
{ filename: 'file', extension: '' },
|
|
521
|
+
{ filename: 'file.html', extension: '.ejs' },
|
|
522
|
+
{ filename: 'file', extension: '.' },
|
|
523
|
+
{ filename: 'file.', extension: '.' },
|
|
524
|
+
{ filename: 'file.', extension: '.ext' },
|
|
525
|
+
{ filename: '.file', extension: '' },
|
|
526
|
+
{ filename: '.file', extension: '.ext' }
|
|
527
|
+
]
|
|
528
|
+
|
|
529
|
+
for (const expectation of scenarios) {
|
|
530
|
+
it(`splits ${stringify(name(expectation))} into ${stringify(
|
|
531
|
+
expectation
|
|
532
|
+
)}`, () => {
|
|
533
|
+
expect(fileModel.splitFilename(file(expectation))).toEqual(expectation)
|
|
534
|
+
})
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
it('should throw an error if the file is not correct', () => {
|
|
538
|
+
const file = {}
|
|
539
|
+
|
|
540
|
+
expect(() => fileModel.splitFilename(file)).toThrow()
|
|
541
|
+
})
|
|
542
|
+
it('should return only the folder name if its a folder', () => {
|
|
543
|
+
const file = {
|
|
544
|
+
name: 'foo',
|
|
545
|
+
type: 'directory'
|
|
546
|
+
}
|
|
547
|
+
const result = fileModel.splitFilename(file)
|
|
548
|
+
expect(result).toEqual({
|
|
549
|
+
filename: 'foo',
|
|
550
|
+
extension: ''
|
|
551
|
+
})
|
|
552
|
+
})
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
describe('generateNewFileNameOnConflict', () => {
|
|
556
|
+
it('should generate the right file name with _X', () => {
|
|
557
|
+
const filename1 = fileModel.generateNewFileNameOnConflict('test')
|
|
558
|
+
expect(filename1).toEqual('test_1')
|
|
559
|
+
const filename2 = fileModel.generateNewFileNameOnConflict('test_1')
|
|
560
|
+
expect(filename2).toEqual('test_2')
|
|
561
|
+
const filename3 = fileModel.generateNewFileNameOnConflict('test_1_1_test')
|
|
562
|
+
expect(filename3).toEqual('test_1_1_test_1')
|
|
563
|
+
const filename4 = fileModel.generateNewFileNameOnConflict('test_')
|
|
564
|
+
expect(filename4).toEqual('test__1')
|
|
565
|
+
})
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
describe('generateFileNameForRevision', () => {
|
|
569
|
+
it('should generate the right file name for a revision', () => {
|
|
570
|
+
const MOCKED_DATE = '2018-01-01T12:00:00.210Z'
|
|
571
|
+
const expectedFilename = 'test_01 January - 12h00.pdf'
|
|
572
|
+
const date = new Date(MOCKED_DATE)
|
|
573
|
+
const result = fileModel.generateFileNameForRevision(
|
|
574
|
+
{ name: 'test.pdf', type: 'file' },
|
|
575
|
+
{ updated_at: date },
|
|
576
|
+
() => '01 January - 12h00'
|
|
577
|
+
)
|
|
578
|
+
expect(result).toEqual(expectedFilename)
|
|
579
|
+
})
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
describe('uploadFileWithConflictStrategy', () => {
|
|
583
|
+
beforeEach(() => {
|
|
584
|
+
getSpy.mockImplementation(() =>
|
|
585
|
+
Promise.resolve({
|
|
586
|
+
data: {
|
|
587
|
+
path: '/GrandParent/Parent',
|
|
588
|
+
_type: 'io.cozy.files',
|
|
589
|
+
_id: '123'
|
|
590
|
+
}
|
|
591
|
+
})
|
|
592
|
+
)
|
|
593
|
+
})
|
|
594
|
+
afterEach(() => {
|
|
595
|
+
jest.restoreAllMocks()
|
|
596
|
+
jest.clearAllMocks()
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
it('should call the upload method if no conflict', async () => {
|
|
600
|
+
statByPathSpy.mockRejectedValueOnce(new Error('Not Found'))
|
|
601
|
+
createFileSpy.mockResolvedValue({
|
|
602
|
+
data: {
|
|
603
|
+
id: 'jj',
|
|
604
|
+
dir_id: 'jj',
|
|
605
|
+
_type: 'io.cozy.files'
|
|
606
|
+
}
|
|
607
|
+
})
|
|
608
|
+
try {
|
|
609
|
+
await fileModel.uploadFileWithConflictStrategy(
|
|
610
|
+
cozyClient,
|
|
611
|
+
{},
|
|
612
|
+
{ name: 'test', dirId: 'a', conflictStrategy: 'erase' }
|
|
613
|
+
)
|
|
614
|
+
} catch (e) {
|
|
615
|
+
expect(createFileSpy).toHaveBeenCalled()
|
|
616
|
+
}
|
|
617
|
+
})
|
|
618
|
+
|
|
619
|
+
it('should rename the file if there is a conflict', async () => {
|
|
620
|
+
const dirId = 'toto'
|
|
621
|
+
//first call we return an existing file => conflict
|
|
622
|
+
//second call, we reject as not found
|
|
623
|
+
statByPathSpy
|
|
624
|
+
.mockReturnValueOnce({
|
|
625
|
+
data: {
|
|
626
|
+
_id: 'file_id',
|
|
627
|
+
_type: 'io.cozy.files'
|
|
628
|
+
}
|
|
629
|
+
})
|
|
630
|
+
.mockRejectedValueOnce(new Error('Not Found'))
|
|
631
|
+
|
|
632
|
+
const opts = {
|
|
633
|
+
name: 'filename',
|
|
634
|
+
dirId,
|
|
635
|
+
conflictStrategy: 'rename',
|
|
636
|
+
contentType: 'image/jpeg'
|
|
637
|
+
}
|
|
638
|
+
await fileModel.uploadFileWithConflictStrategy(cozyClient, '', opts)
|
|
639
|
+
expect(createFileSpy).toHaveBeenCalledWith('', {
|
|
640
|
+
...opts,
|
|
641
|
+
name: 'filename_1'
|
|
642
|
+
})
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
it('should erase the file if there is a conflict', async () => {
|
|
646
|
+
const dirId = 'toto'
|
|
647
|
+
//first call we return an existing file => conflict
|
|
648
|
+
//second call, we reject as not found
|
|
649
|
+
statByPathSpy.mockReturnValueOnce({
|
|
650
|
+
data: {
|
|
651
|
+
id: 'file_id'
|
|
652
|
+
}
|
|
653
|
+
})
|
|
654
|
+
const opts = {
|
|
655
|
+
name: 'filename',
|
|
656
|
+
dirId,
|
|
657
|
+
conflictStrategy: 'erase'
|
|
658
|
+
}
|
|
659
|
+
await fileModel.uploadFileWithConflictStrategy(cozyClient, '', opts)
|
|
660
|
+
expect(updateFileSpy).toHaveBeenCalledWith('', {
|
|
661
|
+
...opts,
|
|
662
|
+
fileId: 'file_id'
|
|
663
|
+
})
|
|
664
|
+
})
|
|
665
|
+
})
|
|
300
666
|
})
|
|
301
667
|
|
|
302
668
|
describe('File qualification', () => {
|
|
@@ -322,7 +688,7 @@ describe('File qualification', () => {
|
|
|
322
688
|
}
|
|
323
689
|
}
|
|
324
690
|
const qualification = Qualification.getByLabel('health_invoice')
|
|
325
|
-
const updFile = await
|
|
691
|
+
const updFile = await fileModel.saveFileQualification(
|
|
326
692
|
mockedClient,
|
|
327
693
|
fileDoc,
|
|
328
694
|
qualification
|
package/dist/types.js
CHANGED
|
@@ -120,6 +120,7 @@ var _dsl = require("./queries/dsl");
|
|
|
120
120
|
/**
|
|
121
121
|
* @typedef {object} CozyClientDocument - A document
|
|
122
122
|
* @property {string} [_id] - Id of the document
|
|
123
|
+
* @property {string} [id] - Id of the document
|
|
123
124
|
* @property {string} [_type] - Type of the document
|
|
124
125
|
* @property {string} [_rev] - Current revision of the document
|
|
125
126
|
* @property {boolean} [_deleted] - When the document has been deleted
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-client",
|
|
3
|
-
"version": "25.0.
|
|
3
|
+
"version": "25.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.node.js",
|
|
6
6
|
"browser": "dist/index.js",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"react-native-inappbrowser-reborn": "^3.5.1"
|
|
69
69
|
},
|
|
70
70
|
"sideEffects": false,
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "537b851a02c87e78bfa84957300f28bbb6db388d"
|
|
72
72
|
}
|
package/types/models/file.d.ts
CHANGED
|
@@ -46,6 +46,39 @@ export function hasMetadataAttribute({ file, attribute }: {
|
|
|
46
46
|
file: IOCozyFile;
|
|
47
47
|
attribute: string;
|
|
48
48
|
}): boolean;
|
|
49
|
+
export function getFullpath(client: CozyClient, dirId: string, name: string): Promise<string>;
|
|
50
|
+
export function move(client: CozyClient, fileId: string, destination: {
|
|
51
|
+
folderId: string;
|
|
52
|
+
path: string;
|
|
53
|
+
}, force?: boolean): Promise<any>;
|
|
54
|
+
export function overrideFileForPath(client: CozyClient, dirPath: string, file: object, metadata: object): Promise<IOCozyFile>;
|
|
55
|
+
export function generateNewFileNameOnConflict(filenameWithoutExtension: string): string;
|
|
56
|
+
export function generateFileNameForRevision(file: IOCozyFile, revision: object, f: Function): string;
|
|
57
|
+
export function uploadFileWithConflictStrategy(client: CozyClient, file: string | ArrayBuffer, options: FileUploadOptions): any;
|
|
58
|
+
export function readMobileFile(fileURL: string): Promise<any>;
|
|
59
|
+
export function doMobileUpload(client: CozyClient, fileURL: string, options: FileUploadOptions): Promise<any>;
|
|
60
|
+
export type FileUploadOptions = {
|
|
61
|
+
/**
|
|
62
|
+
* - The file name to upload
|
|
63
|
+
*/
|
|
64
|
+
name?: string;
|
|
65
|
+
/**
|
|
66
|
+
* - The dirId to upload the file to
|
|
67
|
+
*/
|
|
68
|
+
dirId?: string;
|
|
69
|
+
/**
|
|
70
|
+
* - An object containing the metadata to attach
|
|
71
|
+
*/
|
|
72
|
+
metadata?: object;
|
|
73
|
+
/**
|
|
74
|
+
* - The file Content-Type
|
|
75
|
+
*/
|
|
76
|
+
contentType?: string;
|
|
77
|
+
/**
|
|
78
|
+
* - Erase / rename
|
|
79
|
+
*/
|
|
80
|
+
conflictStrategy?: string;
|
|
81
|
+
};
|
|
49
82
|
import { IOCozyFile } from "../types";
|
|
50
83
|
import CozyClient from "../CozyClient";
|
|
51
84
|
import { QueryResult } from "../types";
|