Skip to content

Commit

Permalink
Add had* states to request module
Browse files Browse the repository at this point in the history
Add a permanent flag to the request module for knowing when a request
had ever been succeeded or errored (even if cleared)
  • Loading branch information
MonkeyAndres committed Mar 12, 2021
1 parent 8a442ca commit 66e44eb
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 9 deletions.
32 changes: 23 additions & 9 deletions lib/request/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const STATES = {
const INITIAL_STATE = {
state: STATES.EMPTY,
error: undefined,

hadSucceeded: false,
hadErrored: false,
}

const makeRequestReducer = ({ start, success, error, clear }) => (
Expand All @@ -18,52 +21,63 @@ const makeRequestReducer = ({ start, success, error, clear }) => (
) => {
if (matchPattern(start, action)) {
return {
...state,
state: STATES.REQUESTING,
error: undefined,
}
}

if (matchPattern(success, action)) {
return {
...state,
state: STATES.SUCCESS,
error: undefined,
hadSucceeded: true,
}
}

if (matchPattern(error, action)) {
return {
...state,
state: STATES.ERROR,
error: action.payload,
hadErrored: true,
}
}

if (matchPattern(clear, action)) {
return INITIAL_STATE
return {
...INITIAL_STATE,
hadSucceeded: state.hadSucceeded,
hadErrored: state.hadErrored,
}
}

return state
}

makeRequestReducer.getIsEmpty = state =>
state.state === STATES.EMPTY
makeRequestReducer.getIsEmpty = state => state.state === STATES.EMPTY

makeRequestReducer.getIsRequesting = state =>
state.state === STATES.REQUESTING
makeRequestReducer.getIsRequesting = state => state.state === STATES.REQUESTING

makeRequestReducer.getIsRequestSucceeded = state =>
state.state === STATES.SUCCESS

makeRequestReducer.getIsError = state =>
state.state === STATES.ERROR
makeRequestReducer.getIsError = state => state.state === STATES.ERROR

makeRequestReducer.getError = state =>
state.error
makeRequestReducer.getError = state => state.error

makeRequestReducer.getIsLoading = state =>
state.state === STATES.EMPTY || state.state === STATES.REQUESTING

makeRequestReducer.getIsDone = state =>
!makeRequestReducer.getIsLoading(state)

makeRequestReducer.getHadSucceeded = state => state.hadSucceeded

makeRequestReducer.getHadErrored = state => state.hadErrored

makeRequestReducer.getHadCompleted = state => state.hadSucceeded || state.hadErrored

makeRequestReducer.STATES = STATES

Expand Down
75 changes: 75 additions & 0 deletions lib/request/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ describe('request', () => {
expect(request.getError(nextState)).toEqual(undefined)
expect(request.getIsLoading(nextState)).toEqual(true)
expect(request.getIsDone(nextState)).toEqual(false)
expect(request.getHadSucceeded(nextState)).toEqual(false)
expect(request.getHadErrored(nextState)).toEqual(false)
expect(request.getHadCompleted(nextState)).toEqual(false)
})
})

Expand All @@ -28,6 +31,9 @@ describe('request', () => {
expect(request.getError(nextState)).toEqual(undefined)
expect(request.getIsLoading(nextState)).toEqual(true)
expect(request.getIsDone(nextState)).toEqual(false)
expect(request.getHadSucceeded(nextState)).toEqual(false)
expect(request.getHadErrored(nextState)).toEqual(false)
expect(request.getHadCompleted(nextState)).toEqual(false)
})

