Skip to content

Commit

Permalink
fix: stop delegating resume/play to controller. (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
morganney authored Sep 17, 2022
1 parent cb3dfc7 commit 640b108
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 17 deletions.
5 changes: 3 additions & 2 deletions __tests__/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('TextToSpeech', () => {
act(() => {
fireEvent.click(getByRole('button', { name: 'Play' }))
})
expect(global.speechSynthesis.cancel).toHaveBeenCalled()
expect(global.speechSynthesis.speak).toHaveBeenCalled()
expect(getByRole('button', { name: 'Pause' })).toBeInTheDocument()

Expand All @@ -39,8 +40,8 @@ describe('TextToSpeech', () => {
fireEvent.click(getByRole('button', { name: 'Mute' }))
})
expect(onMuteToggled).toHaveBeenCalledWith(false)
// Because we are currently paused (so no reset)
expect(global.speechSynthesis.cancel).not.toHaveBeenCalled()
// Cancel only called once thus far as we are currently paused (so no reset)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(1)
expect(global.speechSynthesis.resume).not.toHaveBeenCalled()
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(1)
})
Expand Down
15 changes: 10 additions & 5 deletions __tests__/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ describe('Controller', () => {
expect(controller.preservesPitch).toBe(false)
expect(controller.paused).toBe(false)
controller.play()
// Cancel before play to clear any utterances in the queue
expect(global.speechSynthesis.cancel).toHaveBeenCalled()
expect(global.speechSynthesis.speak).toHaveBeenCalledWith(
expect.objectContaining({ text: SpeechSynthesisMock.textForTest })
)
Expand All @@ -76,21 +78,22 @@ describe('Controller', () => {
controller.resume()
expect(global.speechSynthesis.resume).toHaveBeenCalled()
controller.clear()
expect(global.speechSynthesis.cancel).toHaveBeenCalled()
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(2)
controller.play()
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(2)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(3)
controller.mute()
expect(global.speechSynthesis.resume).toHaveBeenCalledTimes(2)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(2)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(4)
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(3)
controller.unmute(0.5)
expect(controller.volume).toBe(0.5)
expect(global.speechSynthesis.resume).toHaveBeenCalledTimes(3)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(3)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(5)
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(4)
controller.reset()
expect(global.speechSynthesis.resume).toHaveBeenCalledTimes(4)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(4)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(6)
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(5)
})

Expand Down Expand Up @@ -131,8 +134,10 @@ describe('Controller', () => {
controller.reset()
expect(global.HTMLMediaElement.prototype.load).toHaveBeenCalled()
expect(global.HTMLMediaElement.prototype.play).toHaveBeenCalledTimes(3)
// Play request a clear() which for HTMLAudioElement calls pause
expect(global.HTMLAudioElement.prototype.pause).toHaveBeenCalledTimes(2)
controller.clear()
expect(global.HTMLMediaElement.prototype.pause).toHaveBeenCalledTimes(2)
expect(global.HTMLMediaElement.prototype.pause).toHaveBeenCalledTimes(3)
expect(synth.currentTime).toBe(0)

// Check that the rate getter/setter abstracts playbackRate
Expand Down
5 changes: 3 additions & 2 deletions __tests__/hook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ describe('useTts', () => {
act(() => {
result.current.onPlay()
})
expect(global.speechSynthesis.cancel).toHaveBeenCalled()
expect(result.current.state.isPlaying).toBe(true)

// Now mute while playing against a SpeechSynthesis instance of the backing controller
Expand All @@ -169,7 +170,7 @@ describe('useTts', () => {
* This is effectively an onReset().
*/
expect(global.speechSynthesis.resume).toHaveBeenCalled()
expect(global.speechSynthesis.cancel).toHaveBeenCalled()
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(2)
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(2)
expect(result.current.state.isPlaying).toBe(true)

Expand All @@ -186,7 +187,7 @@ describe('useTts', () => {
})
expect(result.current.state.isPaused).toBe(false)
expect(global.speechSynthesis.resume).toHaveBeenCalledTimes(2)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(2)
expect(global.speechSynthesis.cancel).toHaveBeenCalledTimes(3)
expect(global.speechSynthesis.speak).toHaveBeenCalledTimes(3)
expect(result.current.state.isPlaying).toBe(true)
})
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tts-react",
"version": "0.8.0",
"version": "0.8.1",
"description": "React component to convert text to speech.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
6 changes: 3 additions & 3 deletions src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,9 @@ class Controller extends EventTarget {
}

async play(): Promise<void> {
if (this.paused) {
await this.resume()
} else if (this.synthesizer instanceof HTMLAudioElement) {
this.clear()

if (this.synthesizer instanceof HTMLAudioElement) {
await this.playHtmlAudio()
} else {
this.synthesizer.speak(this.target as SpeechSynthesisUtterance)
Expand Down
9 changes: 7 additions & 2 deletions src/hook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,14 @@ const useTts = ({
[lang, voice, fetchAudioData, markTextAsSpoken]
)
const onPlay = useCallback(() => {
controller.play()
if (state.isPaused) {
controller.resume()
} else {
controller.play()
}

dispatch({ type: 'play' })
}, [controller])
}, [controller, state.isPaused])
const onPause = useCallback(() => {
controller.pause()
dispatch({ type: 'pause' })
Expand Down

0 comments on commit 640b108

Please sign in to comment.