1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-08 02:42:44 +00:00

feat: cli mock testing

This commit is contained in:
2022-10-11 18:37:20 +02:00
parent 0a6b972c65
commit 6434123401
13 changed files with 166 additions and 18 deletions

2
.gitignore vendored
View File

@@ -5,8 +5,6 @@ node_modules/
.env*
sas/
sasjs_root/
api/mocks/custom/*
!api/mocks/custom/.keep
tmp/
build/
sasjsbuild/

View File

@@ -103,6 +103,10 @@ PORT=
# If not present, mocking function is disabled
MOCK_SERVERTYPE=
# Path to mocking folder, it's sub directories should be: sas9, viya, sasjs
# Server will automatically use sub directory accordingly
STATIC_MOCK_LOCATION=
#
## Additional SAS Options
#

View File

View File

@@ -9,7 +9,7 @@
<div class="content">
<form id="credentials" class="minimal" action="/SASLogon/login?service=http%3A%2F%2Flocalhost:5004%2FSASStoredProcess%2Fj_spring_cas_security_check" method="post">
<!--form container-->
<input type="hidden" name="lt" value="LT-8-WGkt9EXwICBihaVbxGc92opjufTK1D" aria-hidden="true" />
<input type="hidden" name="lt" value="validtoken" aria-hidden="true" />
<input type="hidden" name="execution" value="e2s1" aria-hidden="true" />
<input type="hidden" name="_eventId" value="submit" aria-hidden="true" />

View File

@@ -57,6 +57,7 @@ export default setProcessVariables().then(async () => {
app.use(express.json({ limit: '100mb' }))
app.use(express.static(path.join(__dirname, '../public')))
app.use(express.urlencoded({ extended: true }))
// Body parser is used for decoding the formdata on POST request.
// Currently only place we use it is SAS9 Mock - POST /SASLogon/login

View File

@@ -2,6 +2,11 @@ import { readFile } from '@sasjs/utils'
import express from 'express'
import path from 'path'
import { Request, Post, Get } from 'tsoa'
import fs from 'fs'
import fse from 'fs-extra'
import dotenv from 'dotenv'
dotenv.config()
export interface Sas9Response {
content: string
@@ -16,9 +21,17 @@ export interface MockFileRead {
export class MockSas9Controller {
private loggedIn: string | undefined
private mocksPath = process.env.STATIC_MOCK_LOCATION || 'mocks'
@Get('/SASStoredProcess')
public async sasStoredProcess(): Promise<Sas9Response> {
public async sasStoredProcess(
@Request() req: express.Request
): Promise<Sas9Response> {
let username = req.query._username?.toString() || undefined
let password = req.query._password?.toString() || undefined
if (username && password) this.loggedIn = req.body.username
if (!this.loggedIn) {
return {
content: '',
@@ -26,17 +39,66 @@ export class MockSas9Controller {
}
}
let program = req.query._program?.toString() || undefined
let filePath: string[] = ['generic', 'sas-stored-process']
if (program) {
filePath = program.replace('/', '').split('/')
return await getMockResponseFromFile([
process.cwd(),
this.mocksPath,
'sas9',
...filePath
])
}
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'generic',
'sas9',
'sas-stored-process'
...filePath
])
}
@Get('/SASStoredProcess/do')
public async sasStoredProcessDoGet(
@Request() req: express.Request
): Promise<Sas9Response> {
let username = req.query._username?.toString() || undefined
let password = req.query._password?.toString() || undefined
if (username && password) this.loggedIn = username
if (!this.loggedIn) {
return {
content: '',
redirect: '/SASLogon/login'
}
}
let program = req.query._program?.toString() || undefined
let filePath: string[] = ['generic', 'sas-stored-process']
if (program) {
filePath = `${program}`.replace('/', '').split('/')
return await getMockResponseFromFile([
process.cwd(),
this.mocksPath,
'sas9',
...filePath
])
}
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'sas9',
...filePath
])
}
@Post('/SASStoredProcess/do/')
public async sasStoredProcessDo(
public async sasStoredProcessDoPost(
@Request() req: express.Request
): Promise<Sas9Response> {
if (!this.loggedIn) {
@@ -55,13 +117,56 @@ export class MockSas9Controller {
let program = req.query._program?.toString() || ''
program = program.replace('/', '')
let debug = req.query._debug?.toString()
let fileContents = ''
if (program.includes('runner') && debug === 'log') {
if (req.files && req.files.length > 0) {
const regexRequest = /cli-tests-request-sas9-.*?\d*/g
const uploadFilePath = (req.files as any)[0].path
fileContents = fs.readFileSync(uploadFilePath, 'utf8')
let matched = fileContents.match(regexRequest)?.[0]
if (matched) {
const testsFolderPath = path.join(
process.cwd(),
this.mocksPath,
'sas9',
'User Folders',
'cli-tests',
'sasdemo',
matched
)
if (!fs.existsSync(testsFolderPath)) fs.mkdirSync(testsFolderPath)
fse.copySync(
path.join(
process.cwd(),
this.mocksPath,
'sas9',
'User Folders',
'sasdemo',
'services'
),
path.join(testsFolderPath, 'services')
)
}
}
}
const content = await getMockResponseFromFile([
process.cwd(),
'mocks',
this.mocksPath,
'sas9',
...program.split('/')
])
content.content += fileContents
if (content.error) {
return content
}
@@ -85,8 +190,8 @@ export class MockSas9Controller {
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'generic',
'sas9',
'generic',
'logged-in'
])
}
@@ -95,21 +200,27 @@ export class MockSas9Controller {
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'generic',
'sas9',
'generic',
'login'
])
}
@Post('/SASLogon/login')
public async loginPost(req: express.Request): Promise<Sas9Response> {
if (req.body.lt && req.body.lt !== 'validtoken')
return {
content: '',
redirect: '/SASLogon/login'
}
this.loggedIn = req.body.username
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'generic',
'sas9',
'generic',
'logged-in'
])
}
@@ -122,8 +233,8 @@ export class MockSas9Controller {
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'generic',
'sas9',
'generic',
'public-access-denied'
])
}
@@ -131,8 +242,8 @@ export class MockSas9Controller {
return await getMockResponseFromFile([
process.cwd(),
'mocks',
'generic',
'sas9',
'generic',
'logged-out'
])
}

