1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-08 13:00:05 +00:00

chore(*): refactor and add tests

This commit is contained in:
Krishna Acondy
2021-01-24 15:08:35 +00:00
parent aed39c2ec4
commit 301edab8ad
7 changed files with 1259 additions and 1899 deletions

View File

@@ -1,6 +1,6 @@
import { ServerType } from '@sasjs/utils/types'
import axios, { AxiosInstance } from 'axios'
import { isAuthorizeFormRequired, parseAndSubmitAuthorizeForm } from '.'
import { ServerType } from '../types'
import { serialize } from '../utils'
export class AuthManager {
@@ -16,7 +16,7 @@ export class AuthManager {
this.httpClient = axios.create({ baseURL: this.serverUrl })
this.loginUrl = `/SASLogon/login`
this.logoutUrl =
this.serverType === ServerType.SAS9
this.serverType === ServerType.Sas9
? '/SASLogon/logout?'
: '/SASLogon/logout.do?'
}
@@ -89,13 +89,16 @@ export class AuthManager {
* @returns - a promise which resolves with an object containing two values - a boolean `isLoggedIn`, and a string `userName`.
*/
public async checkSession() {
const loginResponse = await axios.get(this.loginUrl.replace('.do', ''), {
responseType: 'text',
headers: {
Accept: '*/*'
const loginResponse = await this.httpClient.get(
this.loginUrl.replace('.do', ''),
{
responseType: 'text',
headers: {
Accept: '*/*'
}
}
})
const responseText = await loginResponse.data
)
const responseText = loginResponse?.data
const isLoggedIn = /<button.+onClick.+logout/gm.test(responseText)
let loginForm: any = null
@@ -110,7 +113,7 @@ export class AuthManager {
})
}
private async getLoginForm(response: any) {
private getLoginForm(response: any) {
const pattern: RegExp = /<form.+action="(.*Logon[^"]*).*>/
const matches = pattern.exec(response)
const formInputs: any = {}
@@ -145,7 +148,7 @@ export class AuthManager {
const loginUrl = tempLoginLink
this.loginUrl =
this.serverType === ServerType.SASViya
this.serverType === ServerType.SasViya
? tempLoginLink
: loginUrl.replace('.do', '')
}

View File

@@ -0,0 +1,170 @@
import { AuthManager } from '../AuthManager'
import * as dotenv from 'dotenv'
import * as authModule from '..'
import { ServerType } from '@sasjs/utils/types'
import axios from 'axios'
import {
mockLoginAuthoriseRequiredResponse,
mockLoginSuccessResponse
} from './mockResponses'
import { serialize } from '../../utils'
jest.mock('axios')
jest.mock('../parseAndSubmitAuthorizeForm')
const mockedAxios = axios as jest.Mocked<typeof axios>
describe('AuthManager', () => {
const authCallback = jest.fn().mockImplementation(() => Promise.resolve())
const serverUrl = 'http://test-server.com'
const serverType = ServerType.SasViya
const userName = 'test-username'
const password = 'test-password'
beforeAll(() => {
dotenv.config()
jest.restoreAllMocks()
})
it('should instantiate and set the correct URLs for a Viya server', () => {
const authManager = new AuthManager(serverUrl, serverType, authCallback)
expect(authManager).toBeTruthy()
expect((authManager as any).serverUrl).toEqual(serverUrl)
expect((authManager as any).serverType).toEqual(serverType)
expect((authManager as any).httpClient).toBeTruthy()
expect((authManager as any).loginUrl).toEqual(`/SASLogon/login`)
expect((authManager as any).logoutUrl).toEqual('/SASLogon/logout.do?')
})
it('should instantiate and set the correct URLs for a SAS9 server', () => {
const authCallback = () => Promise.resolve()
const serverType = ServerType.Sas9
const authManager = new AuthManager(serverUrl, serverType, authCallback)
expect(authManager).toBeTruthy()
expect((authManager as any).serverUrl).toEqual(serverUrl)
expect((authManager as any).serverType).toEqual(serverType)
expect((authManager as any).httpClient).toBeTruthy()
expect((authManager as any).loginUrl).toEqual(`/SASLogon/login`)
expect((authManager as any).logoutUrl).toEqual('/SASLogon/logout?')
})
it('should call the auth callback and return when already logged in', async (done) => {
const authManager = new AuthManager(serverUrl, serverType, authCallback)
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: true,
userName: 'test',
loginForm: 'test'
})
)
const loginResponse = await authManager.logIn(userName, password)
expect(loginResponse.isLoggedIn).toBeTruthy()
expect(loginResponse.userName).toEqual(userName)
expect(authCallback).toHaveBeenCalledTimes(1)
done()
})
it('should post a login request to the server if not logged in', async (done) => {
const authManager = new AuthManager(serverUrl, serverType, authCallback)
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: false,
userName: 'test',
loginForm: { name: 'test' }
})
)
mockedAxios.post.mockImplementation(() =>
Promise.resolve({ data: mockLoginSuccessResponse })
)
const loginResponse = await authManager.logIn(userName, password)
expect(loginResponse.isLoggedIn).toBeTruthy()
expect(loginResponse.userName).toEqual(userName)
const loginParams = serialize({
_service: 'default',
username: userName,
password,
name: 'test'
})
expect(mockedAxios.post).toHaveBeenCalledWith(
`/SASLogon/login`,
loginParams,
{
withCredentials: true,
responseType: 'text',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: '*/*'
}
}
)
expect(authCallback).toHaveBeenCalledTimes(1)
done()
})
it('should parse and submit the authorisation form when necessary', async (done) => {
const authManager = new AuthManager(serverUrl, serverType, authCallback)
jest
.spyOn(authModule, 'parseAndSubmitAuthorizeForm')
.mockImplementation(() => Promise.resolve())
jest.spyOn(authManager, 'checkSession').mockImplementation(() =>
Promise.resolve({
isLoggedIn: false,
userName: 'test',
loginForm: { name: 'test' }
})
)
mockedAxios.post.mockImplementation(() =>
Promise.resolve({ data: mockLoginAuthoriseRequiredResponse })
)
await authManager.logIn(userName, password)
expect(authModule.parseAndSubmitAuthorizeForm).toHaveBeenCalledWith(
mockLoginAuthoriseRequiredResponse,
serverUrl
)
done()
})
it('should check and return session information if logged in', async (done) => {
const authManager = new AuthManager(serverUrl, serverType, authCallback)
mockedAxios.get.mockImplementation(() =>
Promise.resolve({ data: '<button onClick="logout">' })
)
const response = await authManager.checkSession()
expect(response.isLoggedIn).toBeTruthy()
expect(mockedAxios.get).toHaveBeenNthCalledWith(1, `/SASLogon/login`, {
responseType: 'text',
headers: {
Accept: '*/*'
}
})
done()
})
it('should check and return session information if logged in', async (done) => {
const authManager = new AuthManager(serverUrl, serverType, authCallback)
mockedAxios.get.mockImplementation(() =>
Promise.resolve({ data: '<button onClick="logout">' })
)
const response = await authManager.checkSession()
expect(response.isLoggedIn).toBeTruthy()
expect(mockedAxios.get).toHaveBeenNthCalledWith(1, `/SASLogon/login`, {
responseType: 'text',
headers: {
Accept: '*/*'
}
})
done()
})
})

View File

@@ -0,0 +1,2 @@
export const mockLoginAuthoriseRequiredResponse = `<form id="application_authorization" action="/SASLogon/oauth/authorize" method="POST"><input type="hidden" name="X-Uaa-Csrf" value="2nfuxIn6WaOURWL7tzTXCe"/>`
export const mockLoginSuccessResponse = `You have signed in`