diff --git a/jest.config.js b/jest.config.js
index 10b9e57c52..3080961854 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -42,7 +42,7 @@ module.exports = {
testEnvironmentOptions: {
url: 'http://cozy.localhost:8080/'
},
- testMatch: ['**/(*.)(spec|test).js?(x)'],
+ testMatch: ['**/(*.)(spec|test).[jt]s?(x)'],
globals: {
__APP_SLUG__: 'drive',
__TARGET__: 'browser',
diff --git a/src/drive/web/modules/views/Upload/UploaderComponent.spec.tsx b/src/drive/web/modules/views/Upload/UploaderComponent.spec.tsx
deleted file mode 100644
index eab7180806..0000000000
--- a/src/drive/web/modules/views/Upload/UploaderComponent.spec.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import React from 'react'
-import { render, RenderResult, waitFor } from '@testing-library/react'
-import '@testing-library/jest-dom/extend-expect'
-
-import { DumbUpload } from 'drive/mobile/modules/upload'
-import { generateForQueue } from 'drive/web/modules/views/Upload/UploadUtils'
-
-jest.mock('cozy-keys-lib', () => ({
- withVaultClient: jest.fn().mockReturnValue({})
-}))
-
-const tSpy = jest.fn()
-const uploadFilesFromNativeSpy = jest.fn()
-
-describe('DumbUpload component', () => {
- const defaultItems = [
- {
- fileName: 'File1.pdf',
- mimeType: 'application/pdf',
- extension: 'pdf',
- contentUri: 'file:///path/to/file.pdf',
- filePath: '/path/to/file.pdf',
- weblink: null,
- text: null,
- subject: null,
- dirId: '123',
- conflictStrategy: 'replace'
- }
- ]
-
- const setupComponent = (): RenderResult => {
- const props = {
- client: {},
- vaultClient: {},
- t: tSpy,
- uploadFilesFromNative: uploadFilesFromNativeSpy,
- stopMediaBackup: jest.fn(),
- router: jest.fn(),
- navigate: jest.fn()
- }
-
- return render()
- }
-
- describe('generateForQueue', () => {
- it('should generate the right object for the Drive queue', () => {
- const genetaredForQueue = generateForQueue(defaultItems)
- expect(genetaredForQueue).toEqual([
- { file: defaultItems[0], isDirectory: false }
- ])
- })
- })
-
- describe('Upload files', () => {
- it('should call uploadFileFromNative with the right arguments', async () => {
- const { rerender } = setupComponent()
- const folderId = 'io.cozy.root'
-
- rerender()
-
- await waitFor(() => {
- const genetaredForQueue = generateForQueue(defaultItems)
- expect(uploadFilesFromNativeSpy).toHaveBeenCalledWith(
- genetaredForQueue,
- folderId,
- expect.any(Function),
- { client: {}, vaultClient: {} }
- )
- })
- })
- })
-})
diff --git a/src/drive/web/modules/views/Upload/useResumeFromFlagship.spec.tsx b/src/drive/web/modules/views/Upload/useResumeFromFlagship.spec.tsx
new file mode 100644
index 0000000000..e684ecbeb7
--- /dev/null
+++ b/src/drive/web/modules/views/Upload/useResumeFromFlagship.spec.tsx
@@ -0,0 +1,141 @@
+import React from 'react'
+import { render, waitFor } from '@testing-library/react'
+import { useDispatch, useSelector } from 'react-redux'
+
+import { useResumeUploadFromFlagship } from 'drive/web/modules/views/Upload/useResumeFromFlagship'
+import { getProcessed, getSuccessful } from 'drive/web/modules/upload'
+import Alerter from 'cozy-ui/transpiled/react/deprecated/Alerter'
+import { WebviewService } from 'cozy-intent'
+
+global.jasmine = {
+ // @ts-expect-error - Test will fail if this is not set
+ testPath: ''
+}
+
+const mockUseDispatch = useDispatch as jest.Mock
+const mockGetProcessed = getProcessed as jest.Mock
+const mockGetSuccessful = getSuccessful as jest.Mock
+const mockUseSelector = useSelector as jest.Mock
+
+jest.mock('cozy-ui/transpiled/react/deprecated/Alerter', () => ({
+ success: jest.fn()
+}))
+
+jest.mock('cozy-intent', () => ({
+ useWebviewIntent: (): Partial => ({
+ call: () =>
+ Promise.resolve({
+ filesToHandle: [{ name: 'testFile' }]
+ }) as unknown as Promise
+ })
+}))
+
+jest.mock('react-redux', () => ({
+ useSelector: jest.fn(),
+ useDispatch: jest.fn(),
+ createSelectorHook: jest.fn()
+}))
+
+jest.mock('drive/web/modules/upload', () => ({
+ getUploadQueue: jest.fn(),
+ ADD_TO_UPLOAD_QUEUE: 'ADD_TO_UPLOAD_QUEUE',
+ getProcessed: jest.fn(),
+ getSuccessful: jest.fn()
+}))
+
+const TestComponent = (): JSX.Element => {
+ useResumeUploadFromFlagship()
+
+ return Test
+}
+
+describe('useResumeUploadFromFlagship', () => {
+ const mockDispatch = jest.fn()
+
+ beforeEach(() => {
+ jest.clearAllMocks()
+ mockUseDispatch.mockReturnValue(mockDispatch)
+ })
+
+ it('should not resume if there is no webview intent', () => {
+ mockGetProcessed.mockReturnValue([])
+ mockUseSelector.mockReturnValue([])
+ mockGetSuccessful.mockReturnValue([])
+
+ render()
+
+ expect(Alerter.success).not.toHaveBeenCalled()
+ })
+
+ it('should not attempt to resume uploads if uploadQueue already has items on initialization', () => {
+ mockGetProcessed.mockReturnValue([])
+ mockGetSuccessful.mockReturnValue([])
+ mockUseSelector.mockReturnValue([{ name: 'testFile' }])
+
+ render()
+
+ expect(mockDispatch).not.toHaveBeenCalledWith({
+ type: 'ADD_TO_UPLOAD_QUEUE',
+ files: ''
+ })
+ })
+
+ it('should dispatch files to the upload queue when webviewIntent returns files from hasFilesToHandle', async () => {
+ mockGetProcessed.mockReturnValue([])
+ mockUseSelector.mockReturnValue([])
+ mockGetSuccessful.mockReturnValue([])
+
+ render()
+
+ await waitFor(() => {
+ expect(mockDispatch).toHaveBeenCalledWith({
+ type: 'ADD_TO_UPLOAD_QUEUE',
+ files: [{ name: 'testFile' }]
+ })
+ })
+ })
+
+ it('should not call the alerter if upload is not finished', async () => {
+ mockGetProcessed.mockReturnValue([])
+ mockGetSuccessful.mockReturnValue([])
+ mockUseSelector.mockReturnValue([{ name: 'testFile' }])
+
+ render()
+
+ await waitFor(() => {
+ expect(Alerter.success).not.toHaveBeenCalled()
+ })
+ })
+
+ it('should not perform any action if webviewIntent returns an error stating "has not been implemented"', async () => {
+ mockGetProcessed.mockReturnValue([])
+ mockUseSelector.mockReturnValue([])
+ mockGetSuccessful.mockReturnValue([])
+ const mockError = new Error('has not been implemented')
+ jest.mock('cozy-intent', () => ({
+ useWebviewIntent: (): Partial => ({
+ call: () => Promise.reject(mockError)
+ })
+ }))
+
+ render()
+
+ await waitFor(() => {
+ expect(mockDispatch).not.toHaveBeenCalled()
+ })
+ })
+
+ it('should display a success message on completion', async () => {
+ mockGetProcessed.mockReturnValue([{ name: 'testFile' }])
+ mockUseSelector.mockReturnValue([{ name: 'testFile' }])
+ mockGetSuccessful.mockReturnValue([{ name: 'testFile' }])
+
+ render()
+
+ await waitFor(() => {
+ expect(Alerter.success).toHaveBeenCalledWith(expect.any(String), {
+ smart_count: 1
+ })
+ })
+ })
+})
diff --git a/src/drive/web/modules/views/Upload/useResumeFromFlagship.ts b/src/drive/web/modules/views/Upload/useResumeFromFlagship.ts
index 1ab31dfb6c..77391719b6 100644
--- a/src/drive/web/modules/views/Upload/useResumeFromFlagship.ts
+++ b/src/drive/web/modules/views/Upload/useResumeFromFlagship.ts
@@ -62,6 +62,9 @@ export const useResumeUploadFromFlagship = (): void => {
const processed = (getProcessed(state) as () => unknown[]).length
const queued = uploadQueue.length
+ // If there are no files processed, we are not in the upload flow
+ if (processed === 0) return
+
// Assuming that the upload is finished if all files have been processed (success or error)
if (processed === queued) {
const successful = (getSuccessful(state) as () => unknown[]).length