Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tysky committed Nov 20, 2023
1 parent 456fc85 commit 7188fcf
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 41 deletions.
5 changes: 2 additions & 3 deletions dist/auther-client.cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,14 +657,13 @@ var AutherClient = /*#__PURE__*/_createClass(function AutherClient(_ref) {
getTokens: getTokens,
saveTokens: saveTokens
});
_context2.next = 10;
_context2.next = 9;
break;
case 6:
_context2.prev = 6;
_context2.t0 = _context2["catch"](0);
_this.logger.error("Error during tokens refreshing at ".concat(new Date(), " [").concat(new Date().toUTCString(), "]"));
throw _context2.t0;
case 10:
case 9:
case "end":
return _context2.stop();
}
Expand Down
5 changes: 2 additions & 3 deletions dist/auther-client.es.js
Original file line number Diff line number Diff line change
Expand Up @@ -655,14 +655,13 @@ var AutherClient = /*#__PURE__*/_createClass(function AutherClient(_ref) {
getTokens: getTokens,
saveTokens: saveTokens
});
_context2.next = 10;
_context2.next = 9;
break;
case 6:
_context2.prev = 6;
_context2.t0 = _context2["catch"](0);
_this.logger.error("Error during tokens refreshing at ".concat(new Date(), " [").concat(new Date().toUTCString(), "]"));
throw _context2.t0;
case 10:
case 9:
case "end":
return _context2.stop();
}
Expand Down
1 change: 0 additions & 1 deletion src/client/AutherClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export class AutherClient {
this.logger.error(
`Error during tokens refreshing at ${new Date()} [${new Date().toUTCString()}]`,
)
throw error
}
}, refreshTimeout)
}
Expand Down
148 changes: 114 additions & 34 deletions tests/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,54 @@ const APPCODE = "appcode"
const AUTHER_URL = "http://localhost/"
const TEST_AUTHORIZATION_CODE = "75e1cece-2991-4be5-9fb4-c6968e5f3311"

