feat: implemented getFileInfoById method

This commit is contained in:
StevanFreeborn
2023-02-04 15:09:13 -06:00
parent ee8594d678
commit 48de5ec3b8
9 changed files with 496 additions and 8 deletions
+2 -1
View File
@@ -16,7 +16,8 @@
"files": ["tests/**/*.spec.ts"],
"rules": {
"@typescript-eslint/no-unused-expressions": "off",
"@typescript-eslint/consistent-type-assertions": "off"
"@typescript-eslint/consistent-type-assertions": "off",
"no-new": "off"
}
}
],
+22
View File
@@ -2,6 +2,7 @@ import { App } from './App';
import { CollectionResponse } from './CollectionResponse';
import { CreatedWithIdResponse } from './CreatedWithIdResponse';
import { Field } from './Field';
import { FileInfo } from './FileInfo';
import { GetPagedAppsResponse } from './GetPagedAppsResponse';
import { GetPagedFieldsResponse } from './GetPagedFieldsResponse';
@@ -218,4 +219,25 @@ export class ApiResponse<T> {
createdWithIdResponse
);
}
asFileInfoType(): ApiResponse<FileInfo> {
const apiResponse = this as ApiResponse<any>;
const fileInfo = new FileInfo(
apiResponse.data.type,
apiResponse.data.contentType,
apiResponse.data.name,
apiResponse.data.createdDate,
apiResponse.data.modifiedDate,
apiResponse.data.owner,
apiResponse.data.notes,
apiResponse.data.fileHref
);
return new ApiResponse<FileInfo>(
apiResponse.statusCode,
apiResponse.message,
fileInfo
);
}
}
+36
View File
@@ -0,0 +1,36 @@
import { FieldType } from '../enums/FieldType';
export class FileInfo {
public type: FieldType;
public contentType: string;
public name: string;
public createdDate: Date;
public modifiedDate: Date;
public owner: string;
public notes: string;
public fileHref: string;
constructor(
type: string,
contentType: string,
name: string,
createdDate: Date,
modifiedDate: Date,
owner: string,
notes: string,
fileHref: string
) {
if (FieldType[type] === undefined) {
throw new Error(`The type '${type}' is not a valid FieldType.`);
}
this.type = FieldType[type];
this.contentType = contentType;
this.name = name;
this.createdDate = createdDate;
this.modifiedDate = modifiedDate;
this.owner = owner;
this.notes = notes;
this.fileHref = fileHref;
}
}
+30 -1
View File
@@ -12,6 +12,7 @@ import { type Field } from './Field';
import { type GetPagedFieldsResponse } from './GetPagedFieldsResponse';
import { type SaveFileRequest } from './SaveFileRequest';
import { type CreatedWithIdResponse } from './CreatedWithIdResponse';
import { type FileInfo } from './FileInfo';
/**
* @class OnspringClient - A client that can communicate with the Onspring API.
@@ -104,7 +105,8 @@ export class OnspringClient {
appIds: number[]
): Promise<ApiResponse<CollectionResponse<App>>> {
const endpoint = EndpointFactory.getAppsByIdsEndpoint();
const apiResponse = await this.post<any>(endpoint, appIds);
const uniqueIds = [...new Set(appIds)];
const apiResponse = await this.post<any>(endpoint, uniqueIds);
if (apiResponse.isSuccessful === false) {
return apiResponse;
@@ -171,6 +173,33 @@ export class OnspringClient {
return apiResponse.asGetPagedFieldsResponseType();
}
/**
* @method getFileInfoById - Gets a file's information 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 the information for.
* @returns {Promise<ApiResponse<FileInfo>>} - A promise that resolves to an ApiResponse of type FileInfo.
*/
public async getFileInfoById(
recordId: number,
fieldId: number,
fileId: number
): Promise<ApiResponse<FileInfo>> {
const endpoint = EndpointFactory.getFileInfoByIdEndpoint(
recordId,
fieldId,
fileId
);
const apiResponse = await this.get<any>(endpoint);
if (apiResponse.isSuccessful === false) {
return apiResponse;
}
return apiResponse.asFileInfoType();
}
/**
* @method saveFile - Saves a file to a record in Onspring.
* @param {SaveFileRequest} request - The request that will be used to save the file.
+190
View File
@@ -0,0 +1,190 @@
import { FileInfo } from '../src/models/FileInfo';
import { expect } from 'chai';
describe('FileInfo', function () {
it('should be defined', function () {
expect(FileInfo).to.not.be.undefined;
});
it('should have a constructor', function () {
expect(FileInfo).to.have.property('constructor');
});
it('should have 8 parameters', function () {
expect(FileInfo).to.have.lengthOf(8);
});
it('should create a new instance of FileInfo', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.be.an.instanceOf(FileInfo);
});
it('should throw an error when the type is not a valid FieldType', function () {
expect(() => {
new FileInfo(
'InvalidType',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
}).to.throw("The type 'InvalidType' is not a valid FieldType.");
});
it('should have a type property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('type');
});
it('should have a contentType property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('contentType');
});
it('should have a name property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('name');
});
it('should have a createdDate property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('createdDate');
});
it('should have a modifiedDate property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('modifiedDate');
});
it('should have a owner property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('owner');
});
it('should have a notes property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('notes');
});
it('should have a fileHref property', function () {
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
new Date(),
new Date(),
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo).to.have.property('fileHref');
});
it('should set properties to the correct values passed to the constructor', function () {
const date = new Date();
const fileInfo = new FileInfo(
'Attachment',
'application/pdf',
'FileName.pdf',
date,
date,
'File Owner',
'notes',
'https://api.onspring.dev'
);
expect(fileInfo.type).to.equal('Attachment');
expect(fileInfo.contentType).to.equal('application/pdf');
expect(fileInfo.name).to.equal('FileName.pdf');
expect(fileInfo.createdDate).to.be.deep.equal(date);
expect(fileInfo.modifiedDate).to.be.deep.equal(date);
expect(fileInfo.owner).to.equal('File Owner');
expect(fileInfo.notes).to.equal('notes');
expect(fileInfo.fileHref).to.equal('https://api.onspring.dev');
});
});
+211
View File
@@ -16,6 +16,7 @@ import { GetPagedFieldsResponse } from '../src/models/GetPagedFieldsResponse';
import { SaveFileRequest } from '../src/models/SaveFileRequest';
import { Readable } from 'stream';
import { CreatedWithIdResponse } from '../src/models/CreatedWithIdResponse';
import { FileInfo } from '../src/models/FileInfo';
describe('OnspringClient', function () {
const baseUrl = 'https://api.onspring.dev';
@@ -1495,4 +1496,214 @@ describe('OnspringClient', function () {
expect(result.data).to.be.null;
});
});
describe('getFileInfoById', function () {
it('should be defined', function () {
expect(OnspringClient.prototype.getFileInfoById).to.be.not.undefined;
});
it('should be a function', function () {
expect(OnspringClient.prototype.getFileInfoById).to.be.a('function');
});
it('should return a promise', function () {
expect(
new OnspringClient(baseUrl, apiKey).getFileInfoById(1, 1, 1)
).to.be.instanceOf(Promise);
});
it('should return a promise that resolves to an api response 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',
},
});
sinon.stub(mockAxiosClient, 'get').returns(
Promise.resolve({
status: 200,
statusText: 'OK',
data: {
type: 'Attachment',
contentType: 'string',
name: 'string',
createdDate: '2023-02-04T20:15:45.007Z',
modifiedDate: '2023-02-04T20:15:45.007Z',
owner: 'string',
notes: 'string',
fileHref: 'string',
},
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileInfoById(1, 1, 1);
expect(result).to.be.instanceOf(ApiResponse<FileInfo>);
expect(result).to.have.property('statusCode', 200);
expect(result).to.have.property('isSuccessful', true);
expect(result.message).to.be.equal('');
expect(result.data).to.be.not.null;
expect(result.data).to.be.instanceOf(FileInfo);
expect(result.data).to.have.property('type', 'Attachment');
expect(result.data).to.have.property('contentType', 'string');
expect(result.data).to.have.property('name', 'string');
expect(result.data).to.have.property(
'createdDate',
'2023-02-04T20:15:45.007Z'
);
expect(result.data).to.have.property(
'modifiedDate',
'2023-02-04T20:15:45.007Z'
);
expect(result.data).to.have.property('owner', 'string');
expect(result.data).to.have.property('notes', 'string');
expect(result.data).to.have.property('fileHref', 'string');
});
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.getFileInfoById(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.message).to.equal(
'{"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.getFileInfoById(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:
'The user does not have permission to access this resource.',
},
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileInfoById(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.message).to.equal(
'The user does not have permission to access this resource.'
);
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: 'The requested resource was not found.',
},
headers: {},
config: {} as InternalAxiosRequestConfig,
} as AxiosResponse)
);
sinon.stub(client, '_client' as any).value(mockAxiosClient);
const result = await client.getFileInfoById(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.message).to.equal('The requested resource was not found.');
expect(result.data).to.be.null;
});
});
});
+1 -2
View File
@@ -1,8 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"module": "CommonJS",
"outDir": "./dist/cjs"
}
}
+1 -2
View File
@@ -1,8 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "esnext",
"target": "es2015",
"module": "ES6",
"outDir": "./dist/esm"
}
}
+3 -2
View File
@@ -1,10 +1,11 @@
{
"compilerOptions": {
"strictNullChecks": true,
"moduleResolution": "node",
"declaration": true,
"declarationDir": "./dist/types",
"esModuleInterop": true
"esModuleInterop": true,
"target": "ES6",
"moduleResolution": "node"
},
"include": ["src/**/*"],
"ts-node": {