mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-15 18:54:36 +00:00
501 lines
16 KiB
TypeScript
501 lines
16 KiB
TypeScript
import SASjs from '@sasjs/adapter'
|
|
import { TestSuite } from '@sasjs/test-framework'
|
|
|
|
const specialCharData: any = {
|
|
table1: [
|
|
{
|
|
tab: '\t',
|
|
lf: '\n',
|
|
cr: '\r',
|
|
semicolon: ';semi',
|
|
percent: '%',
|
|
singleQuote: "'",
|
|
doubleQuote: '"',
|
|
crlf: '\r\n',
|
|
euro: '€euro',
|
|
banghash: '!#banghash',
|
|
dot: '.'
|
|
}
|
|
]
|
|
}
|
|
|
|
const moreSpecialCharData: any = {
|
|
table1: [
|
|
{
|
|
speech0: '"speech',
|
|
pct: '%percent',
|
|
speech: '"speech',
|
|
slash: '\\slash',
|
|
slashWithSpecial: '\\\tslash',
|
|
macvar: '&sysuserid',
|
|
chinese: '传/傳chinese',
|
|
sigma: 'Σsigma',
|
|
at: '@at',
|
|
serbian: 'Српски',
|
|
dollar: '$'
|
|
}
|
|
]
|
|
}
|
|
|
|
const stringData: any = { table1: [{ col1: 'first col value' }] }
|
|
|
|
const getWideData = () => {
|
|
const cols: any = {}
|
|
for (let i = 1; i <= 10000; i++) {
|
|
cols['col' + i] = 'test' + i
|
|
}
|
|
|
|
const data: any = {
|
|
table1: [cols]
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
const getTables = () => {
|
|
const tables: any = {}
|
|
|
|
for (let i = 1; i <= 100; i++) {
|
|
tables['table' + i] = [{ col1: 'x', col2: 'x', col3: 'x', col4: 'x' }]
|
|
}
|
|
return tables
|
|
}
|
|
|
|
const getLargeDataset = () => {
|
|
const rows: any = []
|
|
const colData: string =
|
|
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
|
for (let i = 1; i <= 10000; i++) {
|
|
rows.push({ col1: colData, col2: colData, col3: colData, col4: colData })
|
|
}
|
|
|
|
const data: any = {
|
|
table1: rows
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
const errorAndCsrfData: any = {
|
|
error: [{ col1: 'q', col2: 'w', col3: 'e', col4: 'r' }],
|
|
_csrf: [{ col1: 'q', col2: 'w', col3: 'e', col4: 'r' }]
|
|
}
|
|
|
|
const testTable = 'sometable'
|
|
export const testTableWithSpecialNumeric: { [key: string]: any } = {
|
|
[testTable]: [
|
|
{ var1: 'string', var2: 232, specialnumeric: 'A' },
|
|
{ var1: 'string', var2: 232, specialnumeric: 'B' },
|
|
{ var1: 'string', var2: 232, specialnumeric: '_' },
|
|
{ var1: 'string', var2: 232, specialnumeric: 0 },
|
|
{ var1: 'string', var2: 232, specialnumeric: 'Z' },
|
|
{ var1: 'string', var2: 232, specialnumeric: null }
|
|
],
|
|
[`$${testTable}`]: { formats: { var1: '$char12.', specialnumeric: 'best.' } }
|
|
}
|
|
export const testTableWithSpecialNumericOneRow: { [key: string]: any } = {
|
|
[testTable]: [{ var1: 'string', var2: 232, specialnumeric: 'S' }],
|
|
[`$${testTable}`]: { formats: { var1: '$char12.', specialnumeric: 'best.' } }
|
|
}
|
|
export const testTableWithSpecialNumericLowercase: { [key: string]: any } = {
|
|
[testTable]: [{ var1: 'string', var2: 232, specialnumeric: 's' }],
|
|
[`$${testTable}`]: { formats: { var1: '$char12.', specialnumeric: 'best.' } }
|
|
}
|
|
|
|
export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
|
name: 'Special Cases',
|
|
tests: [
|
|
{
|
|
title: 'Common special characters',
|
|
description: 'Should handle common special characters',
|
|
test: () => {
|
|
return adapter.request('common/sendArr', specialCharData)
|
|
},
|
|
assertion: (res: any) => {
|
|
return (
|
|
res.table1[0][0] === specialCharData.table1[0].tab &&
|
|
res.table1[0][1] === specialCharData.table1[0].lf &&
|
|
res.table1[0][2] === specialCharData.table1[0].cr &&
|
|
res.table1[0][3] === specialCharData.table1[0].semicolon &&
|
|
res.table1[0][4] === specialCharData.table1[0].percent &&
|
|
res.table1[0][5] === specialCharData.table1[0].singleQuote &&
|
|
res.table1[0][6] === specialCharData.table1[0].doubleQuote &&
|
|
res.table1[0][7] === '\n' &&
|
|
res.table1[0][8] === specialCharData.table1[0].euro &&
|
|
res.table1[0][9] === specialCharData.table1[0].banghash &&
|
|
res.table1[0][10] === specialCharData.table1[0].dot
|
|
)
|
|
}
|
|
},
|
|
{
|
|
title: 'Other special characters',
|
|
description: 'Should handle other special characters',
|
|
test: () => {
|
|
return adapter.request('common/sendArr', moreSpecialCharData)
|
|
},
|
|
assertion: (res: any) => {
|
|
return (
|
|
res.table1[0][0] === moreSpecialCharData.table1[0].speech0 &&
|
|
res.table1[0][1] === moreSpecialCharData.table1[0].pct &&
|
|
res.table1[0][2] === moreSpecialCharData.table1[0].speech &&
|
|
res.table1[0][3] === moreSpecialCharData.table1[0].slash &&
|
|
res.table1[0][4] === moreSpecialCharData.table1[0].slashWithSpecial &&
|
|
res.table1[0][5] === moreSpecialCharData.table1[0].macvar &&
|
|
res.table1[0][6] === moreSpecialCharData.table1[0].chinese &&
|
|
res.table1[0][7] === moreSpecialCharData.table1[0].sigma &&
|
|
res.table1[0][8] === moreSpecialCharData.table1[0].at &&
|
|
res.table1[0][9] === moreSpecialCharData.table1[0].serbian &&
|
|
res.table1[0][10] === moreSpecialCharData.table1[0].dollar
|
|
)
|
|
}
|
|
},
|
|
{
|
|
title: 'Wide table with sendArr',
|
|
description: 'Should handle data with 10000 columns',
|
|
test: () => {
|
|
return adapter.request('common/sendArr', getWideData())
|
|
},
|
|
assertion: (res: any) => {
|
|
const data = getWideData()
|
|
let result = true
|
|
for (let i = 0; i <= 10; i++) {
|
|
result =
|
|
result && res.table1[0][i] === data.table1[0]['col' + (i + 1)]
|
|
}
|
|
return result
|
|
}
|
|
},
|
|
{
|
|
title: 'Wide table with sendObj',
|
|
description: 'Should handle data with 10000 columns',
|
|
test: () => {
|
|
return adapter.request('common/sendObj', getWideData())
|
|
},
|
|
assertion: (res: any) => {
|
|
const data = getWideData()
|
|
let result = true
|
|
for (let i = 0; i <= 10; i++) {
|
|
result =
|
|
result &&
|
|
res.table1[0]['COL' + (i + 1)] === data.table1[0]['col' + (i + 1)]
|
|
}
|
|
return result
|
|
}
|
|
},
|
|
{
|
|
title: 'Multiple tables',
|
|
description: 'Should handle data with 100 tables',
|
|
test: () => {
|
|
return adapter.request('common/sendArr', getTables())
|
|
},
|
|
assertion: (res: any) => {
|
|
const data = getTables()
|
|
return (
|
|
res.table1[0][0] === data.table1[0].col1 &&
|
|
res.table1[0][1] === data.table1[0].col2 &&
|
|
res.table1[0][2] === data.table1[0].col3 &&
|
|
res.table1[0][3] === data.table1[0].col4 &&
|
|
res.table50[0][0] === data.table50[0].col1 &&
|
|
res.table50[0][1] === data.table50[0].col2 &&
|
|
res.table50[0][2] === data.table50[0].col3 &&
|
|
res.table50[0][3] === data.table50[0].col4
|
|
)
|
|
}
|
|
},
|
|
{
|
|
title: 'Large dataset with sendObj',
|
|
description: 'Should handle 5mb of data',
|
|
test: () => {
|
|
return adapter.request('common/sendObj', getLargeDataset())
|
|
},
|
|
assertion: (res: any) => {
|
|
const data = getLargeDataset()
|
|
let result = true
|
|
for (let i = 0; i <= 10; i++) {
|
|
result = result && res.table1[i][0] === data.table1[i][0]
|
|
}
|
|
return result
|
|
}
|
|
},
|
|
{
|
|
title: 'Large dataset with sendArr',
|
|
description: 'Should handle 5mb of data',
|
|
test: () => {
|
|
return adapter.request('common/sendArr', getLargeDataset())
|
|
},
|
|
assertion: (res: any) => {
|
|
const data = getLargeDataset()
|
|
let result = true
|
|
for (let i = 0; i <= 10; i++) {
|
|
result =
|
|
result && res.table1[i][0] === Object.values(data.table1[i])[0]
|
|
}
|
|
return result
|
|
}
|
|
},
|
|
{
|
|
title: 'Error and _csrf tables with sendArr',
|
|
description: 'Should handle error and _csrf tables',
|
|
test: () => {
|
|
return adapter.request('common/sendArr', errorAndCsrfData)
|
|
},
|
|
assertion: (res: any) => {
|
|
return (
|
|
res.error[0][0] === errorAndCsrfData.error[0].col1 &&
|
|
res.error[0][1] === errorAndCsrfData.error[0].col2 &&
|
|
res.error[0][2] === errorAndCsrfData.error[0].col3 &&
|
|
res.error[0][3] === errorAndCsrfData.error[0].col4 &&
|
|
res._csrf[0][0] === errorAndCsrfData._csrf[0].col1 &&
|
|
res._csrf[0][1] === errorAndCsrfData._csrf[0].col2 &&
|
|
res._csrf[0][2] === errorAndCsrfData._csrf[0].col3 &&
|
|
res._csrf[0][3] === errorAndCsrfData._csrf[0].col4
|
|
)
|
|
}
|
|
},
|
|
{
|
|
title: 'Error and _csrf tables with sendObj',
|
|
description: 'Should handle error and _csrf tables',
|
|
test: () => {
|
|
return adapter.request('common/sendObj', errorAndCsrfData)
|
|
},
|
|
assertion: (res: any) => {
|
|
return (
|
|
res.error[0].COL1 === errorAndCsrfData.error[0].col1 &&
|
|
res.error[0].COL2 === errorAndCsrfData.error[0].col2 &&
|
|
res.error[0].COL3 === errorAndCsrfData.error[0].col3 &&
|
|
res.error[0].COL4 === errorAndCsrfData.error[0].col4 &&
|
|
res._csrf[0].COL1 === errorAndCsrfData._csrf[0].col1 &&
|
|
res._csrf[0].COL2 === errorAndCsrfData._csrf[0].col2 &&
|
|
res._csrf[0].COL3 === errorAndCsrfData._csrf[0].col3 &&
|
|
res._csrf[0].COL4 === errorAndCsrfData._csrf[0].col4
|
|
)
|
|
}
|
|
},
|
|
{
|
|
title: 'Request with extra attributes on JES approach',
|
|
description:
|
|
'Should complete successful request with extra attributes present in response',
|
|
test: async () => {
|
|
if (adapter.getSasjsConfig().serverType !== 'SASVIYA')
|
|
return Promise.resolve('skip')
|
|
|
|
const config = {
|
|
useComputeApi: false
|
|
}
|
|
|
|
return await adapter.request(
|
|
'common/sendArr',
|
|
stringData,
|
|
config,
|
|
undefined,
|
|
undefined,
|
|
['file', 'data']
|
|
)
|
|
},
|
|
assertion: (response: any) => {
|
|
if (response === 'skip') return true
|
|
|
|
const responseKeys: any = Object.keys(response)
|
|
return responseKeys.includes('file') && responseKeys.includes('data')
|
|
}
|
|
},
|
|
{
|
|
title: 'Special missing values',
|
|
description: 'Should support special missing values',
|
|
test: () => {
|
|
return adapter.request('common/sendObj', testTableWithSpecialNumeric)
|
|
},
|
|
assertion: (res: any) => {
|
|
let assertionRes = true
|
|
|
|
// We receive formats in response. We compare it with formats that we included in request to make sure they are equal
|
|
const resVars = res[`$${testTable}`].vars
|
|
|
|
Object.keys(resVars).forEach((key: any, i: number) => {
|
|
let formatValue =
|
|
testTableWithSpecialNumeric[`$${testTable}`].formats[
|
|
key.toLowerCase()
|
|
]
|
|
// If it is char, we change it to $ to be compatible for comparsion
|
|
// If it is number, it will already be compatible to comapre (best.)
|
|
formatValue = formatValue?.includes('$') ? '$' : formatValue
|
|
|
|
if (
|
|
formatValue !== undefined &&
|
|
!resVars[key].format.includes(formatValue)
|
|
) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
|
|
// Here we will compare the response values with values we send
|
|
const resValues = res[testTable]
|
|
|
|
testTableWithSpecialNumeric[testTable].forEach(
|
|
(row: { [key: string]: any }, i: number) =>
|
|
Object.keys(row).forEach((col: string) => {
|
|
if (resValues[i][col.toUpperCase()] !== row[col]) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
)
|
|
|
|
return assertionRes
|
|
}
|
|
},
|
|
{
|
|
title: 'Special missing values (ONE ROW)',
|
|
description:
|
|
'Should support special missing values, when one row is send',
|
|
test: () => {
|
|
return adapter.request(
|
|
'common/sendObj',
|
|
testTableWithSpecialNumericOneRow
|
|
)
|
|
},
|
|
assertion: (res: any) => {
|
|
let assertionRes = true
|
|
|
|
// We receive formats in response. We compare it with formats that we included in request to make sure they are equal
|
|
const resVars = res[`$${testTable}`].vars
|
|
|
|
Object.keys(resVars).forEach((key: any, i: number) => {
|
|
let formatValue =
|
|
testTableWithSpecialNumeric[`$${testTable}`].formats[
|
|
key.toLowerCase()
|
|
]
|
|
// If it is char, we change it to $ to be compatible for comparsion
|
|
// If it is number, it will already be compatible to comapre (best.)
|
|
formatValue = formatValue?.includes('$') ? '$' : formatValue
|
|
|
|
if (
|
|
formatValue !== undefined &&
|
|
!resVars[key].format.includes(formatValue)
|
|
) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
|
|
// Here we will compare the response values with values we send
|
|
const resValues = res[testTable]
|
|
|
|
testTableWithSpecialNumericOneRow[testTable].forEach(
|
|
(row: { [key: string]: any }, i: number) =>
|
|
Object.keys(row).forEach((col: string) => {
|
|
if (resValues[i][col.toUpperCase()] !== row[col]) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
)
|
|
|
|
return assertionRes
|
|
}
|
|
},
|
|
{
|
|
title: 'Special missing values (LOWERCASE)',
|
|
description:
|
|
'Should support special missing values, when LOWERCASE value is sent',
|
|
test: () => {
|
|
return adapter.request(
|
|
'common/sendObj',
|
|
testTableWithSpecialNumericLowercase
|
|
)
|
|
},
|
|
assertion: (res: any) => {
|
|
let assertionRes = true
|
|
|
|
// We receive formats in response. We compare it with formats that we included in request to make sure they are equal
|
|
const resVars = res[`$${testTable}`].vars
|
|
|
|
Object.keys(resVars).forEach((key: any, i: number) => {
|
|
let formatValue =
|
|
testTableWithSpecialNumericLowercase[`$${testTable}`].formats[
|
|
key.toLowerCase()
|
|
]
|
|
// If it is a char, we change it to $ to be compatible for comparison
|
|
// If it is a number, it will already be compatible to compare (best.)
|
|
formatValue = formatValue?.includes('$') ? '$' : formatValue
|
|
|
|
if (
|
|
formatValue !== undefined &&
|
|
!resVars[key].format.includes(formatValue)
|
|
) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
|
|
// Here we will compare the response values with values we send
|
|
const resValues = res[testTable]
|
|
|
|
testTableWithSpecialNumericLowercase[testTable].forEach(
|
|
(row: { [key: string]: any }, i: number) =>
|
|
Object.keys(row).forEach((col: string) => {
|
|
if (col === 'specialnumeric') {
|
|
if (
|
|
resValues[i][col.toUpperCase()] !== row[col].toUpperCase()
|
|
) {
|
|
assertionRes = false
|
|
}
|
|
} else {
|
|
if (resValues[i][col.toUpperCase()] !== row[col]) {
|
|
assertionRes = false
|
|
}
|
|
}
|
|
})
|
|
)
|
|
|
|
return assertionRes
|
|
}
|
|
},
|
|
{
|
|
title: 'Special missing values (ONE ROW) useComputeApi undefined',
|
|
description:
|
|
'Should support special missing values, when one row is send (On VIYA Web Approach)',
|
|
test: () => {
|
|
return adapter.request(
|
|
'common/sendObj',
|
|
testTableWithSpecialNumericOneRow,
|
|
{ useComputeApi: undefined }
|
|
)
|
|
},
|
|
assertion: (res: any) => {
|
|
let assertionRes = true
|
|
|
|
// We receive formats in response. We compare it with formats that we included in request to make sure they are equal
|
|
const resVars = res[`$${testTable}`].vars
|
|
|
|
Object.keys(resVars).forEach((key: any, i: number) => {
|
|
let formatValue =
|
|
testTableWithSpecialNumeric[`$${testTable}`].formats[
|
|
key.toLowerCase()
|
|
]
|
|
// If it is char, we change it to $ to be compatible for comparsion
|
|
// If it is number, it will already be compatible to comapre (best.)
|
|
formatValue = formatValue?.includes('$') ? '$' : formatValue
|
|
|
|
if (
|
|
formatValue !== undefined &&
|
|
!resVars[key].format.includes(formatValue)
|
|
) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
|
|
// Here we will compare the response values with values we send
|
|
const resValues = res[testTable]
|
|
|
|
testTableWithSpecialNumericOneRow[testTable].forEach(
|
|
(row: { [key: string]: any }, i: number) =>
|
|
Object.keys(row).forEach((col: string) => {
|
|
if (resValues[i][col.toUpperCase()] !== row[col]) {
|
|
assertionRes = false
|
|
}
|
|
})
|
|
)
|
|
|
|
return assertionRes
|
|
}
|
|
}
|
|
]
|
|
})
|