const createAutherClient = () => {
const createAutherClient = (params = {}) => {
return AutherClient.init({
autherUrl: AUTHER_URL,
redirectUri: RETURN_URI,
appcode: APPCODE,
http: doFetch(AUTHER_URL),
...params,
})
}

const getTokenPayload = expDate => {
const expiredAt = expDate ? new Date(expDate) : new Date()
const issuedAt = new Date(expiredAt)
expiredAt.setHours(expiredAt.getHours() + 1)
if (!expDate) {
expiredAt.setHours(expiredAt.getHours() + 1)
}
const iat = issuedAt.getTime() / 1000 // in seconds
const exp = expiredAt.getTime() / 1000 // in seconds
return { iat, exp }
}

const getToken = (params = {}) => {
const payload = btoa(JSON.stringify({ ...getTokenPayload(), ...params }))
const { expDate, type } = params
const payload = btoa(JSON.stringify({ ...getTokenPayload(expDate), type }))
const header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
const signature = "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
const jwtLikeToken = `${header}.${payload}.${signature}`
return jwtLikeToken
}

const getAccessToken = (params = {}) => {
return getToken({ type: "access", ...params })
const getAccessToken = expDate => {
return getToken({ type: "access", expDate })
}

const getRefreshToken = (params = {}) => {
return getToken({ type: "refresh", ...params })
const getRefreshToken = expDate => {
return getToken({ type: "refresh", expDate })
}

const getAuthCallbacks = ({ accessTokenExpDate, refreshTokenExpDate } = {}) => {
let accessToken = getAccessToken(accessTokenExpDate)
let refreshToken = getRefreshToken(refreshTokenExpDate)
const getTokens = () => ({ accessToken, refreshToken })
const saveTokens = (tokens = {}) => {
if (tokens.accessToken) accessToken = tokens.accessToken
if (tokens.refreshToken) refreshToken = tokens.refreshToken
}

return { getTokens, saveTokens }
}

describe("When use auther methods", () => {
Expand Down Expand Up @@ -125,25 +141,25 @@ describe("When use auther methods", () => {
})

describe("authenticate method", () => {
beforeEach(() => {
jest.useFakeTimers()
})

it("should authenticate with fresh tokens", async () => {
fetch.mockResponseOnce(JSON.stringify({
accessToken: getAccessToken(),
refreshToken: getRefreshToken(),
}))
jest.useFakeTimers()

const auth = createAutherClient()
const accessToken = getAccessToken()
const refreshToken = getRefreshToken()
const getTokens = () => ({ accessToken, refreshToken })
const saveTokens = () => {}
const callbacks = getAuthCallbacks()

await expect(() => auth.authentication({ getTokens, saveTokens })).not.toThrowError()
await expect(() => auth.authentication(callbacks)).not.toThrowError()

jest.runOnlyPendingTimers()

const expectedUrl = "http://localhost/tokens/refresh"
const expectedBody = JSON.stringify({ refreshToken })
const expectedBody = JSON.stringify({ refreshToken: callbacks.getTokens().refreshToken })
const expectedHeaders = {
"Content-Type": "application/json",
Accept: "application/json",
Expand All @@ -161,26 +177,18 @@ describe("When use auther methods", () => {
accessToken: getAccessToken(),
refreshToken: getRefreshToken(),
}))
jest.useFakeTimers()

const auth = createAutherClient()
const expiredDate = new Date()
expiredDate.setHours(expiredDate.getHours() - 3)

let accessToken = getAccessToken(getTokenPayload(expiredDate))
let refreshToken = getRefreshToken()
const getTokens = () => ({ accessToken, refreshToken })
const saveTokens = (tokens = {}) => {
if (tokens.accessToken) accessToken = tokens.accessToken
if (tokens.refreshToken) refreshToken = tokens.refreshToken
}

await expect(() => auth.authentication({ getTokens, saveTokens })).not.toThrowError()
const callbacks = getAuthCallbacks({ accessTokenExpDate: expiredDate })
await expect(() => auth.authentication(callbacks)).not.toThrowError()

jest.runOnlyPendingTimers()

const expectedUrl = "http://localhost/tokens/refresh"
const expectedBody = JSON.stringify({ refreshToken })
const expectedBody = JSON.stringify({ refreshToken: callbacks.getTokens().refreshToken })
const expectedHeaders = {
"Content-Type": "application/json",
Accept: "application/json",
Expand All @@ -193,25 +201,97 @@ describe("When use auther methods", () => {
})
})

it("should log error when refresh token expired", async () => {
fetch.mockResponseOnce(JSON.stringify({
accessToken: getAccessToken(),
refreshToken: getRefreshToken(),
}))
const mockLogger = { log: jest.fn(), error: jest.fn() }

const auth = createAutherClient({ logger: mockLogger })
const expiredDate = new Date()
expiredDate.setHours(expiredDate.getHours() - 3)
const callbacks = getAuthCallbacks({ refreshTokenExpDate: expiredDate })

await expect(() => auth.authentication(callbacks)).not.toThrowError()

jest.runAllTimers()

mockLogger.error.mockImplementationOnce(() => {
expect(mockLogger.error).toHaveBeenCalledWith(
`Error during tokens refreshing at ${new Date()} [${new Date().toUTCString()}]`,
)
})
})

it("should throw error when both tokens expired", async () => {
const auth = createAutherClient()
const expiredDate = new Date()
expiredDate.setHours(expiredDate.getHours() - 3)
let accessToken = getAccessToken(getTokenPayload(expiredDate))
let refreshToken = getRefreshToken(getTokenPayload(expiredDate))

const getTokens = () => ({ accessToken, refreshToken })
const saveTokens = (tokens = {}) => {
if (tokens.accessToken) accessToken = tokens.accessToken
if (tokens.refreshToken) refreshToken = tokens.refreshToken
}
const callbacks = getAuthCallbacks({
accessTokenExpDate: expiredDate,
refreshTokenExpDate: expiredDate,
})

await expect(() => auth.authentication({ getTokens, saveTokens }))
await expect(() => auth.authentication(callbacks))
.rejects
.toThrow("token.expired")

expect(fetch).not.toHaveBeenCalled()
})

it("should log error when server fails to refresh tokens", async () => {
const mockLogger = { log: jest.fn(), error: jest.fn() }
const auth = createAutherClient({ logger: mockLogger })

fetch.mockRejectOnce()

const callbacks = getAuthCallbacks()

await expect(() => auth.authentication(callbacks)).not.toThrowError()

jest.runAllTimers()

mockLogger.error.mockImplementationOnce(() => {
expect(mockLogger.error).toHaveBeenCalledWith(
`Error during tokens refreshing at ${new Date()} [${new Date().toUTCString()}]`,
)
})
})

it("should set min refreshTimeout to one minute", async () => {
const mockLogger = { log: jest.fn() }

const auth = createAutherClient({ logger: mockLogger })
const expiredDate = new Date()
expiredDate.setSeconds(expiredDate.getSeconds() + 30)
const callbacks = getAuthCallbacks({ accessTokenExpDate: expiredDate })

await auth.authentication(callbacks)

const expectedRefreshDate = new Date(Date.now() + 60 * 1000) // one minute

expect(mockLogger.log).toHaveBeenCalledWith(
`Token will be refreshed at ${expectedRefreshDate} [${expectedRefreshDate.toUTCString()}]`,
)
})

it("should set max refreshTimeout to one day", async () => {
const mockLogger = { log: jest.fn() }

const auth = createAutherClient({ logger: mockLogger })
const expiredDate = new Date()
expiredDate.setDate(expiredDate.getDate() + 10)
const callbacks = getAuthCallbacks({ accessTokenExpDate: expiredDate })

await auth.authentication(callbacks)

const expectedRefreshDate = new Date(Date.now() + 24 * 60 * 60 * 1000) // one day

expect(mockLogger.log).toHaveBeenCalledWith(
`Token will be refreshed at ${expectedRefreshDate} [${expectedRefreshDate.toUTCString()}]`,
)
})
})
})

Expand Down

0 comments on commit 7188fcf

Please sign in to comment.