View File

@@ -15,5 +15,5 @@ export const setupRoutes = (app: Express) => {
appStreamRouter(req, res, next)
})
app.use('/', csrfProtection, webRouter)
app.use('/', webRouter)
}

View File

@@ -3,6 +3,7 @@ import sas9WebRouter from './sas9-web'
import sasViyaWebRouter from './sasviya-web'
import webRouter from './web'
import { MOCK_SERVERTYPEType } from '../../utils'
import { csrfProtection } from '../../middlewares'
const router = express.Router()
@@ -18,7 +19,7 @@ switch (MOCK_SERVERTYPE) {
break
}
default: {
router.use('/', webRouter)
router.use('/', csrfProtection, webRouter)
}
}

View File

@@ -2,6 +2,12 @@ import express from 'express'
import { generateCSRFToken } from '../../middlewares'
import { WebController } from '../../controllers'
import { MockSas9Controller } from '../../controllers/mock-sas9'
import fs from 'fs'
import multer from 'multer'
import path from 'path'
import dotenv from 'dotenv'
dotenv.config()
const sas9WebRouter = express.Router()
const webController = new WebController()
@@ -9,6 +15,12 @@ const webController = new WebController()
// for example `isLoggedIn` and potentially more in future mocks
const controller = new MockSas9Controller()
const mockPath = process.env.STATIC_MOCK_LOCATION || 'mocks'
const upload = multer({
dest: path.join(process.cwd(), mockPath, 'sas9', 'files-recieved')
})
sas9WebRouter.get('/', async (req, res) => {
let response
try {
@@ -27,7 +39,7 @@ sas9WebRouter.get('/', async (req, res) => {
})
sas9WebRouter.get('/SASStoredProcess', async (req, res) => {
const response = await controller.sasStoredProcess()
const response = await controller.sasStoredProcess(req)
if (response.redirect) {
res.redirect(response.redirect)
@@ -41,8 +53,29 @@ sas9WebRouter.get('/SASStoredProcess', async (req, res) => {
}
})
sas9WebRouter.post('/SASStoredProcess/do/', async (req, res) => {
const response = await controller.sasStoredProcessDo(req)
sas9WebRouter.get('/SASStoredProcess/do/', async (req, res) => {
const response = await controller.sasStoredProcessDoGet(req)
if (response.redirect) {
res.redirect(response.redirect)
return
}
try {
res.send(response.content)
} catch (err: any) {
res.status(403).send(err.toString())
}
})
sas9WebRouter.post('/SASStoredProcess/do/', upload.any(), async (req, res) => {
const response = await controller.sasStoredProcessDoPost(req)
if (req.files) {
;(req.files as any).forEach((file: any) => {
fs.renameSync(file.path, file.destination + '/' + file.fieldname)
})
}
if (response.redirect) {
res.redirect(response.redirect)