import axios from "axios"; import { LhispOauthClient } from "../src/lhisp-oauth-client"; import { ContentType, LhispOauthClientConstructorParams } from "../src/lhisp-oauth-client.t"; // Mock jest and set the type jest.mock("axios"); const mockedAxios = jest.mocked(axios); const apiUrl = "https://myapi.com"; const authUrl = "https://auth.myapi.com/oauth/token"; const clientId = "testClientId"; const clientSecret = "testClientSecret"; const baseClientParams = { apiUrl, authUrl, clientId, clientSecret }; const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`; const contentTypeApplicationJson = ContentType.APPLICATION_JSON; const contentTypeApplicationXFormUrlEncoded = ContentType.APPLICATION_X_WWW_FORM_URLENCODED; const defaultGrantValue = "client_credentials"; const defaultGrantType = `grant_type=${defaultGrantValue}`; describe("Get Access Token", () => { beforeEach(() => { mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); }); it("Should Get with Standard Config", async () => { const cli = getOauthClient(); await accessTokenValidator(cli); validateDefaultGetAccessToken(); }); it("Should Get with Custom Auth Header", async () => { const cli = getOauthClient({ ...baseClientParams, authHeaderName: "CustomAuthorizationHeader", }); await accessTokenValidator(cli); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: authUrl, method: "POST", headers: { CustomAuthorizationHeader: basicAuth, "Content-Type": contentTypeApplicationXFormUrlEncoded, }, data: defaultGrantType, }) ); }); it("Should Get with Custom Grant Type", async () => { const cli = getOauthClient({ ...baseClientParams, grantType: "PermissaoCustom", }); await accessTokenValidator(cli); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, "Content-Type": contentTypeApplicationXFormUrlEncoded, }, data: "grant_type=PermissaoCustom", }) ); }); it("Should Get with Custom Auth Scope", async () => { const cli = getOauthClient({ ...baseClientParams, authScope: "EscopoCustom", }); await accessTokenValidator(cli); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, "Content-Type": contentTypeApplicationXFormUrlEncoded, }, data: `grant_type=${defaultGrantValue}&scope=EscopoCustom`, }) ); }); it("Should Get with Credentials on Request body", async () => { const cli = getOauthClient({ ...baseClientParams, authContentType: contentTypeApplicationJson, sendAuthCredentialsOnRequestBody: true, }); await accessTokenValidator(cli); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, "Content-Type": contentTypeApplicationJson, }, data: `{"grant_type":"${defaultGrantValue}","client_id":"${clientId}","client_secret":"${clientSecret}"}`, }) ); }); }); describe("Request", () => { beforeEach(() => { mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); mockedAxios.request.mockResolvedValueOnce({ data: { status: "ok" } }); }); it("Get without Params", async () => { const cli = getOauthClient(); const resp = await cli.get({ path: "/my-test-url" }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: `${apiUrl}/my-test-url`, method: "GET", headers: { Authorization: `Bearer SomeAccessToken`, "Content-Type": contentTypeApplicationJson, }, data: undefined, }) ); expect(resp).toStrictEqual({ status: "ok" }); }); it("Get with Params", async () => { const cli = getOauthClient(); const resp = await cli.get({ path: "/my-test-url", params: { id: 1 } }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: `${apiUrl}/my-test-url`, method: "GET", headers: { Authorization: `Bearer SomeAccessToken`, "Content-Type": contentTypeApplicationJson, }, params: { id: 1 }, data: undefined, }) ); expect(resp).toStrictEqual({ status: "ok" }); }); it("Post", async () => { const cli = getOauthClient(); const resp = await cli.post({ path: "/my-test-url-post", data: { id: 1, user: "test" } }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: `${apiUrl}/my-test-url-post`, method: "POST", headers: { Authorization: `Bearer SomeAccessToken`, "Content-Type": contentTypeApplicationJson, }, data: { id: 1, user: "test" }, }) ); expect(resp).toStrictEqual({ status: "ok" }); }); it("Post with different contentType", async () => { const cli = getOauthClient(); const resp = await cli.post({ path: "/my-test-url-post", data: { id: 1, user: "test" }, contentType: ContentType.APPLICATION_X_WWW_FORM_URLENCODED, }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: `${apiUrl}/my-test-url-post`, method: "POST", headers: { Authorization: `Bearer SomeAccessToken`, "Content-Type": contentTypeApplicationXFormUrlEncoded, }, data: { id: 1, user: "test" }, }) ); expect(resp).toStrictEqual({ status: "ok" }); }); it("Post with Different Token Header Name", async () => { const cli = getOauthClient({ ...baseClientParams, tokenHeaderName: "x-token", }); const resp = await cli.post({ path: "/my-test-url-post", data: { id: 1, user: "test" }, contentType: ContentType.APPLICATION_X_WWW_FORM_URLENCODED, }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: `${apiUrl}/my-test-url-post`, method: "POST", headers: { "x-token": `Bearer SomeAccessToken`, "Content-Type": contentTypeApplicationXFormUrlEncoded, }, data: { id: 1, user: "test" }, }) ); expect(resp).toStrictEqual({ status: "ok" }); }); }); function validateDefaultGetAccessToken() { expect(mockedAxios.request).toHaveBeenCalledWith( expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, "Content-Type": contentTypeApplicationXFormUrlEncoded, }, data: defaultGrantType, }) ); } async function accessTokenValidator(cli: LhispOauthClient) { const now = Date.now(); const accessToken = await cli.getAccessToken(); expect(accessToken).toBeDefined(); expect(accessToken.token_type).toBe(mockedAccessToken.token_type); expect(accessToken.access_token).toBe(mockedAccessToken.access_token); expect(accessToken.expires_in).toBe(mockedAccessToken.expires_in); expect(accessToken.scope).toBe(mockedAccessToken.scope); } function getOauthClient(opt: LhispOauthClientConstructorParams = baseClientParams) { return new LhispOauthClient(opt); } const mockedAccessToken = { token_type: "Bearer", access_token: "SomeAccessToken", expires_in: 600, scope: "cobrancas.boletos-requisicao cobrancas.boletos-info", };