Skip to content
This repository has been archived by the owner on Nov 19, 2018. It is now read-only.

Commit

Permalink
fix(PauseResumeButton): concurrent chunking & resume is not properly …
Browse files Browse the repository at this point in the history
…supported

fixes #151
  • Loading branch information
rnicholus committed Oct 4, 2017
1 parent 03983fb commit 09cc16d
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 42 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-fine-uploader",
"version": "1.0.6",
"version": "1.0.7",
"license": "MIT",
"description": "React UI components for using Fine Uploader in a React-based project.",
"author": {
Expand Down
79 changes: 45 additions & 34 deletions src/pause-resume-button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class PauseResumeButton extends Component {
super(props)

this.state = {
atLeastOneChunkUploaded: false,
pausable: false,
resumable: false
}
Expand All @@ -26,25 +27,24 @@ class PauseResumeButton extends Component {

this._onStatusChange = (id, oldStatus, newStatus) => {
if (id === this.props.id && !this._unmounted) {
const pausable = newStatus === statusEnum.UPLOADING
const resumable = !pausable && newStatus === statusEnum.PAUSED
const pausable = newStatus === statusEnum.UPLOADING && this.state.atLeastOneChunkUploaded
const resumable = newStatus === statusEnum.PAUSED

if (!pausable && this.state.pausable) {
this.setState({ pausable, resumable })
if (pausable !== this.state.pausable) {
this.setState({ pausable })
}
else if (resumable && !this.state.resumable) {
this.setState({ pausable, resumable })
if (resumable !== this.state.resumable) {
this.setState({ resumable })
}
else if (!resumable && this.state.resumable) {
this.setState({ pausable, resumable })
}
else if (

if (
newStatus === statusEnum.DELETED
|| newStatus === statusEnum.CANCELED
|| newStatus === statusEnum.UPLOAD_SUCCESSFUL
) {
this._unregisterStatusChangeHandler()
this._unregisterOnUploadChunkHandler()
this._unregisterOnResumeHandler()
this._unregisterOnStatusChangeHandler()
this._unregisterOnUploadChunkSuccessHandler()
}
}
}
Expand All @@ -58,34 +58,45 @@ class PauseResumeButton extends Component {
}
}

this._onUploadChunk = (id, name, chunkData) => {
if (id === this.props.id && !this._unmounted) {
if (chunkData.partIndex > 0 && !this.state.pausable) {
this.setState({
pausable: true,
resumable: false
})
}
else if (chunkData.partIndex === 0 && this.state.pausable) {
this.setState({
pausable: false,
resumable: false
})
}
this._onResume = id => {
if (id === this.props.id
&& !this._unmounted
&& !this.state.atLeastOneChunkUploaded) {

this.setState({
atLeastOneChunkUploaded: true,
pausable: true,
resumable: false
})
}
}

this._onUploadChunkSuccess = id => {
if (id === this.props.id
&& !this._unmounted
&& !this.state.atLeastOneChunkUploaded) {

this.setState({
atLeastOneChunkUploaded: true,
pausable: true,
resumable: false
})
}
}
}


componentDidMount() {
this.props.uploader.on('resume', this._onResume)
this.props.uploader.on('statusChange', this._onStatusChange)
this.props.uploader.on('uploadChunk', this._onUploadChunk)
this.props.uploader.on('uploadChunkSuccess', this._onUploadChunkSuccess)
}

componentWillUnmount() {
this._unmounted = true
this._unregisterOnResumeHandler()
this._unregisterOnStatusChangeHandler()
this._unregisterOnUploadChunkHandler()
this._unregisterOnUploadChunkSuccessHandler()
}

render() {
Expand All @@ -108,16 +119,16 @@ class PauseResumeButton extends Component {
return null
}

_unregisterOnStatusChangeHandler() {
this.props.uploader.off('statusChange', this._onStatusChange)
_unregisterOnResumeHandler() {
this.props.uploader.off('resume', this._onResume)
}

_unregisterOnUploadChunkHandler() {
this.props.uploader.off('uploadChunk', this._onUploadChunk)
_unregisterOnStatusChangeHandler() {
this.props.uploader.off('statusChange', this._onStatusChange)
}

_unregisterStatusChangeHandler() {
this.props.uploader.off('statusChange', this._onStatusChange)
_unregisterOnUploadChunkSuccessHandler() {
this.props.uploader.off('uploadChunkSuccess', this._onUploadChunkSuccess)
}
}

Expand Down
44 changes: 37 additions & 7 deletions src/test/unit/pause-resume-button.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import FineUploaderTraditional from 'fine-uploader-wrappers'
import PauseResumeButton from 'src/pause-resume-button'

describe('<PauseResumeButton />', () => {
let statusChangeCallback, uploadChunkCallback, uploader
let resumeCallback,
statusChangeCallback,
uploadChunkSuccessCallback,
uploader

beforeEach(() => {
uploader = new FineUploaderTraditional({options: {}})
Expand All @@ -14,8 +17,11 @@ describe('<PauseResumeButton />', () => {
if (type === 'statusChange') {
statusChangeCallback = callback
}
else if (type === 'uploadChunk') {
uploadChunkCallback = callback
else if (type === 'uploadChunkSuccess') {
uploadChunkSuccessCallback = callback
}
else if (type === 'resume') {
resumeCallback = callback
}
})
})
Expand All @@ -25,11 +31,10 @@ describe('<PauseResumeButton />', () => {
<PauseResumeButton id={ 0 } uploader={ uploader } />
)

uploadChunkCallback(0, 'foo.jpeg', { partIndex: 0 })
let button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-button')[0]
expect(button).toBeFalsy()

uploadChunkCallback(0, 'foo.jpeg', { partIndex: 1 })
uploadChunkSuccessCallback(0, { partIndex: 3 })
button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-button')[0]
expect(button).toBeTruthy()
})
Expand All @@ -39,9 +44,9 @@ describe('<PauseResumeButton />', () => {
<PauseResumeButton id={ 0 } uploader={ uploader } />
)

uploadChunkCallback(0, 'foo.jpeg', { partIndex: 1 })
uploadChunkSuccessCallback(0, { partIndex: 1 })
statusChangeCallback(0, null, 'deleted')
let button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-button')[0]
const button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-button')[0]
expect(button).toBeFalsy()
})

Expand All @@ -50,17 +55,42 @@ describe('<PauseResumeButton />', () => {
<PauseResumeButton id={ 0 } uploader={ uploader } />
)

uploadChunkSuccessCallback(0, { partIndex: 7 })

statusChangeCallback(0, null, 'paused')
let button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-resume-button')[0]
expect(button).toBeTruthy()

const resumeUploadMethod = spyOn(uploader.methods, 'continueUpload')
TestUtils.Simulate.click(button)
expect(resumeUploadMethod).toHaveBeenCalledWith(0)

statusChangeCallback(0, null, 'uploading')
button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-resume-button')[0]
expect(button).toBeTruthy()
expect(button.className.indexOf('react-fine-uploader-pause-button')).not.toBe(-1)
expect(button.className.indexOf('react-fine-uploader-resume-button')).toBe(-1)

const pauseUploadMethod = spyOn(uploader.methods, 'pauseUpload')
TestUtils.Simulate.click(button)
expect(pauseUploadMethod).toHaveBeenCalledWith(0)
statusChangeCallback(0, null, 'paused')
button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-resume-button')[0]
expect(button).toBeTruthy()
expect(button.className.indexOf('react-fine-uploader-pause-button')).toBe(-1)
expect(button.className.indexOf('react-fine-uploader-resume-button')).not.toBe(-1)
})

it('allows a resumed file to be paused immediately', () => {
const PauseResumeButtonComponent = TestUtils.renderIntoDocument(
<PauseResumeButton id={ 0 } uploader={ uploader } />
)

resumeCallback(0, { partIndex: 3 })

let button = TestUtils.scryRenderedDOMComponentsWithClass(PauseResumeButtonComponent, 'react-fine-uploader-pause-button')[0]
expect(button).toBeTruthy()
expect(button.className.indexOf('react-fine-uploader-pause-button')).not.toBe(-1)
expect(button.className.indexOf('react-fine-uploader-resume-button')).toBe(-1)
})
})

0 comments on commit 09cc16d

Please sign in to comment.