mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-11 09:24:35 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76bbb8acf2 | ||
|
|
1ead483921 | ||
|
|
e2cb787f89 | ||
|
|
828aef1873 | ||
|
|
f6ee1111c5 | ||
|
|
5f8750a8b6 | ||
|
|
d027acacb6 | ||
|
|
3660b9127a | ||
|
|
5ac0f12435 | ||
|
|
ee0c4b007b | ||
|
|
db4a4e6d57 | ||
|
|
eba30432dd | ||
|
|
6b9cb3af5f | ||
|
|
afe612925e | ||
|
|
1f9bed0625 | ||
|
|
51fdea46fc | ||
|
|
007b00565c | ||
|
|
38eef00216 | ||
|
|
f1c67432bf | ||
|
|
3041a0f4b1 | ||
|
|
6a5529f3f0 | ||
|
|
7758b78a88 | ||
|
|
09c1038cbd | ||
|
|
87e2449b6f | ||
|
|
c6b927c525 | ||
|
|
4b6445d524 | ||
|
|
bd872e0e75 | ||
|
|
a14a1663fc | ||
|
|
2482a0c674 | ||
|
|
a19de50e67 | ||
|
|
860c9f907c | ||
|
|
d7126a6878 | ||
| bfefdb65a3 | |||
| bbe52562da | |||
| 48917bb4d9 | |||
| 81c3d2a3dc | |||
| 0052d5d340 | |||
| a633bda24d | |||
| e951ea0ab2 | |||
| b75ab13eb7 | |||
| 4de34cc8b0 | |||
| 23a789b383 | |||
| 156f1b1180 | |||
| 491e36d703 | |||
| 06b6e48a16 | |||
| 9bebd356ca | |||
| 171f9bc7b9 |
25
.github/vpn/config.ovpn
vendored
Normal file
25
.github/vpn/config.ovpn
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Client
|
||||
client
|
||||
tls-client
|
||||
dev tun
|
||||
# this will connect with whatever proto DNS tells us (https://community.openvpn.net/openvpn/ticket/934)
|
||||
proto tcp
|
||||
remote vpn.4gl.io 7494
|
||||
resolv-retry infinite
|
||||
cipher AES-256-CBC
|
||||
auth SHA256
|
||||
script-security 2
|
||||
keepalive 10 120
|
||||
remote-cert-tls server
|
||||
|
||||
# Keys
|
||||
ca ca.crt
|
||||
cert user.crt
|
||||
key user.key
|
||||
tls-auth tls.key 1
|
||||
|
||||
# Security
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
verb 3
|
||||
68
.github/workflows/build.yml
vendored
68
.github/workflows/build.yml
vendored
@@ -22,47 +22,77 @@ jobs:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: npm
|
||||
|
||||
- name: Check npm audit
|
||||
run: npm audit --production --audit-level=low
|
||||
# - name: Check npm audit
|
||||
# run: npm audit --production --audit-level=low
|
||||
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Check code style
|
||||
run: npm run lint
|
||||
# - name: Check code style
|
||||
# run: npm run lint
|
||||
|
||||
- name: Run unit tests
|
||||
run: npm test
|
||||
# - name: Run unit tests
|
||||
# run: npm test
|
||||
|
||||
- name: Build Package
|
||||
run: npm run package:lib
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: Install SSH Key
|
||||
uses: shimataro/ssh-key-action@v2
|
||||
with:
|
||||
key: ${{ secrets.DCGITLAB_KEY }}
|
||||
known_hosts: 'placeholder'
|
||||
- name: Write VPN Files
|
||||
run: |
|
||||
echo "$CA_CRT" > .github/vpn/ca.crt
|
||||
echo "$USER_CRT" > .github/vpn/user.crt
|
||||
echo "$USER_KEY" > .github/vpn/user.key
|
||||
echo "$TLS_KEY" > .github/vpn/tls.key
|
||||
shell: bash
|
||||
env:
|
||||
CA_CRT: ${{ secrets.CA_CRT}}
|
||||
USER_CRT: ${{ secrets.USER_CRT }}
|
||||
USER_KEY: ${{ secrets.USER_KEY }}
|
||||
TLS_KEY: ${{ secrets.TLS_KEY }}
|
||||
|
||||
- name: Install Open VPN
|
||||
run: |
|
||||
sudo apt install apt-transport-https
|
||||
sudo wget https://swupdate.openvpn.net/repos/openvpn-repo-pkg-key.pub
|
||||
sudo apt-key add openvpn-repo-pkg-key.pub
|
||||
sudo wget -O /etc/apt/sources.list.d/openvpn3.list https://swupdate.openvpn.net/community/openvpn3/repos/openvpn3-jammy.list
|
||||
sudo apt update
|
||||
sudo apt install openvpn3=17~betaUb22042+jammy
|
||||
|
||||
- name: Start Open VPN 3
|
||||
run: openvpn3 session-start --config .github/vpn/config.ovpn
|
||||
|
||||
- name: install pm2
|
||||
run: npm i -g pm2
|
||||
|
||||
- name: Deploy sasjs-tests
|
||||
run: |
|
||||
npm install -g replace-in-files-cli
|
||||
cd sasjs-tests
|
||||
replace-in-files --regex='"@sasjs/adapter".*' --replacement='"@sasjs/adapter":"latest",' ./package.json
|
||||
npm i
|
||||
npm i --legacy-peer-deps
|
||||
replace-in-files --regex='"serverUrl".*' --replacement='"serverUrl":"${{ secrets.SASJS_SERVER_URL }}",' ./public/config.json
|
||||
replace-in-files --regex='"userName".*' --replacement='"userName":"${{ secrets.SASJS_USERNAME }}",' ./public/config.json
|
||||
replace-in-files --regex='"password".*' --replacement='"password":"${{ secrets.SASJS_PASSWORD }}",' ./public/config.json
|
||||
replace-in-files --regex='"userName".*' --replacement='"userName":"${{ secrets.SASJS_USERNAME_DEV }}",' ./public/config.json
|
||||
replace-in-files --regex='"password".*' --replacement='"password":"${{ secrets.SASJS_PASSWORD_DEV }}",' ./public/config.json
|
||||
replace-in-files --regex='"serverType".*' --replacement='"serverType":"SASJS",' ./public/config.json
|
||||
npm run update:adapter && npm run build
|
||||
scp -o stricthostkeychecking=no -r ./build/* ${{ secrets.DCGITLAB_DEPLOY_PATH_VIYA }}
|
||||
# npm run update:adapter
|
||||
pm2 start --name sasjs-test npm -- start
|
||||
cat ./public/config.json
|
||||
cat ../cypress.json
|
||||
|
||||
- name: Sleep for 10 seconds
|
||||
uses: jakejarvis/wait-action@master
|
||||
with:
|
||||
time: '10s'
|
||||
|
||||
- name: Run cypress on sasjs
|
||||
run: |
|
||||
replace-in-files --regex='"sasjsTestsUrl".*' --replacement='"sasjsTestsUrl":"${{ secrets.SASJS_TEST_URL_VIYA }}",' ./cypress.json
|
||||
replace-in-files --regex='"username".*' --replacement='"username":"${{ secrets.SASJS_USERNAME }}",' ./cypress.json
|
||||
replace-in-files --regex='"password".*' --replacement='"password":"${{ secrets.SASJS_PASSWORD }}",' ./cypress.json
|
||||
ss -lntu
|
||||
replace-in-files --regex='"sasjsTestsUrl".*' --replacement='"sasjsTestsUrl":"http://localhost:3000",' ./cypress.json
|
||||
replace-in-files --regex='"username".*' --replacement='"username":"${{ secrets.SASJS_USERNAME_DEV }}",' ./cypress.json
|
||||
replace-in-files --regex='"password".*' --replacement='"password":"${{ secrets.SASJS_PASSWORD_DEV }}",' ./cypress.json
|
||||
sh ./sasjs-tests/sasjs-cypress-run.sh ${{ secrets.MATRIX_TOKEN }} https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
|
||||
|
||||
# For some reason if coverage report action is run before other commands, those commands can't access the directories and files on which they depend on
|
||||
|
||||
@@ -5,6 +5,9 @@ const testingFinishTimeout = Cypress.env('testingFinishTimeout')
|
||||
|
||||
context('sasjs-tests', function () {
|
||||
this.beforeAll(() => {
|
||||
cy.task('log', 'beforeAll')
|
||||
cy.task('log', `sasjsTestsUrl: ${sasjsTestsUrl}`)
|
||||
|
||||
cy.visit(sasjsTestsUrl)
|
||||
})
|
||||
|
||||
@@ -13,66 +16,115 @@ context('sasjs-tests', function () {
|
||||
})
|
||||
|
||||
it('Should have all tests successfull', (done) => {
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find('input[placeholder="User Name"]').length > 0) {
|
||||
cy.get('input[placeholder="User Name"]').type(username)
|
||||
cy.get('input[placeholder="Password"]').type(password)
|
||||
cy.get('.submit-button').click()
|
||||
}
|
||||
cy.task('log', `Should have all tests successfull`)
|
||||
|
||||
cy.get('input[placeholder="User Name"]', { timeout: 40000 })
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.get('.ui.massive.icon.primary.left.labeled.button')
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get('.ui.massive.loading.primary.button', {
|
||||
timeout: testingFinishTimeout
|
||||
})
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.get('span.icon.failed')
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
done()
|
||||
})
|
||||
cy.get('body').then(($body) => {
|
||||
cy.task('log', `22`)
|
||||
cy.wait(1000).then(() => {
|
||||
const startButton = $body.find(
|
||||
'.ui.massive.icon.primary.left.labeled.button'
|
||||
)[0]
|
||||
|
||||
// ui massive icon primary left labeled button
|
||||
|
||||
cy.task('log', `startButton: ${startButton}`)
|
||||
|
||||
if (
|
||||
!startButton ||
|
||||
(startButton && !Cypress.dom.isVisible(startButton))
|
||||
) {
|
||||
cy.task('log', `34`)
|
||||
cy.task('log', `username: ${username}`)
|
||||
cy.task('log', `password: ${password}`)
|
||||
|
||||
const userNameInput = cy.get('input[placeholder="User Name"]')
|
||||
const passwordInput = cy.get('input[placeholder="Password"]')
|
||||
|
||||
cy.task('log', `userNameInput: ${userNameInput}`)
|
||||
cy.task('log', `passwordInput: ${passwordInput}`)
|
||||
|
||||
cy.get('input[placeholder="User Name"]').type(username)
|
||||
cy.get('input[placeholder="Password"]').type(password)
|
||||
const submitBtn = cy.get('.submit-button')
|
||||
|
||||
cy.task('log', `submitBtn: ${submitBtn}`)
|
||||
cy.get('.submit-button').click()
|
||||
}
|
||||
|
||||
cy.get('input[placeholder="User Name"]', { timeout: 40000 })
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.task('log', `46`)
|
||||
cy.get('.ui.massive.icon.primary.left.labeled.button')
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.task('log', `50`)
|
||||
|
||||
const loadingButton = $body.find(
|
||||
'.ui.massive.loading.primary.button'
|
||||
)[0]
|
||||
|
||||
cy.task('log', `loadingButton: ${loadingButton}`)
|
||||
|
||||
cy.get('.ui.massive.loading.primary.button', {
|
||||
timeout: testingFinishTimeout
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('Should have all tests successfull with debug on', (done) => {
|
||||
cy.get('body').then(($body) => {
|
||||
if ($body.find('input[placeholder="User Name"]').length > 0) {
|
||||
cy.get('input[placeholder="User Name"]').type(username)
|
||||
cy.get('input[placeholder="Password"]').type(password)
|
||||
cy.get('.submit-button').click()
|
||||
}
|
||||
|
||||
cy.get('.ui.fitted.toggle.checkbox label')
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get('input[placeholder="User Name"]', { timeout: 40000 })
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.get('.ui.massive.icon.primary.left.labeled.button')
|
||||
.click()
|
||||
.then(() => {
|
||||
cy.get('.ui.massive.loading.primary.button', {
|
||||
timeout: testingFinishTimeout
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.task('log', `56`)
|
||||
cy.get('span.icon.failed')
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.task('log', `60`)
|
||||
done()
|
||||
})
|
||||
})
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
cy.get('span.icon.failed')
|
||||
.should('not.exist')
|
||||
.then(() => {
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// it('Should have all tests successfull with debug on', (done) => {
|
||||
// cy.get('body').then(($body) => {
|
||||
// cy.wait(1000).then(() => {
|
||||
// const startButton = $body.find(
|
||||
// '.ui.massive.icon.primary.left.labeled.button'
|
||||
// )[0]
|
||||
|
||||
// if (
|
||||
// !startButton ||
|
||||
// (startButton && !Cypress.dom.isVisible(startButton))
|
||||
// ) {
|
||||
// cy.get('input[placeholder="User Name"]').type(username)
|
||||
// cy.get('input[placeholder="Password"]').type(password)
|
||||
// cy.get('.submit-button').click()
|
||||
// }
|
||||
|
||||
// cy.get('.ui.fitted.toggle.checkbox label')
|
||||
// .click()
|
||||
// .then(() => {
|
||||
// cy.get('input[placeholder="User Name"]', { timeout: 40000 })
|
||||
// .should('not.exist')
|
||||
// .then(() => {
|
||||
// cy.get('.ui.massive.icon.primary.left.labeled.button')
|
||||
// .click()
|
||||
// .then(() => {
|
||||
// cy.get('.ui.massive.loading.primary.button', {
|
||||
// timeout: testingFinishTimeout
|
||||
// })
|
||||
// .should('not.exist')
|
||||
// .then(() => {
|
||||
// cy.get('span.icon.failed')
|
||||
// .should('not.exist')
|
||||
// .then(() => {
|
||||
// done()
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
})
|
||||
|
||||
@@ -39,4 +39,11 @@ module.exports = (on, config) => {
|
||||
return launchOptions
|
||||
}
|
||||
})
|
||||
|
||||
on('task', {
|
||||
log(message) {
|
||||
console.log(message)
|
||||
return null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
25
cypress/support/commands.js
Normal file
25
cypress/support/commands.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
20
cypress/support/index.js
Normal file
20
cypress/support/index.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -32,7 +32,7 @@
|
||||
"node-polyfill-webpack-plugin": "1.1.4",
|
||||
"path": "0.12.7",
|
||||
"pem": "1.14.5",
|
||||
"prettier": "2.7.1",
|
||||
"prettier": "2.8.7",
|
||||
"process": "0.11.10",
|
||||
"rimraf": "3.0.2",
|
||||
"semantic-release": "19.0.3",
|
||||
@@ -13925,9 +13925,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"version": "2.8.7",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
|
||||
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
@@ -27416,9 +27416,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"version": "2.8.7",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
|
||||
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-bytes": {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"node-polyfill-webpack-plugin": "1.1.4",
|
||||
"path": "0.12.7",
|
||||
"pem": "1.14.5",
|
||||
"prettier": "2.7.1",
|
||||
"prettier": "2.8.7",
|
||||
"process": "0.11.10",
|
||||
"rimraf": "3.0.2",
|
||||
"semantic-release": "19.0.3",
|
||||
|
||||
5
sasjs-tests/.gitignore
vendored
5
sasjs-tests/.gitignore
vendored
@@ -13,10 +13,7 @@
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.*
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
1367
sasjs-tests/package-lock.json
generated
1367
sasjs-tests/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
"homepage": ".",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@sasjs/adapter": "file:../build/sasjs-adapter-5.0.0.tgz",
|
||||
"@sasjs/adapter": "4.3.5",
|
||||
"@sasjs/test-framework": "1.5.7",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^14.14.41",
|
||||
@@ -45,4 +45,4 @@
|
||||
"devDependencies": {
|
||||
"node-sass": "7.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
"userName": "",
|
||||
"password": "",
|
||||
"sasJsConfig": {
|
||||
"serverUrl": "",
|
||||
"appLoc": "/Public/app/adapter-tests",
|
||||
"serverUrl": "https://sas9.4gl.io",
|
||||
"appLoc": "/Public/app/adapter-tests/services",
|
||||
"serverType": "SASJS",
|
||||
"debug": false,
|
||||
"contextName": "sasjs adapter compute context",
|
||||
"useComputeApi": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,23 @@
|
||||
"targets": [
|
||||
{
|
||||
"name": "4gl",
|
||||
"serverType": "SASJS",
|
||||
"serverUrl": "https://sas9.4gl.io",
|
||||
"appLoc": "/Public/app/adapter-tests"
|
||||
"serverType": "SASJS",
|
||||
"httpsAgentOptions": {
|
||||
"allowInsecureRequests": false
|
||||
},
|
||||
"appLoc": "/Public/app/adapter-tests",
|
||||
"deployConfig": {
|
||||
"deployServicePack": true,
|
||||
"deployScripts": []
|
||||
},
|
||||
"streamConfig": {
|
||||
"streamWeb": true,
|
||||
"streamWebFolder": "webv",
|
||||
"webSourcePath": "build",
|
||||
"streamServiceName": "adapter-tests",
|
||||
"assetPaths": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -11,7 +11,7 @@ const Login = (): ReactElement<{}> => {
|
||||
const handleSubmit = useCallback(
|
||||
(e: any) => {
|
||||
e.preventDefault()
|
||||
appContext.adapter.logIn(username, password).then((res) => {
|
||||
appContext.adapter.logIn(username, password).then((res: any) => {
|
||||
appContext.setIsLoggedIn(res.isLoggedIn)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -29,11 +29,33 @@ describe('SASViyaApiClient', () => {
|
||||
jest
|
||||
.spyOn(requestClient, 'get')
|
||||
.mockImplementation(() => Promise.reject('Not Found'))
|
||||
|
||||
const error = await sasViyaApiClient
|
||||
.createFolder('test', '/foo')
|
||||
.catch((e: any) => e)
|
||||
|
||||
expect(error).toBeInstanceOf(RootFolderNotFoundError)
|
||||
})
|
||||
|
||||
it('should throw an error when ', async () => {
|
||||
const testMessage1 = 'test message 1'
|
||||
const testMessage2 = 'test message 2.'
|
||||
|
||||
jest.spyOn(requestClient, 'post').mockImplementation(() => {
|
||||
return Promise.reject({
|
||||
message: testMessage1,
|
||||
response: { data: { message: testMessage2 }, status: 409 }
|
||||
})
|
||||
})
|
||||
|
||||
const error = await sasViyaApiClient
|
||||
.createFolder('test', '/foo')
|
||||
.catch((e: any) => e)
|
||||
|
||||
const expectedError = `${testMessage1}. ${testMessage2} To override, please set "isForced" to "true".`
|
||||
|
||||
expect(error).toEqual(expectedError)
|
||||
})
|
||||
})
|
||||
|
||||
const setupMocks = () => {
|
||||
|
||||
@@ -378,12 +378,14 @@ export class SASViyaApiClient {
|
||||
isForced?: boolean
|
||||
): Promise<Folder> {
|
||||
const logger = process.logger || console
|
||||
|
||||
if (!parentFolderPath && !parentFolderUri) {
|
||||
throw new Error('Path or URI of the parent folder is required.')
|
||||
}
|
||||
|
||||
if (!parentFolderUri && parentFolderPath) {
|
||||
parentFolderUri = await this.getFolderUri(parentFolderPath, accessToken)
|
||||
|
||||
if (!parentFolderUri) {
|
||||
logger.info(
|
||||
`Parent folder at path '${parentFolderPath}' is not present.`
|
||||
@@ -394,6 +396,7 @@ export class SASViyaApiClient {
|
||||
parentFolderPath.lastIndexOf('/')
|
||||
)
|
||||
const newFolderName = `${parentFolderPath.split('/').pop()}`
|
||||
|
||||
if (newParentFolderPath === '') {
|
||||
throw new RootFolderNotFoundError(
|
||||
parentFolderPath,
|
||||
@@ -401,20 +404,24 @@ export class SASViyaApiClient {
|
||||
accessToken
|
||||
)
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Creating parent folder:\n'${newFolderName}' in '${newParentFolderPath}'`
|
||||
)
|
||||
|
||||
const parentFolder = await this.createFolder(
|
||||
newFolderName,
|
||||
newParentFolderPath,
|
||||
undefined,
|
||||
accessToken
|
||||
)
|
||||
|
||||
logger.info(
|
||||
`Parent folder '${newFolderName}' has been successfully created.`
|
||||
)
|
||||
|
||||
parentFolderUri = `/folders/folders/${parentFolder.id}`
|
||||
} else if (isForced && accessToken) {
|
||||
} else if (isForced) {
|
||||
const folderPath = parentFolderPath + '/' + folderName
|
||||
const folderUri = await this.getFolderUri(folderPath, accessToken)
|
||||
|
||||
@@ -427,8 +434,8 @@ export class SASViyaApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
const { result: createFolderResponse } =
|
||||
await this.requestClient.post<Folder>(
|
||||
const { result: createFolderResponse } = await this.requestClient
|
||||
.post<Folder>(
|
||||
`/folders/folders?parentFolderUri=${parentFolderUri}`,
|
||||
{
|
||||
name: folderName,
|
||||
@@ -436,12 +443,34 @@ export class SASViyaApiClient {
|
||||
},
|
||||
accessToken
|
||||
)
|
||||
.catch((err) => {
|
||||
const { message, response } = err
|
||||
|
||||
if (message && response && response.data && response.data.message) {
|
||||
const { status } = response
|
||||
const { message: responseMessage } = response.data
|
||||
const messages = [message, responseMessage].map((mes: string) =>
|
||||
/\.$/.test(mes) ? mes : `${mes}.`
|
||||
)
|
||||
|
||||
if (!isForced && status === 409) {
|
||||
messages.push(`To override, please set "isForced" to "true".`)
|
||||
}
|
||||
|
||||
const errMessage = messages.join(' ')
|
||||
|
||||
throw errMessage
|
||||
}
|
||||
|
||||
throw err
|
||||
})
|
||||
|
||||
// update folder map with newly created folder.
|
||||
await this.populateFolderMap(
|
||||
`${parentFolderPath}/${folderName}`,
|
||||
accessToken
|
||||
)
|
||||
|
||||
return createFolderResponse
|
||||
}
|
||||
|
||||
@@ -900,7 +929,7 @@ export class SASViyaApiClient {
|
||||
return `/folders/folders/${folderDetails.id}`
|
||||
}
|
||||
|
||||
private async getRecycleBinUri(accessToken: string) {
|
||||
private async getRecycleBinUri(accessToken?: string) {
|
||||
const url = '/folders/folders/@myRecycleBin'
|
||||
|
||||
const { result: folder } = await this.requestClient
|
||||
@@ -984,7 +1013,7 @@ export class SASViyaApiClient {
|
||||
sourceFolder: string,
|
||||
targetParentFolder: string,
|
||||
targetFolderName: string,
|
||||
accessToken: string
|
||||
accessToken?: string
|
||||
) {
|
||||
// If target path is an existing folder, than keep source folder name, othervise rename it with given target folder name
|
||||
const sourceFolderName = sourceFolder.split('/').pop() as string
|
||||
@@ -1051,7 +1080,7 @@ export class SASViyaApiClient {
|
||||
* @param folderPath - the full path (eg `/Public/example/deleteThis`) of the folder to be deleted.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
*/
|
||||
public async deleteFolder(folderPath: string, accessToken: string) {
|
||||
public async deleteFolder(folderPath: string, accessToken?: string) {
|
||||
const recycleBinUri = await this.getRecycleBinUri(accessToken)
|
||||
const folderName = folderPath.split('/').pop() || ''
|
||||
const date = new Date()
|
||||
|
||||
19
src/SASjs.ts
19
src/SASjs.ts
@@ -337,13 +337,16 @@ export default class SASjs {
|
||||
sasApiClient?: SASViyaApiClient,
|
||||
isForced?: boolean
|
||||
) {
|
||||
if (sasApiClient)
|
||||
if (sasApiClient) {
|
||||
return await sasApiClient.createFolder(
|
||||
folderName,
|
||||
parentFolderPath,
|
||||
parentFolderUri,
|
||||
accessToken
|
||||
accessToken,
|
||||
isForced
|
||||
)
|
||||
}
|
||||
|
||||
return await this.sasViyaApiClient!.createFolder(
|
||||
folderName,
|
||||
parentFolderPath,
|
||||
@@ -783,13 +786,11 @@ export default class SASjs {
|
||||
this.isMethodSupported('deployServicePack', [ServerType.SasViya])
|
||||
|
||||
let sasApiClient: any = null
|
||||
|
||||
if (serverUrl || appLoc) {
|
||||
if (!serverUrl) {
|
||||
serverUrl = this.sasjsConfig.serverUrl
|
||||
}
|
||||
if (!appLoc) {
|
||||
appLoc = this.sasjsConfig.appLoc
|
||||
}
|
||||
if (!serverUrl) serverUrl = this.sasjsConfig.serverUrl
|
||||
if (!appLoc) appLoc = this.sasjsConfig.appLoc
|
||||
|
||||
if (this.sasjsConfig.serverType === ServerType.SasViya) {
|
||||
sasApiClient = new SASViyaApiClient(
|
||||
serverUrl,
|
||||
@@ -807,11 +808,13 @@ export default class SASjs {
|
||||
}
|
||||
} else {
|
||||
let sasClientConfig: any = null
|
||||
|
||||
if (this.sasjsConfig.serverType === ServerType.SasViya) {
|
||||
sasClientConfig = this.sasViyaApiClient!.getConfig()
|
||||
} else if (this.sasjsConfig.serverType === ServerType.Sas9) {
|
||||
sasClientConfig = this.sas9ApiClient!.getConfig()
|
||||
}
|
||||
|
||||
serverUrl = sasClientConfig.serverUrl
|
||||
appLoc = sasClientConfig.rootFolderName as string
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { prefixMessage } from '@sasjs/utils/error'
|
||||
import { RequestClient } from '../request/RequestClient'
|
||||
import { getTokenRequestErrorPrefix } from './getTokenRequestErrorPrefix'
|
||||
import { ServerType } from '@sasjs/utils'
|
||||
|
||||
/**
|
||||
* Exchanges the auth code for an access token for the given client.
|
||||
@@ -31,6 +33,16 @@ export async function getAccessTokenForSasjs(
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
throw prefixMessage(err, 'Error while getting access token. ')
|
||||
throw prefixMessage(
|
||||
err,
|
||||
getTokenRequestErrorPrefix(
|
||||
'fetching access token',
|
||||
'getAccessTokenForSasjs',
|
||||
ServerType.Sasjs,
|
||||
url,
|
||||
data,
|
||||
clientId
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { SasAuthResponse } from '@sasjs/utils/types'
|
||||
import { SasAuthResponse, ServerType } from '@sasjs/utils/types'
|
||||
import { prefixMessage } from '@sasjs/utils/error'
|
||||
import { RequestClient } from '../request/RequestClient'
|
||||
import { CertificateError } from '../types/errors'
|
||||
import { getTokenRequestErrorPrefix } from './getTokenRequestErrorPrefix'
|
||||
|
||||
// TODO: update func docs
|
||||
/**
|
||||
* Exchanges the auth code for an access token for the given client.
|
||||
* @param requestClient - the pre-configured HTTP request client
|
||||
* Exchange the auth code for access / refresh tokens for the given client / secret pair.
|
||||
* @param requestClient - the pre-configured HTTP request client.
|
||||
* @param clientId - the client ID to authenticate with.
|
||||
* @param clientSecret - the client secret to authenticate with.
|
||||
* @param authCode - the auth code received from the server.
|
||||
@@ -16,29 +18,43 @@ export async function getAccessTokenForViya(
|
||||
clientSecret: string,
|
||||
authCode: string
|
||||
): Promise<SasAuthResponse> {
|
||||
const url = '/SASLogon/oauth/token'
|
||||
let token
|
||||
|
||||
if (typeof Buffer === 'undefined') {
|
||||
token = btoa(clientId + ':' + clientSecret)
|
||||
} else {
|
||||
token = Buffer.from(clientId + ':' + clientSecret).toString('base64')
|
||||
}
|
||||
|
||||
const url = '/SASLogon/oauth/token'
|
||||
const headers = {
|
||||
Authorization: 'Basic ' + token,
|
||||
Accept: 'application/json'
|
||||
}
|
||||
|
||||
const data = new URLSearchParams({
|
||||
const dataJson = {
|
||||
grant_type: 'authorization_code',
|
||||
code: authCode
|
||||
})
|
||||
}
|
||||
const data = new URLSearchParams(dataJson)
|
||||
|
||||
const authResponse = await requestClient
|
||||
.post(url, data, undefined, 'application/x-www-form-urlencoded', headers)
|
||||
.then((res) => res.result as SasAuthResponse)
|
||||
.catch((err) => {
|
||||
if (err instanceof CertificateError) throw err
|
||||
throw prefixMessage(err, 'Error while getting access token. ')
|
||||
throw prefixMessage(
|
||||
err,
|
||||
getTokenRequestErrorPrefix(
|
||||
'fetching access token',
|
||||
'getAccessTokenForViya',
|
||||
ServerType.SasViya,
|
||||
url,
|
||||
dataJson,
|
||||
headers,
|
||||
clientId,
|
||||
clientSecret
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
return authResponse
|
||||
|
||||
88
src/auth/getTokenRequestErrorPrefix.ts
Normal file
88
src/auth/getTokenRequestErrorPrefix.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { ServerType } from '@sasjs/utils/types'
|
||||
|
||||
type Server = ServerType.SasViya | ServerType.Sasjs
|
||||
type Operation = 'fetching access token' | 'refreshing tokens'
|
||||
|
||||
const getServerName = (server: Server) =>
|
||||
server === ServerType.SasViya ? 'Viya' : 'Sasjs'
|
||||
|
||||
const getResponseTitle = (server: Server) =>
|
||||
`Response from ${getServerName(server)} is below.`
|
||||
|
||||
/**
|
||||
* Forms error prefix for requests related to token operations.
|
||||
* @param operation - string describing operation ('fetching access token' or 'refreshing tokens').
|
||||
* @param funcName - name of the function sent the request.
|
||||
* @param server - server type (SASVIYA or SASJS).
|
||||
* @param url - endpoint used to send the request.
|
||||
* @param data - request payload.
|
||||
* @param headers - request headers.
|
||||
* @param clientId - client ID to authenticate with.
|
||||
* @param clientSecret - client secret to authenticate with.
|
||||
* @returns - string containing request information. Example:
|
||||
* Error while fetching access token from /SASLogon/oauth/token
|
||||
* Thrown by the @sasjs/adapter getAccessTokenForViya function.
|
||||
* Payload:
|
||||
* {
|
||||
* "grant_type": "authorization_code",
|
||||
* "code": "example_code"
|
||||
* }
|
||||
* Headers:
|
||||
* {
|
||||
* "Authorization": "Basic NEdMQXBwOjRHTEFwcDE=",
|
||||
* "Accept": "application/json"
|
||||
* }
|
||||
* ClientId: exampleClientId
|
||||
* ClientSecret: exampleClientSecret
|
||||
*
|
||||
* Response from Viya is below.
|
||||
* Auth error: {
|
||||
* "error": "invalid_token",
|
||||
* "error_description": "No scopes were granted"
|
||||
* }
|
||||
*/
|
||||
export const getTokenRequestErrorPrefix = (
|
||||
operation: Operation,
|
||||
funcName: string,
|
||||
server: Server,
|
||||
url: string,
|
||||
data?: {},
|
||||
headers?: {},
|
||||
clientId?: string,
|
||||
clientSecret?: string
|
||||
) => {
|
||||
const stringify = (obj: {}) => JSON.stringify(obj, null, 2)
|
||||
|
||||
const lines = [
|
||||
`Error while ${operation} from ${url}`,
|
||||
`Thrown by the @sasjs/adapter ${funcName} function.`
|
||||
]
|
||||
|
||||
if (data) {
|
||||
lines.push('Payload:')
|
||||
lines.push(stringify(data))
|
||||
}
|
||||
if (headers) {
|
||||
lines.push('Headers:')
|
||||
lines.push(stringify(headers))
|
||||
}
|
||||
if (clientId) lines.push(`ClientId: ${clientId}`)
|
||||
if (clientSecret) lines.push(`ClientSecret: ${clientSecret}`)
|
||||
|
||||
lines.push('')
|
||||
lines.push(`${getResponseTitle(server)}`)
|
||||
lines.push('')
|
||||
|
||||
return lines.join(`\n`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse error prefix to get response payload.
|
||||
* @param prefix - error prefix generated by getTokenRequestErrorPrefix function.
|
||||
* @param server - server type (SASVIYA or SASJS).
|
||||
* @returns - response payload.
|
||||
*/
|
||||
export const getTokenRequestErrorPrefixResponse = (
|
||||
prefix: string,
|
||||
server: ServerType.SasViya | ServerType.Sasjs
|
||||
) => prefix.split(`${getResponseTitle(server)}\n`).pop() as string
|
||||
@@ -22,6 +22,7 @@ export async function getTokens(
|
||||
): Promise<AuthConfig> {
|
||||
const logger = process.logger || console
|
||||
let { access_token, refresh_token, client, secret } = authConfig
|
||||
|
||||
if (
|
||||
isAccessTokenExpiring(access_token) ||
|
||||
isRefreshTokenExpiring(refresh_token)
|
||||
@@ -29,6 +30,7 @@ export async function getTokens(
|
||||
if (hasTokenExpired(refresh_token)) {
|
||||
const error =
|
||||
'Unable to obtain new access token. Your refresh token has expired.'
|
||||
|
||||
logger.error(error)
|
||||
|
||||
throw new Error(error)
|
||||
@@ -47,5 +49,6 @@ export async function getTokens(
|
||||
: await refreshTokensForSasjs(requestClient, refresh_token)
|
||||
;({ access_token, refresh_token } = tokens)
|
||||
}
|
||||
|
||||
return { access_token, refresh_token, client, secret }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { prefixMessage } from '@sasjs/utils/error'
|
||||
import { RequestClient } from '../request/RequestClient'
|
||||
import { getTokenRequestErrorPrefix } from './getTokenRequestErrorPrefix'
|
||||
import { ServerType } from '@sasjs/utils'
|
||||
|
||||
/**
|
||||
* Exchanges the refresh token for an access token for the given client.
|
||||
@@ -28,7 +30,15 @@ export async function refreshTokensForSasjs(
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
throw prefixMessage(err, 'Error while refreshing tokens: ')
|
||||
throw prefixMessage(
|
||||
err,
|
||||
getTokenRequestErrorPrefix(
|
||||
'refreshing tokens',
|
||||
'refreshTokensForSasjs',
|
||||
ServerType.Sasjs,
|
||||
url
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
return authResponse
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { SasAuthResponse } from '@sasjs/utils/types'
|
||||
import { SasAuthResponse, ServerType } from '@sasjs/utils/types'
|
||||
import { prefixMessage } from '@sasjs/utils/error'
|
||||
import * as NodeFormData from 'form-data'
|
||||
import { RequestClient } from '../request/RequestClient'
|
||||
import { isNode } from '../utils'
|
||||
import { getTokenRequestErrorPrefix } from './getTokenRequestErrorPrefix'
|
||||
|
||||
/**
|
||||
* Exchanges the refresh token for an access token for the given client.
|
||||
@@ -46,7 +47,19 @@ export async function refreshTokensForViya(
|
||||
)
|
||||
.then((res) => res.result)
|
||||
.catch((err) => {
|
||||
throw prefixMessage(err, 'Error while refreshing tokens: ')
|
||||
throw prefixMessage(
|
||||
err,
|
||||
getTokenRequestErrorPrefix(
|
||||
'refreshing tokens',
|
||||
'refreshTokensForViya',
|
||||
ServerType.SasViya,
|
||||
url,
|
||||
formData,
|
||||
headers,
|
||||
clientId,
|
||||
clientSecret
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
return authResponse
|
||||
|
||||
@@ -55,7 +55,7 @@ describe('getAccessTokenForSasjs', () => {
|
||||
authConfig.refresh_token
|
||||
).catch((e: any) => e)
|
||||
|
||||
expect(error).toContain('Error while getting access token')
|
||||
expect(error).toContain('Error while fetching access token')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('getAccessTokenForViya', () => {
|
||||
authConfig.refresh_token
|
||||
).catch((e: any) => e)
|
||||
|
||||
expect(error).toContain('Error while getting access token')
|
||||
expect(error).toContain('Error while fetching access token')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
81
src/auth/spec/getTokenRequestErrorPrefix.spec.ts
Normal file
81
src/auth/spec/getTokenRequestErrorPrefix.spec.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { ServerType } from '@sasjs/utils/types'
|
||||
import { getTokenRequestErrorPrefix } from '../getTokenRequestErrorPrefix'
|
||||
|
||||
describe('getTokenRequestErrorPrefix', () => {
|
||||
it('should return error prefix', () => {
|
||||
// INFO: Viya with only required attributes
|
||||
let operation: 'fetching access token' = 'fetching access token'
|
||||
const funcName = 'testFunc'
|
||||
const url = '/SASjsApi/auth/token'
|
||||
|
||||
let expectedPrefix = `Error while ${operation} from ${url}
|
||||
Thrown by the @sasjs/adapter ${funcName} function.
|
||||
|
||||
Response from Viya is below.
|
||||
`
|
||||
|
||||
expect(
|
||||
getTokenRequestErrorPrefix(operation, funcName, ServerType.SasViya, url)
|
||||
).toEqual(expectedPrefix)
|
||||
|
||||
// INFO: Sasjs with data and headers
|
||||
const data = {
|
||||
grant_type: 'authorization_code',
|
||||
code: 'testCode'
|
||||
}
|
||||
const headers = {
|
||||
Authorization: 'Basic test=',
|
||||
Accept: 'application/json'
|
||||
}
|
||||
|
||||
expectedPrefix = `Error while ${operation} from ${url}
|
||||
Thrown by the @sasjs/adapter ${funcName} function.
|
||||
Payload:
|
||||
${JSON.stringify(data, null, 2)}
|
||||
Headers:
|
||||
${JSON.stringify(headers, null, 2)}
|
||||
|
||||
Response from Sasjs is below.
|
||||
`
|
||||
|
||||
expect(
|
||||
getTokenRequestErrorPrefix(
|
||||
operation,
|
||||
funcName,
|
||||
ServerType.Sasjs,
|
||||
url,
|
||||
data,
|
||||
headers
|
||||
)
|
||||
).toEqual(expectedPrefix)
|
||||
|
||||
// INFO: Viya with all attributes
|
||||
const clientId = 'testId'
|
||||
const clientSecret = 'testSecret'
|
||||
|
||||
expectedPrefix = `Error while ${operation} from ${url}
|
||||
Thrown by the @sasjs/adapter ${funcName} function.
|
||||
Payload:
|
||||
${JSON.stringify(data, null, 2)}
|
||||
Headers:
|
||||
${JSON.stringify(headers, null, 2)}
|
||||
ClientId: ${clientId}
|
||||
ClientSecret: ${clientSecret}
|
||||
|
||||
Response from Viya is below.
|
||||
`
|
||||
|
||||
expect(
|
||||
getTokenRequestErrorPrefix(
|
||||
operation,
|
||||
funcName,
|
||||
ServerType.SasViya,
|
||||
url,
|
||||
data,
|
||||
headers,
|
||||
clientId,
|
||||
clientSecret
|
||||
)
|
||||
).toEqual(expectedPrefix)
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ServerType } from '@sasjs/utils'
|
||||
import { generateToken, mockAuthResponse } from './mockResponses'
|
||||
import { RequestClient } from '../../request/RequestClient'
|
||||
import { refreshTokensForSasjs } from '../refreshTokensForSasjs'
|
||||
import { getTokenRequestErrorPrefixResponse } from '../getTokenRequestErrorPrefix'
|
||||
|
||||
const requestClient = new (<jest.Mock<RequestClient>>RequestClient)()
|
||||
|
||||
@@ -38,9 +40,9 @@ describe('refreshTokensForSasjs', () => {
|
||||
const error = await refreshTokensForSasjs(
|
||||
requestClient,
|
||||
refresh_token
|
||||
).catch((e: any) => e)
|
||||
).catch((e: any) => getTokenRequestErrorPrefixResponse(e, ServerType.Sasjs))
|
||||
|
||||
expect(error).toEqual(`Error while refreshing tokens: ${tokenError}`)
|
||||
expect(error).toEqual(tokenError)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { AuthConfig } from '@sasjs/utils'
|
||||
import { AuthConfig, ServerType } from '@sasjs/utils'
|
||||
import * as NodeFormData from 'form-data'
|
||||
import { generateToken, mockAuthResponse } from './mockResponses'
|
||||
import { RequestClient } from '../../request/RequestClient'
|
||||
import { refreshTokensForViya } from '../refreshTokensForViya'
|
||||
import * as IsNodeModule from '../../utils/isNode'
|
||||
import { getTokenRequestErrorPrefixResponse } from '../getTokenRequestErrorPrefix'
|
||||
|
||||
const requestClient = new (<jest.Mock<RequestClient>>RequestClient)()
|
||||
|
||||
@@ -67,9 +68,11 @@ describe('refreshTokensForViya', () => {
|
||||
authConfig.client,
|
||||
authConfig.secret,
|
||||
authConfig.refresh_token
|
||||
).catch((e: any) => e)
|
||||
).catch((e: any) =>
|
||||
getTokenRequestErrorPrefixResponse(e, ServerType.SasViya)
|
||||
)
|
||||
|
||||
expect(error).toEqual(`Error while refreshing tokens: ${tokenError}`)
|
||||
expect(error).toEqual(tokenError)
|
||||
})
|
||||
|
||||
it('should throw an error if environment is not Node', async () => {
|
||||
|
||||
@@ -48,7 +48,7 @@ export class SasjsRequestClient extends RequestClient {
|
||||
const splittedResponse = response.data.split(SASJS_LOGS_SEPARATOR)
|
||||
|
||||
webout = splittedResponse[0]
|
||||
if (webout) parsedResponse = webout
|
||||
if (webout !== undefined) parsedResponse = webout
|
||||
|
||||
log = splittedResponse[1]
|
||||
printOutput = splittedResponse[2]
|
||||
|
||||
@@ -11,8 +11,8 @@ import {
|
||||
NotFoundError,
|
||||
InternalServerError
|
||||
} from '../types/errors'
|
||||
import { prefixMessage } from '@sasjs/utils/error'
|
||||
import { RequestClient } from '../request/RequestClient'
|
||||
import { getTokenRequestErrorPrefixResponse } from '../auth/getTokenRequestErrorPrefix'
|
||||
|
||||
const axiosActual = jest.requireActual('axios')
|
||||
|
||||
@@ -66,14 +66,18 @@ describe('RequestClient', () => {
|
||||
})
|
||||
|
||||
it('should response the POST method with Unauthorized', async () => {
|
||||
await expect(
|
||||
adapter.getAccessToken('clientId', 'clientSecret', 'incorrect')
|
||||
).rejects.toEqual(
|
||||
prefixMessage(
|
||||
new LoginRequiredError(incorrectAuthCodeErr),
|
||||
'Error while getting access token. '
|
||||
const expectedError = new LoginRequiredError({
|
||||
error: 'unauthorized',
|
||||
error_description: 'Bad credentials'
|
||||
})
|
||||
|
||||
const rejectionErrorMessage = await adapter
|
||||
.getAccessToken('clientId', 'clientSecret', 'incorrect')
|
||||
.catch((err) =>
|
||||
getTokenRequestErrorPrefixResponse(err.message, ServerType.SasViya)
|
||||
)
|
||||
)
|
||||
|
||||
expect(rejectionErrorMessage).toEqual(expectedError.message)
|
||||
})
|
||||
|
||||
describe('handleError', () => {
|
||||
@@ -209,15 +213,15 @@ describe('RequestClient - Self Signed Server', () => {
|
||||
serverType: ServerType.SasViya
|
||||
})
|
||||
|
||||
await expect(
|
||||
adapterWithoutCertificate.getAccessToken(
|
||||
'clientId',
|
||||
'clientSecret',
|
||||
'authCode'
|
||||
const expectedError = 'self signed certificate'
|
||||
|
||||
const rejectionErrorMessage = await adapterWithoutCertificate
|
||||
.getAccessToken('clientId', 'clientSecret', 'authCode')
|
||||
.catch((err) =>
|
||||
getTokenRequestErrorPrefixResponse(err.message, ServerType.SasViya)
|
||||
)
|
||||
).rejects.toThrow(
|
||||
`Error while getting access token. ${ERROR_MESSAGES.selfSigned}`
|
||||
)
|
||||
|
||||
expect(rejectionErrorMessage).toEqual(expectedError)
|
||||
})
|
||||
|
||||
it('should response the POST method using insecure flag', async () => {
|
||||
@@ -247,14 +251,18 @@ describe('RequestClient - Self Signed Server', () => {
|
||||
})
|
||||
|
||||
it('should response the POST method with Unauthorized', async () => {
|
||||
await expect(
|
||||
adapter.getAccessToken('clientId', 'clientSecret', 'incorrect')
|
||||
).rejects.toEqual(
|
||||
prefixMessage(
|
||||
new LoginRequiredError(incorrectAuthCodeErr),
|
||||
'Error while getting access token. '
|
||||
const expectedError = new LoginRequiredError({
|
||||
error: 'unauthorized',
|
||||
error_description: 'Bad credentials'
|
||||
})
|
||||
|
||||
const rejectionErrorMessage = await adapter
|
||||
.getAccessToken('clientId', 'clientSecret', 'incorrect')
|
||||
.catch((err) =>
|
||||
getTokenRequestErrorPrefixResponse(err.message, ServerType.SasViya)
|
||||
)
|
||||
)
|
||||
|
||||
expect(rejectionErrorMessage).toEqual(expectedError.message)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user