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 = axios as jest.Mocked; const apiUrl = "https://myapi.com"; const authUrl = "https://auth.myapi.com/oauth/token"; const clientId = "testClientdId"; const clientSecret = "testClientSecret"; const baseClientParams = { apiUrl, authUrl, clientId, clientSecret }; const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`; const contentTypeApplicationJson = "application/json"; const contentTypeApplicationXFormUrlEncoded = "application/x-www-form-urlencoded"; const defaultGrantValue='client_credentials'; const defaultGrantType=`{"grant_type":"${defaultGrantValue}"}`; describe("Get Access Token", ()=>{ it("Shoud Get with Standard Config", async ()=>{ const cli = getOauthClient(); mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); await accessTokenValidator(cli); validateDefaultGetAccessToken(); }); it("Shoud Get with Custom Auth Header", async ()=>{ const cli = getOauthClient({ ...baseClientParams, authHeaderName: 'CustomAuthorizationHeader', }); mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); await accessTokenValidator(cli); expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ url: authUrl, method: "POST", headers: { CustomAuthorizationHeader: basicAuth, 'Content-Type': contentTypeApplicationJson, }, data: defaultGrantType, })); }); it("Shoud Get with Custom Grant Type", async ()=>{ const cli = getOauthClient({ ...baseClientParams, grantType: 'PermissaoCustom', }); mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); await accessTokenValidator(cli); expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, 'Content-Type': contentTypeApplicationJson, }, data: '{"grant_type":"PermissaoCustom"}', })); }); it("Shoud Get with Custom Auth Scope", async ()=>{ const cli = getOauthClient({ ...baseClientParams, authScope: 'EscopoCustom', }); mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); await accessTokenValidator(cli); expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, 'Content-Type': contentTypeApplicationJson, }, data: `{"grant_type":"${defaultGrantValue}","scope":"EscopoCustom"}`, })); }); it("Shoud Get with Credentials on Request body", async ()=>{ const cli = getOauthClient({ ...baseClientParams, sendAuthCredentialsOnRequestBody: true, }); mockedAxios.request.mockReset(); mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); await accessTokenValidator(cli); expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, 'Content-Type': contentTypeApplicationJson, }, data: `{"grant_type":"${defaultGrantValue}","client_id":"${clientId}","client_secret":"${clientSecret}"}`, })); }); }); describe("Request", ()=>{ it("Get without Params", async ()=>{ const cli = getOauthClient(); mockedAxios.request.mockReset(); // Mockando a requizição para obter o token. mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); mockedAxios.request.mockResolvedValueOnce({ data: {"status": "ok"} }); const resp = await cli.get({ path: '/my-test-url' }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toBeCalledWith(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(); mockedAxios.request.mockReset(); // Mockando a requizição para obter o token. mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); mockedAxios.request.mockResolvedValueOnce({ data: {"status": "ok"} }); const resp = await cli.get({ path: '/my-test-url', params: { id: 1 } }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toBeCalledWith(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(); mockedAxios.request.mockReset(); // Mockando a requizição para obter o token. mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); mockedAxios.request.mockResolvedValueOnce({ data: {"status": "ok"} }); const resp = await cli.post({ path: '/my-test-url-post', data: { id: 1, user: 'test' } }); validateDefaultGetAccessToken(); expect(mockedAxios.request).toBeCalledWith(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(); mockedAxios.request.mockReset(); // Mockando a requizição para obter o token. mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); mockedAxios.request.mockResolvedValueOnce({ data: {"status": "ok"} }); 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).toBeCalledWith(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", }); mockedAxios.request.mockReset(); // Mockando a requizição para obter o token. mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken }); mockedAxios.request.mockResolvedValueOnce({ data: {"status": "ok"} }); 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).toBeCalledWith(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).toBeCalledWith(expect.objectContaining({ url: authUrl, method: "POST", headers: { Authorization: basicAuth, 'Content-Type': contentTypeApplicationJson, }, 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); expect(accessToken.created_at).toBeGreaterThanOrEqual(now); } 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", }