it('success', () => {
Expand All @@ -41,6 +47,9 @@ describe('request', () => {
expect(request.getError(nextState)).toEqual(undefined)
expect(request.getIsLoading(nextState)).toEqual(false)
expect(request.getIsDone(nextState)).toEqual(true)
expect(request.getHadSucceeded(nextState)).toEqual(true)
expect(request.getHadErrored(nextState)).toEqual(false)
expect(request.getHadCompleted(nextState)).toEqual(true)
})

it('error', () => {
Expand All @@ -54,6 +63,9 @@ describe('request', () => {
expect(request.getError(nextState)).toEqual('foobar')
expect(request.getIsLoading(nextState)).toEqual(false)
expect(request.getIsDone(nextState)).toEqual(true)
expect(request.getHadSucceeded(nextState)).toEqual(false)
expect(request.getHadErrored(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)
})

it('clear', () => {
Expand All @@ -67,6 +79,69 @@ describe('request', () => {
expect(request.getError(nextState)).toEqual(undefined)
expect(request.getIsLoading(nextState)).toEqual(true)
expect(request.getIsDone(nextState)).toEqual(false)
expect(request.getHadSucceeded(nextState)).toEqual(false)
expect(request.getHadErrored(nextState)).toEqual(false)
expect(request.getHadCompleted(nextState)).toEqual(false)
})
})

describe('Preserves had* states', () => {
it('preserves hadSuccess', () => {
const reducer = request({
start: 'START',
success: 'SUCCESS',
error: 'ERROR',
clear: 'CLEAR',
})

let nextState = reducer(undefined, { type: 'SUCCESS' })

expect(request.getHadSucceeded(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'START' })

expect(request.getHadSucceeded(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'CLEAR' })

expect(request.getHadSucceeded(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'ERROR' })

expect(request.getHadSucceeded(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)
})

it('preserves hadSuccess', () => {
const reducer = request({
start: 'START',
success: 'SUCCESS',
error: 'ERROR',
clear: 'CLEAR',
})

let nextState = reducer(undefined, { type: 'ERROR' })

expect(request.getHadErrored(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'START' })

expect(request.getHadErrored(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'CLEAR' })

expect(request.getHadErrored(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'SUCCESS' })

expect(request.getHadErrored(nextState)).toEqual(true)
expect(request.getHadCompleted(nextState)).toEqual(true)
})
})
})
9 changes: 9 additions & 0 deletions lib/requestById/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ makeRequestByIdReducer.getIsLoadingById = id =>
makeRequestByIdReducer.getIsDoneById = id =>
F.pipe(makeRequestByIdReducer.getById(id), request.getIsDone)

makeRequestByIdReducer.getHadSucceededById = id =>
F.pipe(makeRequestByIdReducer.getById(id), request.getHadSucceeded)

makeRequestByIdReducer.getHadErroredById = id =>
F.pipe(makeRequestByIdReducer.getById(id), request.getHadErrored)

makeRequestByIdReducer.getHadCompletedById = id =>
F.pipe(makeRequestByIdReducer.getById(id), request.getHadCompleted)

makeRequestByIdReducer.STATES = request.STATES

export default makeRequestByIdReducer
75 changes: 75 additions & 0 deletions lib/requestById/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ describe('requestById', () => {
expect(requestById.getErrorById('foo')(nextState)).toEqual(undefined)
expect(requestById.getIsLoadingById('foo')(nextState)).toEqual(true)
expect(requestById.getIsDoneById('foo')(nextState)).toEqual(false)
expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(false)
expect(requestById.getHadErroredById('foo')(nextState)).toEqual(false)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(false)
})
})

Expand All @@ -28,6 +31,9 @@ describe('requestById', () => {
expect(requestById.getErrorById('foo')(nextState)).toEqual(undefined)
expect(requestById.getIsLoadingById('foo')(nextState)).toEqual(true)
expect(requestById.getIsDoneById('foo')(nextState)).toEqual(false)
expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(false)
expect(requestById.getHadErroredById('foo')(nextState)).toEqual(false)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(false)
})

it('success', () => {
Expand All @@ -41,6 +47,9 @@ describe('requestById', () => {
expect(requestById.getErrorById('foo')(nextState)).toEqual(undefined)
expect(requestById.getIsLoadingById('foo')(nextState)).toEqual(false)
expect(requestById.getIsDoneById('foo')(nextState)).toEqual(true)
expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(true)
expect(requestById.getHadErroredById('foo')(nextState)).toEqual(false)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)
})

it('error', () => {
Expand All @@ -57,6 +66,9 @@ describe('requestById', () => {
expect(requestById.getErrorById('foo')(nextState)).toEqual('error')
expect(requestById.getIsLoadingById('foo')(nextState)).toEqual(false)
expect(requestById.getIsDoneById('foo')(nextState)).toEqual(true)
expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(false)
expect(requestById.getHadErroredById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)
})

it('clear', () => {
Expand All @@ -70,6 +82,69 @@ describe('requestById', () => {
expect(requestById.getErrorById('foo')(nextState)).toEqual(undefined)
expect(requestById.getIsLoadingById('foo')(nextState)).toEqual(true)
expect(requestById.getIsDoneById('foo')(nextState)).toEqual(false)
expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(false)
expect(requestById.getHadErroredById('foo')(nextState)).toEqual(false)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(false)
})
})

describe('Preserves had* states', () => {
it('preserves hadSuccess', () => {
const reducer = requestById({
start: 'START',
success: 'SUCCESS',
error: 'ERROR',
clear: 'CLEAR',
})

let nextState = reducer(undefined, { type: 'SUCCESS', payload: { id: 'foo' } })

expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'START', payload: { id: 'foo' } })

expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'CLEAR', payload: { id: 'foo' } })

expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'ERROR', payload: { id: 'foo' } })

expect(requestById.getHadSucceededById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)
})

it('preserves hadSuccess', () => {
const reducer = requestById({
start: 'START',
success: 'SUCCESS',
error: 'ERROR',
clear: 'CLEAR',
})

let nextState = reducer(undefined, { type: 'ERROR', payload: { id: 'foo' } })

expect(requestById.getHadErroredById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'START', payload: { id: 'foo' } })

expect(requestById.getHadErroredById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'CLEAR', payload: { id: 'foo' } })

expect(requestById.getHadErroredById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)

nextState = reducer(nextState, { type: 'SUCCESS', payload: { id: 'foo' } })

expect(requestById.getHadErroredById('foo')(nextState)).toEqual(true)
expect(requestById.getHadCompletedById('foo')(nextState)).toEqual(true)
})
})
})

0 comments on commit 66e44eb

Please sign in to comment.