Skip to content

Commit

Permalink
fix: Do not display Alerter on empty uploads
Browse files Browse the repository at this point in the history
- Previously an empty uploadQueue was considered a success on app load
- Fix by verifying that processed/queued have a length
- Add unit tests to cover that fix
- Delete old unit test from DumbUploadComponent,
this test is not testing anything at the moment
  • Loading branch information
acezard committed Oct 31, 2023
1 parent 482affc commit 4ddcd10
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 73 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
72 changes: 0 additions & 72 deletions src/drive/web/modules/views/Upload/UploaderComponent.spec.tsx

This file was deleted.

141 changes: 141 additions & 0 deletions src/drive/web/modules/views/Upload/useResumeFromFlagship.spec.tsx
Original file line number Diff line number Diff line change
@@ -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<WebviewService> => ({
call: () =>
Promise.resolve({
filesToHandle: [{ name: 'testFile' }]
}) as unknown as Promise<boolean>
})
}))

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 <div>Test</div>
}

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(<TestComponent />)

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(<TestComponent />)

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(<TestComponent />)

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(<TestComponent />)

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<WebviewService> => ({
call: () => Promise.reject(mockError)
})
}))

render(<TestComponent />)

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(<TestComponent />)

await waitFor(() => {
expect(Alerter.success).toHaveBeenCalledWith(expect.any(String), {
smart_count: 1
})
})
})
})
3 changes: 3 additions & 0 deletions src/drive/web/modules/views/Upload/useResumeFromFlagship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4ddcd10

Please sign in to comment.