Merged in development (pull request #1)

Preparando pipeline para deploy
This commit is contained in:
Leandro Costa 2023-01-27 14:50:54 +00:00
commit 19276599d3
6 changed files with 173 additions and 101 deletions

View file

@ -1,6 +1,6 @@
import axios from 'axios'; import axios from 'axios';
import LhispOauthClient from "../src/lhisp-oauth-client"; import { LhispOauthClient } from "../src/lhisp-oauth-client";
import { LhispOauthClientConstructorParams } from '../src/lhisp-oauth-client.t'; import { ContentType, LhispOauthClientConstructorParams } from '../src/lhisp-oauth-client.t';
// Mock jest and set the type // Mock jest and set the type
jest.mock('axios'); jest.mock('axios');
@ -13,34 +13,20 @@ const clientSecret = "testClientSecret";
const baseClientParams = { apiUrl, authUrl, clientId, clientSecret }; const baseClientParams = { apiUrl, authUrl, clientId, clientSecret };
const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`; const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`;
const contentTypeApplicationJson = "application/json"; const contentTypeApplicationJson = "application/json";
const contentTypeApplicationXFormUrlEncoded = "application/x-www-form-urlencoded";
const defaultGrantValue='client_credentials'; const defaultGrantValue='client_credentials';
const defaultGrantType=`{"grant_type":"${defaultGrantValue}"}`; const defaultGrantType=`{"grant_type":"${defaultGrantValue}"}`;
describe("Get Access Token", ()=>{ describe("Get Access Token", ()=>{
beforeEach(() => {
mockedAxios.request.mockReset();
mockedAxios.request.mockResolvedValueOnce({ data: mockedAccessToken });
});
it("Shoud Get with Standard Config", async ()=>{ it("Shoud Get with Standard Config", async ()=>{
const cli = getOauthClient(); const cli = getOauthClient();
mockedAxios.request.mockReset(); await accessTokenValidator(cli);
mockedAxios.request.mockResolvedValueOnce({ validateDefaultGetAccessToken();
data: mockedAccessToken
});
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);
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
url: authUrl,
method: "POST",
headers: {
Authorization: basicAuth,
'Content-Type': contentTypeApplicationJson,
},
data: defaultGrantType,
}));
}); });
it("Shoud Get with Custom Auth Header", async ()=>{ it("Shoud Get with Custom Auth Header", async ()=>{
@ -48,19 +34,7 @@ describe("Get Access Token", ()=>{
...baseClientParams, ...baseClientParams,
authHeaderName: 'CustomAuthorizationHeader', authHeaderName: 'CustomAuthorizationHeader',
}); });
mockedAxios.request.mockReset(); await accessTokenValidator(cli);
mockedAxios.request.mockResolvedValueOnce({
data: mockedAccessToken
});
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);
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
url: authUrl, url: authUrl,
method: "POST", method: "POST",
@ -77,19 +51,7 @@ describe("Get Access Token", ()=>{
...baseClientParams, ...baseClientParams,
grantType: 'PermissaoCustom', grantType: 'PermissaoCustom',
}); });
mockedAxios.request.mockReset(); await accessTokenValidator(cli);
mockedAxios.request.mockResolvedValueOnce({
data: mockedAccessToken
});
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);
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
url: authUrl, url: authUrl,
method: "POST", method: "POST",
@ -106,19 +68,7 @@ describe("Get Access Token", ()=>{
...baseClientParams, ...baseClientParams,
authScope: 'EscopoCustom', authScope: 'EscopoCustom',
}); });
mockedAxios.request.mockReset(); await accessTokenValidator(cli);
mockedAxios.request.mockResolvedValueOnce({
data: mockedAccessToken
});
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);
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
url: authUrl, url: authUrl,
method: "POST", method: "POST",
@ -135,19 +85,7 @@ describe("Get Access Token", ()=>{
...baseClientParams, ...baseClientParams,
sendAuthCredentialsOnRequestBody: true, sendAuthCredentialsOnRequestBody: true,
}); });
mockedAxios.request.mockReset(); await accessTokenValidator(cli);
mockedAxios.request.mockResolvedValueOnce({
data: mockedAccessToken
});
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);
expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({ expect(mockedAxios.request).toBeCalledWith(expect.objectContaining({
url: authUrl, url: authUrl,
method: "POST", method: "POST",
@ -160,6 +98,129 @@ describe("Get Access Token", ()=>{
}); });
}); });
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).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();
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();
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();
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",
});
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){ function getOauthClient(opt:LhispOauthClientConstructorParams=baseClientParams){
return new LhispOauthClient(opt); return new LhispOauthClient(opt);
} }

