feat: implement getFileById method

This commit is contained in:
StevanFreeborn
2023-02-06 21:28:11 -06:00
parent fac2367052
commit 04e1ebdf8d
8 changed files with 718 additions and 101 deletions
+37
View File
@@ -1,8 +1,10 @@
import { type AxiosResponse } from 'axios';
import { FieldType } from '../enums/FieldType'; import { FieldType } from '../enums/FieldType';
import { App } from './App'; import { App } from './App';
import { CollectionResponse } from './CollectionResponse'; import { CollectionResponse } from './CollectionResponse';
import { CreatedWithIdResponse } from './CreatedWithIdResponse'; import { CreatedWithIdResponse } from './CreatedWithIdResponse';
import { Field } from './Field'; import { Field } from './Field';
import { File } from './File';
import { FileInfo } from './FileInfo'; import { FileInfo } from './FileInfo';
import { FormulaField } from './FormulaField'; import { FormulaField } from './FormulaField';
import { GetPagedAppsResponse } from './GetPagedAppsResponse'; import { GetPagedAppsResponse } from './GetPagedAppsResponse';
@@ -221,6 +223,41 @@ export class ApiResponse<T> {
); );
} }
public asFileType(response: AxiosResponse): ApiResponse<File> {
const apiResponse = this as ApiResponse<any>;
let fileName = response.headers['content-disposition']
.split(';')[1]
.split('=')[1];
fileName = fileName.substring(1, fileName.length - 1);
const contentType =
response.headers['content-type'] ??
response.headers['Content-Type'] ??
null;
let contentLength =
response.headers['content-length'] ??
response.headers['Content-Length'] ??
0;
contentLength = parseInt(contentLength);
const file = new File(
apiResponse.data,
fileName,
contentType,
contentLength
);
return new ApiResponse<File>(
apiResponse.statusCode,
apiResponse.message,
file
);
}
/** /**
* @method asFileCollectionType - Converts the field item to the appropriate field object based upon the field item's type. * @method asFileCollectionType - Converts the field item to the appropriate field object based upon the field item's type.
* @param fieldItem - The field item to convert. * @param fieldItem - The field item to convert.
+46
View File
@@ -0,0 +1,46 @@
import { type Readable } from 'stream';
/**
* @class File - Represents a file retrieved from Onspring.
*/
export class File {
/**
* @property {Readable} stream - The stream of the file.
*/
public stream: Readable;
/**
* @property {string} fileName - The name of the file.
*/
public fileName: string;
/**
* @property {string} contentType - The content type of the file.
*/
public contentType: string;
/**
* @property {number} contentLength - The content length of the file.
*/
public contentLength: number;
/**
* @constructor - Creates a new instance of File.
* @param {Readable} stream - The stream of the file.
* @param {string} fileName - The name of the file.
* @param {string} contentType - The content type of the file.
* @param {number} contentLength - The content length of the file.
* @returns {File} - A new instance of File.
*/
constructor(
stream: Readable,
fileName: string,
contentType: string,
contentLength: number
) {
this.stream = stream;
this.fileName = fileName;
this.contentType = contentType;
this.contentLength = contentLength;
}
}
+34 -2
View File
@@ -1,10 +1,10 @@
import axios from 'axios'; import axios from 'axios';
import { type AxiosInstance, type AxiosRequestConfig } from 'axios'; import { PagingRequest } from './PagingRequest';
import { ArgumentValidator } from './ArgumentValidator'; import { ArgumentValidator } from './ArgumentValidator';
import { EndpointFactory } from './EndpointFactory'; import { EndpointFactory } from './EndpointFactory';
import { ApiResponseFactory } from './ApiResponseFactory'; import { ApiResponseFactory } from './ApiResponseFactory';
import { type AxiosInstance, type AxiosRequestConfig } from 'axios';
import { type ApiResponse } from './ApiResponse'; import { type ApiResponse } from './ApiResponse';
import { PagingRequest } from './PagingRequest';
import { type GetPagedAppsResponse } from './GetPagedAppsResponse'; import { type GetPagedAppsResponse } from './GetPagedAppsResponse';
import { type App } from './App'; import { type App } from './App';
import { type CollectionResponse } from './CollectionResponse'; import { type CollectionResponse } from './CollectionResponse';
@@ -13,6 +13,7 @@ import { type GetPagedFieldsResponse } from './GetPagedFieldsResponse';
import { type SaveFileRequest } from './SaveFileRequest'; import { type SaveFileRequest } from './SaveFileRequest';
import { type CreatedWithIdResponse } from './CreatedWithIdResponse'; import { type CreatedWithIdResponse } from './CreatedWithIdResponse';
import { type FileInfo } from './FileInfo'; import { type FileInfo } from './FileInfo';
import { type File } from './File';
/** /**
* @class OnspringClient - A client that can communicate with the Onspring API. * @class OnspringClient - A client that can communicate with the Onspring API.
@@ -200,6 +201,37 @@ export class OnspringClient {
return apiResponse.asFileInfoType(); return apiResponse.asFileInfoType();
} }
/**
* @method getFileById - Gets a file by its id.
* @param {number} recordId - The id of the record that the file is attached to.
* @param {number} fieldId - The id of the field that the file is attached to.
* @param {number} fileId - The id of the file to get.
* @returns {Promise<ApiResponse<File>>} - A promise that resolves to an ApiResponse of type File.
*/
public async getFileById(
recordId: number,
fieldId: number,
fileId: number
): Promise<ApiResponse<File>> {
const endpoint = EndpointFactory.getFileByIdEndpoint(
recordId,
fieldId,
fileId
);
const response = await this._client.get(endpoint, {
responseType: 'stream',
});
const apiResponse = ApiResponseFactory.getApiResponse<any>(response);
if (apiResponse.isSuccessful === false) {
return apiResponse;
}
return apiResponse.asFileType(response);
}
/** /**
* @method saveFile - Saves a file to a record in Onspring. * @method saveFile - Saves a file to a record in Onspring.
* @param {SaveFileRequest} request - The request that will be used to save the file. * @param {SaveFileRequest} request - The request that will be used to save the file.
+344 -99
View File
@@ -14,6 +14,10 @@ import { ListValue } from '../src/models/ListValue';
import { ReferenceField } from '../src/models/ReferenceField'; import { ReferenceField } from '../src/models/ReferenceField';
import { Multiplicity } from '../src/enums/Multiplicity'; import { Multiplicity } from '../src/enums/Multiplicity';
import { ListField } from '../src/models/ListField'; import { ListField } from '../src/models/ListField';
import { File } from '../src/models/File';
import fs from 'fs';
import { type AxiosResponse } from 'axios';
import path from 'path';
describe('ApiResponse', function () { describe('ApiResponse', function () {
it('should be defined', function () { it('should be defined', function () {
@@ -122,13 +126,15 @@ describe('ApiResponse', function () {
expect(appsPagedResponse).to.be.instanceOf(ApiResponse); expect(appsPagedResponse).to.be.instanceOf(ApiResponse);
expect(appsPagedResponse.data).to.be.instanceOf(GetPagedAppsResponse); expect(appsPagedResponse.data).to.be.instanceOf(GetPagedAppsResponse);
expect(appsPagedResponse.data).to.not.be.null; expect(appsPagedResponse.data).to.not.be.null;
expect(appsPagedResponse.data).to.have.property('totalPages', 1);
expect(appsPagedResponse.data).to.have.property('totalRecords', 2);
expect(appsPagedResponse.data).to.have.property('pageNumber', 1);
expect(appsPagedResponse.data).to.have.property('pageSize', 2);
expect(appsPagedResponse.data)
.to.have.property('items')
.that.is.an.instanceOf(Array)
.and.has.lengthOf(2);
if (appsPagedResponse.data != null) { if (appsPagedResponse.data != null) {
expect(appsPagedResponse.data.totalPages).to.equal(1);
expect(appsPagedResponse.data.totalRecords).to.equal(2);
expect(appsPagedResponse.data.pageNumber).to.equal(1);
expect(appsPagedResponse.data.pageSize).to.equal(2);
expect(appsPagedResponse.data.items).to.be.instanceOf(Array);
expect(appsPagedResponse.data.items).to.have.lengthOf(2);
expect(appsPagedResponse.data.items[0]).to.be.instanceOf(App); expect(appsPagedResponse.data.items[0]).to.be.instanceOf(App);
expect(appsPagedResponse.data.items[1]).to.be.instanceOf(App); expect(appsPagedResponse.data.items[1]).to.be.instanceOf(App);
} }
@@ -149,13 +155,21 @@ describe('ApiResponse', function () {
expect(appsPagedResponse).to.be.instanceOf(ApiResponse); expect(appsPagedResponse).to.be.instanceOf(ApiResponse);
expect(appsPagedResponse.data).to.be.instanceOf(GetPagedAppsResponse); expect(appsPagedResponse.data).to.be.instanceOf(GetPagedAppsResponse);
expect(appsPagedResponse.data).to.not.be.null; expect(appsPagedResponse.data).to.not.be.null;
expect(appsPagedResponse.data).to.have.property('totalPages', 0);
expect(appsPagedResponse.data).to.have.property('totalRecords', 0);
expect(appsPagedResponse.data).to.have.property('pageNumber', 0);
expect(appsPagedResponse.data).to.have.property('pageSize', 0);
expect(appsPagedResponse.data)
.to.have.property('items')
.that.is.an.instanceOf(Array)
.and.has.lengthOf(0);
if (appsPagedResponse.data != null) { if (appsPagedResponse.data != null) {
expect(appsPagedResponse.data.totalPages).to.equal(0); appsPagedResponse.data.items.forEach((item) => {
expect(appsPagedResponse.data.totalRecords).to.equal(0); expect(item).to.be.instanceOf(App);
expect(appsPagedResponse.data.pageNumber).to.equal(0); expect(item).to.have.property('id');
expect(appsPagedResponse.data.pageSize).to.equal(0); expect(item).to.have.property('name');
expect(appsPagedResponse.data.items).to.be.instanceOf(Array); expect(item).to.have.property('href');
expect(appsPagedResponse.data.items).to.have.lengthOf(0); });
} }
}); });
}); });
@@ -182,13 +196,12 @@ describe('ApiResponse', function () {
expect(appResponse).to.be.instanceOf(ApiResponse); expect(appResponse).to.be.instanceOf(ApiResponse);
expect(appResponse.data).to.be.instanceOf(App); expect(appResponse.data).to.be.instanceOf(App);
expect(appResponse.data).to.not.be.null; expect(appResponse.data).to.not.be.null;
if (appResponse.data != null) { expect(appResponse.data).to.have.property('id', 1);
expect(appResponse.data.id).to.equal(1); expect(appResponse.data).to.have.property('name', 'Test App');
expect(appResponse.data.name).to.equal('Test App'); expect(appResponse.data).to.have.property(
expect(appResponse.data.href).to.equal( 'href',
'https://api.onspring.dev/apps/id/1' 'https://api.onspring.dev/apps/id/1'
); );
}
}); });
}); });
@@ -228,12 +241,12 @@ describe('ApiResponse', function () {
CollectionResponse<App> CollectionResponse<App>
); );
expect(appCollectionResponse.data).to.not.be.null; expect(appCollectionResponse.data).to.not.be.null;
expect(appCollectionResponse.data).to.have.property('count', 2);
expect(appCollectionResponse.data)
.to.have.property('items')
.that.is.instanceOf(Array)
.and.has.lengthOf(2);
if (appCollectionResponse.data != null) { if (appCollectionResponse.data != null) {
expect(appCollectionResponse.data).to.have.property('count');
expect(appCollectionResponse.data).to.have.property('items');
expect(appCollectionResponse.data.count).to.equal(2);
expect(appCollectionResponse.data.items).to.be.instanceOf(Array);
expect(appCollectionResponse.data.items).to.have.lengthOf(2);
appCollectionResponse.data.items.forEach((item) => { appCollectionResponse.data.items.forEach((item) => {
expect(item).to.be.instanceOf(App); expect(item).to.be.instanceOf(App);
expect(item).to.have.property('id'); expect(item).to.have.property('id');
@@ -270,15 +283,16 @@ describe('ApiResponse', function () {
expect(fieldResponse).to.be.instanceOf(ApiResponse); expect(fieldResponse).to.be.instanceOf(ApiResponse);
expect(fieldResponse.data).to.be.instanceOf(Field); expect(fieldResponse.data).to.be.instanceOf(Field);
expect(fieldResponse.data).to.not.be.null; expect(fieldResponse.data).to.not.be.null;
if (fieldResponse.data != null) { expect(fieldResponse.data).to.have.property('id', 1);
expect(fieldResponse.data.id).to.equal(1); expect(fieldResponse.data).to.have.property('appId', 1);
expect(fieldResponse.data.appId).to.equal(1); expect(fieldResponse.data).to.have.property('name', 'Text Field');
expect(fieldResponse.data.name).to.equal('Text Field'); expect(fieldResponse.data).to.have.property('type', FieldType.Text);
expect(fieldResponse.data.type).to.equal(FieldType.Text); expect(fieldResponse.data).to.have.property(
expect(fieldResponse.data.status).to.equal(FieldStatus.Enabled); 'status',
expect(fieldResponse.data.isRequired).to.equal(false); FieldStatus.Enabled
expect(fieldResponse.data.isUnique).to.equal(false); );
} expect(fieldResponse.data).to.have.property('isRequired', false);
expect(fieldResponse.data).to.have.property('isUnique', false);
}); });
it('should return an ApiResponse<Field> when data contains a list field', function () { it('should return an ApiResponse<Field> when data contains a list field', function () {
@@ -324,19 +338,32 @@ describe('ApiResponse', function () {
expect(fieldResponse.data).to.be.instanceOf(Field); expect(fieldResponse.data).to.be.instanceOf(Field);
expect(fieldResponse.data).to.be.instanceOf(ListField); expect(fieldResponse.data).to.be.instanceOf(ListField);
expect(fieldResponse.data).to.not.be.null; expect(fieldResponse.data).to.not.be.null;
expect(fieldResponse.data).to.be.instanceOf(ListField);
expect(fieldResponse.data).to.have.property('id', 11929);
expect(fieldResponse.data).to.have.property('appId', 373);
expect(fieldResponse.data).to.have.property(
'name',
'single-select list field'
);
expect(fieldResponse.data).to.have.property('type', FieldType.List);
expect(fieldResponse.data).to.have.property(
'status',
FieldStatus.Enabled
);
expect(fieldResponse.data).to.have.property('isRequired', false);
expect(fieldResponse.data).to.have.property('isUnique', false);
expect(fieldResponse.data).to.have.property(
'multiplicity',
Multiplicity.SingleSelect
);
expect(fieldResponse.data).to.have.property('listId', 1581);
expect(fieldResponse.data)
.to.have.property('values')
.that.is.instanceOf(Array)
.and.has.lengthOf(3);
if (fieldResponse.data != null) { if (fieldResponse.data != null) {
const listField = fieldResponse.data as ListField; const listField = fieldResponse.data as ListField;
expect(listField.id).to.equal(11929);
expect(listField.appId).to.equal(373);
expect(listField.name).to.equal('single-select list field');
expect(listField.type).to.equal(FieldType.List);
expect(listField.status).to.equal(FieldStatus.Enabled);
expect(listField.isRequired).to.equal(false);
expect(listField.isUnique).to.equal(false);
expect(listField.multiplicity).to.equal(Multiplicity.SingleSelect);
expect(listField.listId).to.equal(1581);
expect(listField.values).to.be.instanceOf(Array);
expect(listField.values).to.have.lengthOf(3);
listField.values.forEach((value) => { listField.values.forEach((value) => {
expect(value).to.be.instanceOf(ListValue); expect(value).to.be.instanceOf(ListValue);
expect(value).to.have.property('id'); expect(value).to.have.property('id');
@@ -368,18 +395,22 @@ describe('ApiResponse', function () {
expect(fieldResponse.data).to.be.instanceOf(Field); expect(fieldResponse.data).to.be.instanceOf(Field);
expect(fieldResponse.data).to.be.instanceOf(ReferenceField); expect(fieldResponse.data).to.be.instanceOf(ReferenceField);
expect(fieldResponse.data).to.not.be.null; expect(fieldResponse.data).to.not.be.null;
if (fieldResponse.data != null) { expect(fieldResponse.data).to.be.instanceOf(ReferenceField);
const referenceField = fieldResponse.data as ReferenceField; expect(fieldResponse.data).to.have.property('id', 11866);
expect(referenceField.id).to.equal(11866); expect(fieldResponse.data).to.have.property('appId', 373);
expect(referenceField.appId).to.equal(373); expect(fieldResponse.data).to.have.property('name', 'Created By');
expect(referenceField.name).to.equal('Created By'); expect(fieldResponse.data).to.have.property('type', FieldType.Reference);
expect(referenceField.type).to.equal(FieldType.Reference); expect(fieldResponse.data).to.have.property(
expect(referenceField.status).to.equal(FieldStatus.Enabled); 'status',
expect(referenceField.isRequired).to.equal(false); FieldStatus.Enabled
expect(referenceField.isUnique).to.equal(false); );
expect(referenceField.multiplicity).to.equal(Multiplicity.SingleSelect); expect(fieldResponse.data).to.have.property('isRequired', false);
expect(referenceField.referencedAppId).to.equal(2); expect(fieldResponse.data).to.have.property('isUnique', false);
} expect(fieldResponse.data).to.have.property(
'multiplicity',
Multiplicity.SingleSelect
);
expect(fieldResponse.data).to.have.property('referencedAppId', 2);
}); });
it('should return an ApiResponse<Field> when data contains a list formula field', function () { it('should return an ApiResponse<Field> when data contains a list formula field', function () {
@@ -417,18 +448,28 @@ describe('ApiResponse', function () {
expect(fieldResponse.data).to.be.instanceOf(Field); expect(fieldResponse.data).to.be.instanceOf(Field);
expect(fieldResponse.data).to.be.instanceOf(FormulaField); expect(fieldResponse.data).to.be.instanceOf(FormulaField);
expect(fieldResponse.data).to.not.be.null; expect(fieldResponse.data).to.not.be.null;
expect(fieldResponse.data).to.be.instanceOf(FormulaField);
expect(fieldResponse.data).to.have.property('id', 12680);
expect(fieldResponse.data).to.have.property('appId', 373);
expect(fieldResponse.data).to.have.property('name', 'List Formula Field');
expect(fieldResponse.data).to.have.property('type', FieldType.Formula);
expect(fieldResponse.data).to.have.property(
'status',
FieldStatus.Enabled
);
expect(fieldResponse.data).to.have.property('isRequired', false);
expect(fieldResponse.data).to.have.property('isUnique', false);
expect(fieldResponse.data).to.have.property(
'outputType',
FormulaOutputType.ListValue
);
expect(fieldResponse.data)
.to.have.property('values')
.that.is.instanceOf(Array)
.and.has.lengthOf(2);
if (fieldResponse.data != null) { if (fieldResponse.data != null) {
const formulaField = fieldResponse.data as FormulaField; const formulaField = fieldResponse.data as FormulaField;
expect(formulaField.id).to.equal(12680);
expect(formulaField.appId).to.equal(373);
expect(formulaField.name).to.equal('List Formula Field');
expect(formulaField.type).to.equal(FieldType.Formula);
expect(formulaField.status).to.equal(FieldStatus.Enabled);
expect(formulaField.isRequired).to.equal(false);
expect(formulaField.isUnique).to.equal(false);
expect(formulaField.outputType).to.equal(FormulaOutputType.ListValue);
expect(formulaField.values).to.be.instanceOf(Array);
expect(formulaField.values).to.have.lengthOf(2);
formulaField.values.forEach((value) => { formulaField.values.forEach((value) => {
expect(value).to.be.instanceOf(ListValue); expect(value).to.be.instanceOf(ListValue);
expect(value).to.have.property('id'); expect(value).to.have.property('id');
@@ -460,19 +501,25 @@ describe('ApiResponse', function () {
expect(fieldResponse.data).to.be.instanceOf(Field); expect(fieldResponse.data).to.be.instanceOf(Field);
expect(fieldResponse.data).to.be.instanceOf(FormulaField); expect(fieldResponse.data).to.be.instanceOf(FormulaField);
expect(fieldResponse.data).to.not.be.null; expect(fieldResponse.data).to.not.be.null;
if (fieldResponse.data != null) { expect(fieldResponse.data).to.be.instanceOf(FormulaField);
const formulaField = fieldResponse.data as FormulaField; expect(fieldResponse.data).to.have.property('id', 12060);
expect(formulaField.id).to.equal(12060); expect(fieldResponse.data).to.have.property('appId', 373);
expect(formulaField.appId).to.equal(373); expect(fieldResponse.data).to.have.property('name', 'GetWeekOfYear');
expect(formulaField.name).to.equal('GetWeekOfYear'); expect(fieldResponse.data).to.have.property('type', FieldType.Formula);
expect(formulaField.type).to.equal(FieldType.Formula); expect(fieldResponse.data).to.have.property(
expect(formulaField.status).to.equal(FieldStatus.Enabled); 'status',
expect(formulaField.isRequired).to.equal(false); FieldStatus.Enabled
expect(formulaField.isUnique).to.equal(false); );
expect(formulaField.outputType).to.equal(FormulaOutputType.Text); expect(fieldResponse.data).to.have.property('isRequired', false);
expect(formulaField.values).to.be.instanceOf(Array); expect(fieldResponse.data).to.have.property('isUnique', false);
expect(formulaField.values).to.have.lengthOf(0); expect(fieldResponse.data).to.have.property(
} 'outputType',
FormulaOutputType.Text
);
expect(fieldResponse.data)
.to.have.property('values')
.that.is.instanceOf(Array)
.and.has.lengthOf(0);
}); });
}); });
@@ -520,9 +567,13 @@ describe('ApiResponse', function () {
CollectionResponse<Field> CollectionResponse<Field>
); );
expect(fieldCollectionResponse.data).to.not.be.null; expect(fieldCollectionResponse.data).to.not.be.null;
expect(fieldCollectionResponse.data).to.have.property('count', 2);
expect(fieldCollectionResponse.data)
.to.have.property('items')
.that.is.instanceOf(Array)
.and.has.lengthOf(2);
if (fieldCollectionResponse.data != null) { if (fieldCollectionResponse.data != null) {
expect(fieldCollectionResponse.data.items).to.be.instanceOf(Array);
expect(fieldCollectionResponse.data.items).to.have.lengthOf(2);
fieldCollectionResponse.data.items.forEach((item) => { fieldCollectionResponse.data.items.forEach((item) => {
expect(item).to.be.instanceOf(Field); expect(item).to.be.instanceOf(Field);
expect(item).to.have.property('id'); expect(item).to.have.property('id');
@@ -587,14 +638,16 @@ describe('ApiResponse', function () {
GetPagedFieldsResponse GetPagedFieldsResponse
); );
expect(getPagedFieldsResponse.data).to.not.be.null; expect(getPagedFieldsResponse.data).to.not.be.null;
expect(getPagedFieldsResponse.data).to.have.property('pageNumber', 1);
expect(getPagedFieldsResponse.data).to.have.property('pageSize', 2);
expect(getPagedFieldsResponse.data).to.have.property('totalPages', 1);
expect(getPagedFieldsResponse.data).to.have.property('totalRecords', 2);
expect(getPagedFieldsResponse.data)
.to.have.property('items')
.that.is.instanceOf(Array)
.and.has.lengthOf(2);
if (getPagedFieldsResponse.data != null) { if (getPagedFieldsResponse.data != null) {
expect(getPagedFieldsResponse.data.pageNumber).to.equal(1);
expect(getPagedFieldsResponse.data.pageSize).to.equal(2);
expect(getPagedFieldsResponse.data.totalPages).to.equal(1);
expect(getPagedFieldsResponse.data.totalRecords).to.equal(2);
expect(getPagedFieldsResponse.data.items).to.be.instanceOf(Array);
expect(getPagedFieldsResponse.data.items).to.have.lengthOf(2);
getPagedFieldsResponse.data.items.forEach((item) => { getPagedFieldsResponse.data.items.forEach((item) => {
expect(item).to.be.instanceOf(Field); expect(item).to.be.instanceOf(Field);
expect(item).to.have.property('id'); expect(item).to.have.property('id');
@@ -627,15 +680,14 @@ describe('ApiResponse', function () {
GetPagedFieldsResponse GetPagedFieldsResponse
); );
expect(getPagedFieldsResponse.data).to.not.be.null; expect(getPagedFieldsResponse.data).to.not.be.null;
expect(getPagedFieldsResponse.data).to.have.property('pageNumber', 0);
if (getPagedFieldsResponse.data != null) { expect(getPagedFieldsResponse.data).to.have.property('pageSize', 0);
expect(getPagedFieldsResponse.data.pageNumber).to.equal(0); expect(getPagedFieldsResponse.data).to.have.property('totalPages', 0);
expect(getPagedFieldsResponse.data.pageSize).to.equal(0); expect(getPagedFieldsResponse.data).to.have.property('totalRecords', 0);
expect(getPagedFieldsResponse.data.totalPages).to.equal(0); expect(getPagedFieldsResponse.data)
expect(getPagedFieldsResponse.data.totalRecords).to.equal(0); .to.have.property('items')
expect(getPagedFieldsResponse.data.items).to.be.instanceOf(Array); .that.is.instanceOf(Array)
expect(getPagedFieldsResponse.data.items).to.have.lengthOf(0); .and.has.lengthOf(0);
}
}); });
}); });
@@ -666,9 +718,202 @@ describe('ApiResponse', function () {
CreatedWithIdResponse CreatedWithIdResponse
); );
expect(createdWithIdResponse.data).to.not.be.null; expect(createdWithIdResponse.data).to.not.be.null;
if (createdWithIdResponse.data != null) { expect(createdWithIdResponse.data).to.have.property('id', 1);
expect(createdWithIdResponse.data.id).to.equal(1); });
} });
describe('asFileType', function () {
it('should be defined', function () {
expect(ApiResponse.prototype.asFileType).to.not.be.undefined;
});
it('should be a function', function () {
expect(ApiResponse.prototype.asFileType).to.be.a('function');
});
it('should have 1 parameter', function () {
expect(ApiResponse.prototype.asFileType).to.have.lengthOf(1);
});
it('should return an ApiResponse<File> when data contains an attachment file', function () {
const mockResponse = {
headers: {
'content-type': 'text/plain',
'content-disposition': 'attachment; filename="test-attachment.txt"',
'Content-Length': '13',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-attachment.txt'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse).to.be.instanceOf(ApiResponse<File>);
expect(fileResponse.data).to.be.instanceOf(File);
expect(fileResponse.data).to.not.be.null;
expect(fileResponse.data).to.have.property(
'fileName',
'test-attachment.txt'
);
expect(fileResponse.data).to.have.property('contentLength', 13);
expect(fileResponse.data).to.have.property('contentType', 'text/plain');
expect(fileResponse.data).to.have.property('stream', mockResponseData);
});
it('should return an ApiResponse<File> when data contains an image file', function () {
const mockResponse = {
headers: {
'content-type': 'image/jpeg',
'content-disposition': 'attachment; filename="test-image.jpeg"',
'Content-Length': '98897',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse).to.be.instanceOf(ApiResponse<File>);
expect(fileResponse.data).to.be.instanceOf(File);
expect(fileResponse.data).to.not.be.null;
expect(fileResponse.data).to.have.property('fileName', 'test-image.jpeg');
expect(fileResponse.data).to.have.property('contentLength', 98897);
expect(fileResponse.data).to.have.property('contentType', 'image/jpeg');
expect(fileResponse.data).to.have.property('stream', mockResponseData);
});
it('should return an ApiResponse<file> with proper contentType value when header is Content-Type', function () {
const mockResponse = {
headers: {
'Content-Type': 'image/jpeg',
'content-disposition': 'attachment; filename="test-image.jpeg"',
'Content-Length': '98897',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse.data).to.have.property('contentType', 'image/jpeg');
});
it('should return an ApiResponse<file> with proper contentType value when header is content-type', function () {
const mockResponse = {
headers: {
'content-type': 'image/jpeg',
'content-disposition': 'attachment; filename="test-image.jpeg"',
'Content-Length': '98897',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse.data).to.have.property('contentType', 'image/jpeg');
});
it('should return an ApiResponse<file> with proper contentType value when no content-type header is present', function () {
const mockResponse = {
headers: {
'content-disposition': 'attachment; filename="test-image.jpeg"',
'Content-Length': '98897',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse.data).to.have.property('contentType', null);
});
it('should return an ApiResponse<file> with proper contentLength value when header is Content-Length', function () {
const mockResponse = {
headers: {
'Content-Type': 'image/jpeg',
'content-disposition': 'attachment; filename="test-image.jpeg"',
'Content-Length': '98897',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse.data).to.have.property('contentLength', 98897);
});
it('should return an ApiResponse<file> with proper contentLength value when header is content-length', function () {
const mockResponse = {
headers: {
'Content-Type': 'image/jpeg',
'content-disposition': 'attachment; filename="test-image.jpeg"',
'content-length': '98897',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse.data).to.have.property('contentLength', 98897);
});
it('should return an ApiResponse<file> with proper contentLength value when no content-length header is present', function () {
const mockResponse = {
headers: {
'Content-Type': 'image/jpeg',
'content-disposition': 'attachment; filename="test-image.jpeg"',
} as AxiosResponse['headers'],
} as AxiosResponse;
const attachmentPath = path.join(
__dirname,
'testData',
'test-image.jpeg'
);
const mockResponseData = fs.createReadStream(attachmentPath);
const apiResponse = new ApiResponse(200, 'OK', mockResponseData);
const fileResponse = apiResponse.asFileType(mockResponse);
expect(fileResponse.data).to.have.property('contentLength', 0);
}); });
}); });
}); });
+62
View File
@@ -0,0 +1,62 @@
import { File } from '../src/models/File';
import { expect } from 'chai';
import { Readable } from 'stream';
describe('File', function () {
it('should be defined', function () {
expect(File).to.not.be.undefined;
});
it('should have a constructor', function () {
expect(File).to.have.property('constructor');
});
it('should have a stream property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1)
).to.have.property('stream');
});
it('should have a fileName property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1)
).to.have.property('fileName');
});
it('should have a contentType property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1)
).to.have.property('contentType');
});
it('should have a contentLength property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1)
).to.have.property('contentLength');
});
it('should have a constructor that sets the stream property', function () {
const stream = new Readable();
expect(
new File(stream, 'File Name', 'Content Type', 1).stream
).to.deep.equal(stream);
});
it('should have a constructor that sets the fileName property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1).fileName
).to.equal('File Name');
});
it('should have a constructor that sets the contentType property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1).contentType
).to.equal('Content Type');
});
it('should have a constructor that sets the contentLength property', function () {
expect(
new File(new Readable(), 'File Name', 'Content Type', 1).contentLength
).to.equal(1);
});
});
+194
View File
@@ -17,6 +17,9 @@ import { SaveFileRequest } from '../src/models/SaveFileRequest';
import { Readable } from 'stream'; import { Readable } from 'stream';
import { CreatedWithIdResponse } from '../src/models/CreatedWithIdResponse'; import { CreatedWithIdResponse } from '../src/models/CreatedWithIdResponse';
import { FileInfo } from '../src/models/FileInfo'; import { FileInfo } from '../src/models/FileInfo';
import { File } from '../src/models/File';
import fs from 'fs';
import path from 'path';
describe('OnspringClient', function () { describe('OnspringClient', function () {
const baseUrl = 'https://api.onspring.dev'; const baseUrl = 'https://api.onspring.dev';
@@ -1706,4 +1709,195 @@ describe('OnspringClient', function () {
expect(result.data).to.be.null; expect(result.data).to.be.null;
}); });
}); });
describe('getFileById', function () {
it('should be defined', function () {
expect(OnspringClient.prototype.getFileById).to.not.be.undefined;
});
it('should be a function', function () {
expect(OnspringClient.prototype.getFileById).to.be.a('function');
});
it('should return a promise', function () {
expect(
new OnspringClient(baseUrl, apiKey).getFileById(1, 1, 1)
).to.be.instanceOf(Promise);
});
it('should return a promise that resolves to a file when request is successful', async function () {
const client = new OnspringClient(baseUrl, apiKey);
const mockAxiosClient = axios.create({
baseURL: baseUrl,
headers: {
'x-apikey': apiKey,
'x-api-version': '2',
},
});
const filePath = path.join(__dirname, 'testData', 'test-attachment.txt');
const file = fs.createReadStream(filePath);
sinon.stub(mockAxiosClient, 'get').returns(
Promise.resolve({
status: 200,
statusText: 'OK',
data: file,
headers: {
'content-disposition': 'attachment; filename="test-attachment.txt"',
'content-length': 14,
'content-type': 'text/plain',
},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileById(1, 1, 1);
expect(result).to.be.instanceOf(ApiResponse<File>);
expect(result).to.have.property('statusCode', 200);
expect(result).to.have.property('isSuccessful', true);
expect(result).to.have.property('message', '');
expect(result.data).to.be.instanceOf(File);
expect(result.data).to.have.property('fileName', 'test-attachment.txt');
expect(result.data).to.have.property('contentLength', 14);
expect(result.data).to.have.property('contentType', 'text/plain');
expect(result.data)
.to.have.property('stream')
.that.is.instanceOf(Readable);
});
it('should return a promise that resolves to an api response when request receives a 400 response', async function () {
const client = new OnspringClient(baseUrl, apiKey);
const mockAxiosClient = axios.create({
baseURL: baseUrl,
headers: {
'x-apikey': apiKey,
'x-api-version': '2',
},
});
sinon.stub(mockAxiosClient, 'get').returns(
Promise.resolve({
status: 400,
statusText: 'Bad Request',
data: { field: ['Field requested is not a file type field.'] },
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileById(1, 1, 1);
expect(result).to.be.instanceOf(ApiResponse);
expect(result).to.have.property('statusCode', 400);
expect(result).to.have.property('isSuccessful', false);
expect(result).to.have.property(
'message',
'{"field":["Field requested is not a file type field."]}'
);
expect(result.data).to.be.null;
});
it('should return a promise that resolves to an api response when request receives a 401 response', async function () {
const client = new OnspringClient(baseUrl, apiKey);
const mockAxiosClient = axios.create({
baseURL: baseUrl,
headers: {
'x-apikey': apiKey,
'x-api-version': '2',
},
});
sinon.stub(mockAxiosClient, 'get').returns(
Promise.resolve({
status: 401,
statusText: 'Unauthorized',
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileById(1, 1, 1);
expect(result).to.be.instanceOf(ApiResponse);
expect(result).to.have.property('statusCode', 401);
expect(result).to.have.property('isSuccessful', false);
expect(result.message).to.be.undefined;
expect(result.data).to.be.null;
});
it('should return a promise that resolves to an api response when request receives a 403 response', async function () {
const client = new OnspringClient(baseUrl, apiKey);
const mockAxiosClient = axios.create({
baseURL: baseUrl,
headers: {
'x-apikey': apiKey,
'x-api-version': '2',
},
});
sinon.stub(mockAxiosClient, 'get').returns(
Promise.resolve({
status: 403,
statusText: 'Forbidden',
data: { message: 'Forbidden' },
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileById(1, 1, 1);
expect(result).to.be.instanceOf(ApiResponse);
expect(result).to.have.property('statusCode', 403);
expect(result).to.have.property('isSuccessful', false);
expect(result).to.have.property('message', 'Forbidden');
expect(result.data).to.be.null;
});
it('should return a promise that resolves to an api response when request receives a 404 response', async function () {
const client = new OnspringClient(baseUrl, apiKey);
const mockAxiosClient = axios.create({
baseURL: baseUrl,
headers: {
'x-apikey': apiKey,
'x-api-version': '2',
},
});
sinon.stub(mockAxiosClient, 'get').returns(
Promise.resolve({
status: 404,
statusText: 'Not Found',
data: { message: 'Not Found' },
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileById(1, 1, 1);
expect(result).to.be.instanceOf(ApiResponse);
expect(result).to.have.property('statusCode', 404);
expect(result).to.have.property('isSuccessful', false);
expect(result).to.have.property('message', 'Not Found');
expect(result.data).to.be.null;
});
});
}); });
+1
View File
@@ -0,0 +1 @@
This is a test attachment.
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB