1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-16 16:40:06 +00:00

fix(file-upload-form): fixed form data for node env

This commit is contained in:
Yury Shkoda
2023-07-06 15:49:24 +03:00
parent 22edcb0a8e
commit 0d9ba36de8
7 changed files with 113 additions and 41 deletions

View File

@@ -26,12 +26,12 @@ export const generateFileUploadForm = (
) )
} }
if (typeof FormData === 'undefined' && formData instanceof NodeFormData) { if (formData instanceof NodeFormData) {
formData.append(name, csv, { formData.append(name, csv, {
filename: `${name}.csv`, filename: `${name}.csv`,
contentType: 'application/csv' contentType: 'application/csv'
}) })
} else { } else if (formData instanceof FormData) {
const file = new Blob([csv], { const file = new Blob([csv], {
type: 'application/csv' type: 'application/csv'
}) })

View File

@@ -1,4 +1,6 @@
import { generateFileUploadForm } from '../generateFileUploadForm' import { generateFileUploadForm } from '../generateFileUploadForm'
import * as NodeFormData from 'form-data'
import { convertToCSV } from '../../utils/convertToCsv'
describe('generateFileUploadForm', () => { describe('generateFileUploadForm', () => {
beforeAll(() => { beforeAll(() => {
@@ -11,44 +13,89 @@ describe('generateFileUploadForm', () => {
;(global as any).Blob = BlobMock ;(global as any).Blob = BlobMock
}) })
it('should generate file upload form from data', () => { describe('browser', () => {
const formData = new FormData() it('should generate file upload form from data', () => {
const testTable = 'sometable' const formData = new FormData()
const testTableWithNullVars: { [key: string]: any } = { const testTable = 'sometable'
[testTable]: [ const testTableWithNullVars: { [key: string]: any } = {
{ var1: 'string', var2: 232, nullvar: 'A' }, [testTable]: [
{ var1: 'string', var2: 232, nullvar: 'B' }, { var1: 'string', var2: 232, nullvar: 'A' },
{ var1: 'string', var2: 232, nullvar: '_' }, { var1: 'string', var2: 232, nullvar: 'B' },
{ var1: 'string', var2: 232, nullvar: 0 }, { var1: 'string', var2: 232, nullvar: '_' },
{ var1: 'string', var2: 232, nullvar: 'z' }, { var1: 'string', var2: 232, nullvar: 0 },
{ var1: 'string', var2: 232, nullvar: null } { var1: 'string', var2: 232, nullvar: 'z' },
], { var1: 'string', var2: 232, nullvar: null }
[`$${testTable}`]: { formats: { var1: '$char12.', nullvar: 'best.' } } ],
} [`$${testTable}`]: { formats: { var1: '$char12.', nullvar: 'best.' } }
const tableName = Object.keys(testTableWithNullVars).filter((key: string) => }
Array.isArray(testTableWithNullVars[key]) const tableName = Object.keys(testTableWithNullVars).filter(
)[0] (key: string) => Array.isArray(testTableWithNullVars[key])
)[0]
jest.spyOn(formData, 'append').mockImplementation(() => {}) jest.spyOn(formData, 'append').mockImplementation(() => {})
generateFileUploadForm(formData, testTableWithNullVars) generateFileUploadForm(formData, testTableWithNullVars)
expect(formData.append).toHaveBeenCalledOnce() expect(formData.append).toHaveBeenCalledOnce()
expect(formData.append).toHaveBeenCalledWith( expect(formData.append).toHaveBeenCalledWith(
tableName, tableName,
{}, {},
`${tableName}.csv` `${tableName}.csv`
) )
})
it('should throw an error if too large string was provided', () => {
const formData = new FormData()
const data = { testTable: [{ var1: 'z'.repeat(32765 + 1) }] }
expect(() => generateFileUploadForm(formData, data)).toThrow(
new Error(
'The max length of a string value in SASjs is 32765 characters.'
)
)
})
}) })
it('should throw an error if too large string was provided', () => { describe('node', () => {
const formData = new FormData() it('should generate file upload form from data', () => {
const data = { testTable: [{ var1: 'z'.repeat(32765 + 1) }] } const formData = new NodeFormData()
const testTable = 'sometable'
const testTableWithNullVars: { [key: string]: any } = {
[testTable]: [
{ var1: 'string', var2: 232, nullvar: 'A' },
{ var1: 'string', var2: 232, nullvar: 'B' },
{ var1: 'string', var2: 232, nullvar: '_' },
{ var1: 'string', var2: 232, nullvar: 0 },
{ var1: 'string', var2: 232, nullvar: 'z' },
{ var1: 'string', var2: 232, nullvar: null }
],
[`$${testTable}`]: { formats: { var1: '$char12.', nullvar: 'best.' } }
}
const tableName = Object.keys(testTableWithNullVars).filter(
(key: string) => Array.isArray(testTableWithNullVars[key])
)[0]
const csv = convertToCSV(testTableWithNullVars, tableName)
expect(() => generateFileUploadForm(formData, data)).toThrow( jest.spyOn(formData, 'append').mockImplementation(() => {})
new Error(
'The max length of a string value in SASjs is 32765 characters.' generateFileUploadForm(formData, testTableWithNullVars)
expect(formData.append).toHaveBeenCalledOnce()
expect(formData.append).toHaveBeenCalledWith(tableName, csv, {
contentType: 'application/csv',
filename: `${tableName}.csv`
})
})
it('should throw an error if too large string was provided', () => {
const formData = new NodeFormData()
const data = { testTable: [{ var1: 'z'.repeat(32765 + 1) }] }
expect(() => generateFileUploadForm(formData, data)).toThrow(
new Error(
'The max length of a string value in SASjs is 32765 characters.'
)
) )
) })
}) })
}) })

View File

@@ -10,8 +10,8 @@ import {
LoginRequiredError LoginRequiredError
} from '../types/errors' } from '../types/errors'
import { generateFileUploadForm } from '../file/generateFileUploadForm' import { generateFileUploadForm } from '../file/generateFileUploadForm'
import { RequestClient } from '../request/RequestClient' import { RequestClient } from '../request/RequestClient'
import { getFormData } from '../utils'
import { import {
isRelativePath, isRelativePath,
@@ -53,8 +53,7 @@ export class SasjsJobExecutor extends BaseJobExecutor {
* Use the available form data object (FormData in Browser, NodeFormData in * Use the available form data object (FormData in Browser, NodeFormData in
* Node) * Node)
*/ */
let formData = let formData = getFormData()
typeof FormData === 'undefined' ? new NodeFormData() : new FormData()
if (data) { if (data) {
// file upload approach // file upload approach

View File

@@ -16,10 +16,11 @@ import { SASViyaApiClient } from '../SASViyaApiClient'
import { import {
isRelativePath, isRelativePath,
parseSasViyaDebugResponse, parseSasViyaDebugResponse,
appendExtraResponseAttributes appendExtraResponseAttributes,
parseWeboutResponse,
getFormData
} from '../utils' } from '../utils'
import { BaseJobExecutor } from './JobExecutor' import { BaseJobExecutor } from './JobExecutor'
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
export interface WaitingRequstPromise { export interface WaitingRequstPromise {
promise: Promise<any> | null promise: Promise<any> | null
@@ -112,8 +113,7 @@ export class WebJobExecutor extends BaseJobExecutor {
* Use the available form data object (FormData in Browser, NodeFormData in * Use the available form data object (FormData in Browser, NodeFormData in
* Node) * Node)
*/ */
let formData = let formData = getFormData()
typeof FormData === 'undefined' ? new NodeFormData() : new FormData()
if (data) { if (data) {
const stringifiedData = JSON.stringify(data) const stringifiedData = JSON.stringify(data)

5
src/utils/getFormData.ts Normal file
View File

@@ -0,0 +1,5 @@
import { isNode } from './'
import * as NodeFormData from 'form-data'
export const getFormData = () =>
isNode() ? new NodeFormData() : new FormData()

View File

@@ -20,3 +20,4 @@ export * from './parseWeboutResponse'
export * from './serialize' export * from './serialize'
export * from './splitChunks' export * from './splitChunks'
export * from './validateInput' export * from './validateInput'
export * from './getFormData'

View File

@@ -0,0 +1,20 @@
import { getFormData } from '..'
import * as isNodeModule from '../isNode'
import * as NodeFormData from 'form-data'
describe('getFormData', () => {
it('should return NodeFormData if environment is Node', () => {
jest.spyOn(isNodeModule, 'isNode').mockImplementation(() => true)
expect(getFormData() instanceof NodeFormData).toEqual(true)
})
it('should return FormData if environment is not Node', () => {
const formDataMock = () => {}
;(global as any).FormData = formDataMock
jest.spyOn(isNodeModule, 'isNode').mockImplementation(() => false)
expect(getFormData() instanceof FormData).toEqual(true)
})
})