diff --git a/src/hooks/index.ts b/src/hooks/index.ts index ec473f6..8075b1b 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -4,3 +4,4 @@ export * from "./useTuitioClient"; export * from "./useTuitioToken"; export * from "./useTuitioUser"; export * from "./useTuitioUserInfo"; +export * from "./useTuitioDecodedToken"; diff --git a/src/hooks/useTuitioDecodedToken.ts b/src/hooks/useTuitioDecodedToken.ts new file mode 100644 index 0000000..feef41a --- /dev/null +++ b/src/hooks/useTuitioDecodedToken.ts @@ -0,0 +1,23 @@ +// Copyright (c) 2023 Tudor Stanciu + +import { useContext, useState, useEffect } from "react"; +import { TuitioContext } from "../contexts"; +import { camelizeKeys } from "@flare/js-utils"; +import type { TuitioTokenData } from "@flare/tuitio-client"; + +const useTuitioDecodedToken = () => { + const state = useContext(TuitioContext); + const [decodedToken, setDecodedToken] = useState(); + + useEffect(() => { + if (decodedToken || !state.auth.token) return; + const decodedTokenBuffer = Buffer.from(state.auth.token, "base64"); + const decodedTokenString = decodedTokenBuffer.toString("utf-8"); + const decoded = camelizeKeys(JSON.parse(decodedTokenString)); + setDecodedToken(decoded); + }, [decodedToken, state.auth.token]); + + return { decodedToken }; +}; + +export { useTuitioDecodedToken }; diff --git a/src/hooks/useTuitioToken.ts b/src/hooks/useTuitioToken.ts index 8423c97..fa33df0 100644 --- a/src/hooks/useTuitioToken.ts +++ b/src/hooks/useTuitioToken.ts @@ -1,13 +1,11 @@ // Copyright (c) 2023 Tudor Stanciu -import { useContext, useCallback, useState, useEffect } from "react"; +import { useContext, useCallback } from "react"; import { TuitioContext } from "../contexts"; -import { camelizeKeys } from "@flare/js-utils"; -import type { TuitioTokenData } from "@flare/tuitio-client"; const useTuitioToken = () => { const state = useContext(TuitioContext); - const [decodedToken, setDecodedToken] = useState(); + const token = state.auth.token; const validate = useCallback((): boolean => { const validUntil = state.auth.validUntil; @@ -18,18 +16,9 @@ const useTuitioToken = () => { return valid; }, [state.auth.validUntil]); - useEffect(() => { - if (decodedToken || !state.auth.token) return; - const decodedTokenBuffer = Buffer.from(state.auth.token, "base64"); - const decodedTokenString = decodedTokenBuffer.toString("utf-8"); - const decoded = camelizeKeys(JSON.parse(decodedTokenString)); - setDecodedToken(decoded); - }, [decodedToken, state.auth.token]); - - const token = state.auth.token; const valid: boolean = validate(); - return { token, validate, valid, decodedToken }; + return { token, validate, valid }; }; export { useTuitioToken }; diff --git a/tests/hooks/useTuitioDecodedToken.test.tsx b/tests/hooks/useTuitioDecodedToken.test.tsx new file mode 100644 index 0000000..35396e4 --- /dev/null +++ b/tests/hooks/useTuitioDecodedToken.test.tsx @@ -0,0 +1,35 @@ +// Copyright (c) 2023 Tudor Stanciu + +import React from "react"; +import { renderHook } from "@testing-library/react-hooks"; +import { TuitioContext } from "../../src/contexts"; +import { useTuitioDecodedToken } from "../../src/hooks"; + +const tokenMock = + "eyJUb2tlbklkIjoiZDkzZjEwMzQtNjI4ZS00MWQ4LWI5OGUtNGM3MDhiMmRlODgzIiwiVXNlcklkIjoxLCJVc2VyTmFtZSI6InR1aXRpby51c2VyIiwiRmlyc3ROYW1lIjoiVHVpdGlvIiwiTGFzdE5hbWUiOiJVc2VyIiwiRW1haWwiOiJ0dWl0aW8udXNlckBsYWIuY29tIiwiU2VjdXJpdHlTdGFtcCI6InRlc3Qtc2VjdXJpdHktc3RhbXAiLCJMb2NrU3RhbXAiOiJ0ZXN0LWxvY2stc3RhbXAiLCJDcmVhdGVkQXQiOiIyMDIwLTAxLTI5VDE1OjIyOjQ5LjYyMzk5MzFaIiwiRXhwaXJlc0luIjoxMDYyfQ=="; + +describe("useTuitioDecodedToken tests", () => { + const testState = { + auth: { userName: "test-user", token: tokenMock, validUntil: new Date() }, + configuration: { + tuitioUrl: null + } + }; + + testState.auth.validUntil.setHours(testState.auth.validUntil.getHours() + 1); + + const wrapper = ({ children }: { children?: React.ReactNode }) => ( + {children} + ); + + it("should successfully decode token", () => { + const { result } = renderHook(() => useTuitioDecodedToken(), { wrapper }); + const { decodedToken } = result.current; + expect(decodedToken?.userId).toEqual(1); + expect(decodedToken?.userName).toBe("tuitio.user"); + expect(decodedToken?.firstName).toBe("Tuitio"); + expect(decodedToken?.securityStamp).toBeDefined(); + expect(decodedToken?.lockStamp).toBeDefined(); + expect(decodedToken?.createdAt).toBeDefined(); + }); +}); diff --git a/tests/hooks/useTuitioToken.test.tsx b/tests/hooks/useTuitioToken.test.tsx index 37a02cd..2bfd139 100644 --- a/tests/hooks/useTuitioToken.test.tsx +++ b/tests/hooks/useTuitioToken.test.tsx @@ -5,12 +5,9 @@ import { renderHook } from "@testing-library/react-hooks"; import { TuitioContext } from "../../src/contexts"; import { useTuitioToken } from "../../src/hooks"; -const tokenMock = - "eyJUb2tlbklkIjoiZDkzZjEwMzQtNjI4ZS00MWQ4LWI5OGUtNGM3MDhiMmRlODgzIiwiVXNlcklkIjoxLCJVc2VyTmFtZSI6InR1aXRpby51c2VyIiwiRmlyc3ROYW1lIjoiVHVpdGlvIiwiTGFzdE5hbWUiOiJVc2VyIiwiRW1haWwiOiJ0dWl0aW8udXNlckBsYWIuY29tIiwiU2VjdXJpdHlTdGFtcCI6InRlc3Qtc2VjdXJpdHktc3RhbXAiLCJMb2NrU3RhbXAiOiJ0ZXN0LWxvY2stc3RhbXAiLCJDcmVhdGVkQXQiOiIyMDIwLTAxLTI5VDE1OjIyOjQ5LjYyMzk5MzFaIiwiRXhwaXJlc0luIjoxMDYyfQ=="; - describe("useTuitioToken: positive flow", () => { const testState = { - auth: { userName: "test-user", token: tokenMock, validUntil: new Date() }, + auth: { userName: "test-user", token: "mocked-token", validUntil: new Date() }, configuration: { tuitioUrl: null } @@ -24,7 +21,7 @@ describe("useTuitioToken: positive flow", () => { it("should return the correct token", () => { const { result } = renderHook(() => useTuitioToken(), { wrapper }); - expect(result.current.token).toEqual(tokenMock); + expect(result.current.token).toEqual("mocked-token"); }); it("should return false value for valid", () => { @@ -37,17 +34,6 @@ describe("useTuitioToken: positive flow", () => { const valid = result.current.validate(); expect(valid).toBe(true); }); - - it("should successfully decode token", () => { - const { result } = renderHook(() => useTuitioToken(), { wrapper }); - const { decodedToken } = result.current; - expect(decodedToken?.userId).toEqual(1); - expect(decodedToken?.userName).toBe("tuitio.user"); - expect(decodedToken?.firstName).toBe("Tuitio"); - expect(decodedToken?.securityStamp).toBeDefined(); - expect(decodedToken?.lockStamp).toBeDefined(); - expect(decodedToken?.createdAt).toBeDefined(); - }); }); describe("useTuitioToken: negative flow", () => {