View file

@ -1,33 +1,44 @@
image: node:14 image: node:18-alpine
definitions:
steps:
- step: &build-and-test
name: Build and Test
caches:
- node
script:
- yarn install
- yarn build
artifacts:
- dist/**
pipelines: pipelines:
branches: branches:
default: default:
- step: <<: *build-and-test
name: Build and Test
caches:
- node
script:
- yarn install
- yarn build
'{development,realease-no-verify/*}': '{development,realease-no-verify/*}':
- step: *build-and-test
- step: - step:
name: Build and Deploy Dev name: Prepare Package
caches:
- node
script: script:
- yarn install - apk add git
- yarn build:dev - cp package.json dist/
- sed -i s/$BITBUCKET_REPO_SLUG/$BITBUCKET_REPO_SLUG-dev/ dist/package.json
- npm version patch -m "[skip CI] Version %s"
- git push
artifacts:
- dist/**
- step:
name: Publish
deployment: staging
script:
- pipe: atlassian/npm-publish:0.2.0
variables:
NPM_TOKEN: $NPM_TOKEN
FOLDER: dist
master: master:
- step: *build-and-test
- step: - step:
name: Build and Deploy Prod name: Prepare Package
caches:
- node
script: script:
- yarn install
- yarn build
- mkdir dist/src
- mv dist/*{js,txt} dist/src/
- cp package.json dist/ - cp package.json dist/
artifacts: artifacts:
- dist/** - dist/**

View file

@ -1,6 +1,6 @@
{ {
"name": "lhisp-oauth-client", "name": "lhisp-oauth-client",
"version": "1.0.0", "version": "1.0.5",
"main": "src/index", "main": "src/index",
"types": "src/index.d.ts", "types": "src/index.d.ts",
"repository": "git@bitbucket.org:leandro_costa/lhisp-oauth-client.git", "repository": "git@bitbucket.org:leandro_costa/lhisp-oauth-client.git",

View file

@ -23,7 +23,7 @@ export interface LhispOauthClientConstructorParams {
export interface ExecutarRequestParams extends AxiosRequestConfig { export interface ExecutarRequestParams extends AxiosRequestConfig {
path: string; path: string;
contentType: ContentType, contentType?: ContentType,
} }
export interface AccessToken { export interface AccessToken {
@ -40,6 +40,6 @@ export enum ContentType {
} }
export const defaultGrantType = 'client_credentials'; export const defaultGrantType = 'client_credentials';
export const defaultAuthContentType = ContentType.APPLICATION_JSON; export const defaultAuthContentType = ContentType.APPLICATION_X_WWW_FORM_URLENCODED;
export const defaultAuthHeaderName = 'Authorization'; export const defaultAuthHeaderName = 'Authorization';
export const defaultTokenHeaderName = 'Authorization'; export const defaultTokenHeaderName = 'Authorization';

View file

@ -10,7 +10,7 @@ import {
LhispOauthClientConstructorParams, LhispOauthClientConstructorParams,
} from "./lhisp-oauth-client.t"; } from "./lhisp-oauth-client.t";
export default class LhispOauthClient { export class LhispOauthClient {
protected authUrl: string; protected authUrl: string;
protected apiUrl: string; protected apiUrl: string;
protected clientId: string; protected clientId: string;