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