Skip to content

Commit

Permalink
feat(guards): allow guards to return a value instead of calling next (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Jul 21, 2020
1 parent 3475486 commit 5cb209f
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 2 deletions.
122 changes: 122 additions & 0 deletions __tests__/guards/guardToPromiseFn.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,126 @@ describe('guardToPromiseFn', () => {
expect(err).toBe(error)
}
})

describe('no next argument', () => {
it('rejects if returns false', async () => {
expect.assertions(1)
try {
await guardToPromiseFn((to, from) => false, to, from)()
} catch (err) {
expect(err).toMatchObject({
from,
to,
type: ErrorTypes.NAVIGATION_ABORTED,
})
}
})

it('resolves no value is returned', async () => {
await expect(
guardToPromiseFn((to, from) => {}, to, from)()
).resolves.toEqual(undefined)
})

it('resolves if true is returned', async () => {
await expect(
guardToPromiseFn((to, from) => true, to, from)()
).resolves.toEqual(undefined)
})

it('rejects if false is returned', async () => {
expect.assertions(1)
try {
await guardToPromiseFn((to, from) => false, to, from)()
} catch (err) {
expect(err).toMatchObject({
from,
to,
type: ErrorTypes.NAVIGATION_ABORTED,
})
}
})

it('rejects if async false is returned', async () => {
expect.assertions(1)
try {
await guardToPromiseFn(async (to, from) => false, to, from)()
} catch (err) {
expect(err).toMatchObject({
from,
to,
type: ErrorTypes.NAVIGATION_ABORTED,
})
}
})

it('rejects if a string location is returned', async () => {
expect.assertions(1)
try {
await guardToPromiseFn((to, from) => '/new', to, from)()
} catch (err) {
expect(err).toMatchObject({
from: to,
to: '/new',
type: ErrorTypes.NAVIGATION_GUARD_REDIRECT,
})
}
})

it('rejects if an object location is returned', async () => {
expect.assertions(1)
let redirectTo = { path: '/new' }
try {
await guardToPromiseFn((to, from) => redirectTo, to, from)()
} catch (err) {
expect(err).toMatchObject({
from: to,
to: redirectTo,
type: ErrorTypes.NAVIGATION_GUARD_REDIRECT,
})
}
})

it('rejects if an error is returned', async () => {
expect.assertions(1)
let error = new Error('nope')
try {
await guardToPromiseFn((to, from) => error, to, from)()
} catch (err) {
expect(err).toBe(error)
}
})

it('rejects if guard rejects a Promise', async () => {
expect.assertions(1)
let error = new Error('nope')
try {
await guardToPromiseFn(
async (to, from) => {
throw error
},
to,
from
)()
} catch (err) {
expect(err).toBe(error)
}
})

it('rejects if guard throws an error', async () => {
expect.assertions(1)
let error = new Error('nope')
try {
await guardToPromiseFn(
(to, from) => {
throw error
},
to,
from
)()
} catch (err) {
expect(err).toBe(error)
}
})
})
})
7 changes: 5 additions & 2 deletions src/navigationGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,17 @@ export function guardToPromiseFn(
}

// wrapping with Promise.resolve allows it to work with both async and sync guards
Promise.resolve(
let guardCall = Promise.resolve(
guard.call(
record && record.instances[name!],
to,
from,
__DEV__ ? canOnlyBeCalledOnce(next, to, from) : next
)
).catch(err => reject(err))
)

if (guard.length < 3) guardCall.then(next)
guardCall.catch(err => reject(err))
})
}

Expand Down

0 comments on commit 5cb209f

Please sign in to comment.