feat: implement addOrUpdateListItem method
This commit is contained in:
@@ -10,6 +10,7 @@ import { FormulaField } from './FormulaField';
|
|||||||
import { GetPagedAppsResponse } from './GetPagedAppsResponse';
|
import { GetPagedAppsResponse } from './GetPagedAppsResponse';
|
||||||
import { GetPagedFieldsResponse } from './GetPagedFieldsResponse';
|
import { GetPagedFieldsResponse } from './GetPagedFieldsResponse';
|
||||||
import { ListField } from './ListField';
|
import { ListField } from './ListField';
|
||||||
|
import { ListItemResponse } from './ListItemResponse';
|
||||||
import { ListValue } from './ListValue';
|
import { ListValue } from './ListValue';
|
||||||
import { ReferenceField } from './ReferenceField';
|
import { ReferenceField } from './ReferenceField';
|
||||||
|
|
||||||
@@ -258,6 +259,18 @@ export class ApiResponse<T> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public asListItemResponseType(): ApiResponse<ListItemResponse> {
|
||||||
|
const apiResponse = this as ApiResponse<any>;
|
||||||
|
|
||||||
|
const listItemResponse = new ListItemResponse(apiResponse.data.id);
|
||||||
|
|
||||||
|
return new ApiResponse<ListItemResponse>(
|
||||||
|
apiResponse.statusCode,
|
||||||
|
apiResponse.message,
|
||||||
|
listItemResponse
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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.
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* @class ListItemRequest - Represents a list item request
|
||||||
|
*/
|
||||||
|
export class ListItemRequest {
|
||||||
|
/**
|
||||||
|
* @property {number} listId - The id for the list that the item belongs to.
|
||||||
|
*/
|
||||||
|
public listId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {string} id - The id for the list item.
|
||||||
|
*/
|
||||||
|
public id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {string} name - The name of the list item.
|
||||||
|
*/
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} numericValue - The numeric value of the list item.
|
||||||
|
*/
|
||||||
|
public numericValue: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {string} color - The color of the list item.
|
||||||
|
*/
|
||||||
|
public color: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor - Creates a new instance of the ListItemRequest class.
|
||||||
|
* @param {number} listId - The id for the list that the item belongs to.
|
||||||
|
* @param {string} id - The id for the list item.
|
||||||
|
* @param {string} name - The name of the list item.
|
||||||
|
* @param {number} numericValue - The numeric value of the list item.
|
||||||
|
* @param {string} color - The color of the list item.
|
||||||
|
* @returns {ListItemRequest} - A new instance of the ListItemRequest class.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
listId: number,
|
||||||
|
id: string,
|
||||||
|
name: string,
|
||||||
|
numericValue: number,
|
||||||
|
color: string
|
||||||
|
) {
|
||||||
|
this.listId = listId;
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.numericValue = numericValue;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { CreatedWithIdResponse } from './CreatedWithIdResponse';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class ListItemResponse - Represents a respons when a list item is created or updated.
|
||||||
|
*/
|
||||||
|
export class ListItemResponse extends CreatedWithIdResponse {
|
||||||
|
constructor(id: number) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ 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';
|
import { type File } from './File';
|
||||||
|
import { type ListItemResponse } from './ListItemResponse';
|
||||||
|
import { type ListItemRequest } from './ListItemRequest';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class OnspringClient - A client that can communicate with the Onspring API.
|
* @class OnspringClient - A client that can communicate with the Onspring API.
|
||||||
@@ -269,6 +271,22 @@ export class OnspringClient {
|
|||||||
return apiResponse;
|
return apiResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async addOrUpdateListItem(
|
||||||
|
listItemRequest: ListItemRequest
|
||||||
|
): Promise<ApiResponse<ListItemResponse>> {
|
||||||
|
const { listId, ...data } = listItemRequest;
|
||||||
|
|
||||||
|
const endpoint = EndpointFactory.getAddOrUpdateListItemEndpoint(listId);
|
||||||
|
|
||||||
|
const apiResponse = await this.put<any>(endpoint, data);
|
||||||
|
|
||||||
|
if (apiResponse.isSuccessful === false) {
|
||||||
|
return apiResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse.asListItemResponseType();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method get - Makes a GET request to the specified endpoint.
|
* @method get - Makes a GET request to the specified endpoint.
|
||||||
* @param {string} endpoint - The endpoint that will be used to make the request.
|
* @param {string} endpoint - The endpoint that will be used to make the request.
|
||||||
@@ -301,6 +319,29 @@ export class OnspringClient {
|
|||||||
return apiResponse;
|
return apiResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method put - Makes a PUT request to the specified endpoint.
|
||||||
|
* @param {string} endpoint - The endpoint that will be used to make the request.
|
||||||
|
* @param {any} data - The data that will be sent with the request.
|
||||||
|
* @param {AxiosRequestConfig} config - The configuration that will be used to make the request.
|
||||||
|
* @returns {Promise<ApiResponse<T>>} - A promise that resolves to an ApiResponse of type T.
|
||||||
|
*/
|
||||||
|
private async put<T>(
|
||||||
|
endpoint: string,
|
||||||
|
data: any,
|
||||||
|
config: AxiosRequestConfig = {}
|
||||||
|
): Promise<ApiResponse<T>> {
|
||||||
|
const response = await this._client.put(endpoint, data, config);
|
||||||
|
const apiResponse = ApiResponseFactory.getApiResponse<T>(response);
|
||||||
|
return apiResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method delete - Makes a DELETE request to the specified endpoint.
|
||||||
|
* @param {string} endpoint - The endpoint that will be used to make the request.
|
||||||
|
* @param {AxiosRequestConfig} config - The configuration that will be used to make the request.
|
||||||
|
* @returns {Promise<ApiResponse<T>>} - A promise that resolves to an ApiResponse of type T.
|
||||||
|
*/
|
||||||
private async delete<T>(
|
private async delete<T>(
|
||||||
endpoint: string,
|
endpoint: string,
|
||||||
config: AxiosRequestConfig = {}
|
config: AxiosRequestConfig = {}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { File } from '../src/models/File';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { type AxiosResponse } from 'axios';
|
import { type AxiosResponse } from 'axios';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { ListItemResponse } from '../src/models/ListItemResponse';
|
||||||
|
|
||||||
describe('ApiResponse', function () {
|
describe('ApiResponse', function () {
|
||||||
it('should be defined', function () {
|
it('should be defined', function () {
|
||||||
@@ -916,4 +917,29 @@ describe('ApiResponse', function () {
|
|||||||
expect(fileResponse.data).to.have.property('contentLength', 0);
|
expect(fileResponse.data).to.have.property('contentLength', 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('asListItemResponseType', function () {
|
||||||
|
it('should be defined', function () {
|
||||||
|
expect(ApiResponse.prototype.asListItemResponseType).to.not.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be a function', function () {
|
||||||
|
expect(ApiResponse.prototype.asListItemResponseType).to.be.a('function');
|
||||||
|
});
|
||||||
|
it('should have no parameters', function () {
|
||||||
|
expect(ApiResponse.prototype.asListItemResponseType.length).to.equal(0);
|
||||||
|
});
|
||||||
|
it('should return an ApiResponse<ListItemResponse>', function () {
|
||||||
|
const apiResponse = new ApiResponse(200, 'OK', {
|
||||||
|
id: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
|
||||||
|
});
|
||||||
|
const listItemResponse = apiResponse.asListItemResponseType();
|
||||||
|
expect(listItemResponse).to.be.an.instanceof(ApiResponse);
|
||||||
|
expect(listItemResponse.data).to.be.an.instanceof(ListItemResponse);
|
||||||
|
expect(listItemResponse.data).to.have.property(
|
||||||
|
'id',
|
||||||
|
'3fa85f64-5717-4562-b3fc-2c963f66afa6'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { ListItemRequest } from '../src/models/ListItemRequest';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
|
describe('ListItemRequest', function () {
|
||||||
|
it('should be defined', function () {
|
||||||
|
expect(ListItemRequest).to.not.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a constructor with 5 parameters', function () {
|
||||||
|
expect(ListItemRequest).to.have.property('constructor');
|
||||||
|
expect(ListItemRequest).to.have.lengthOf(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a constructor that takes a listId, id, name, numericValue, and color and sets the listId, id, name, numericValue, and color properties', function () {
|
||||||
|
const listId = 1;
|
||||||
|
const id = '1';
|
||||||
|
const name = 'name';
|
||||||
|
const numericValue = 1;
|
||||||
|
const color = 'color';
|
||||||
|
const listItemRequest = new ListItemRequest(
|
||||||
|
listId,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
numericValue,
|
||||||
|
color
|
||||||
|
);
|
||||||
|
expect(listItemRequest).to.have.property('listId', listId);
|
||||||
|
expect(listItemRequest).to.have.property('id', id);
|
||||||
|
expect(listItemRequest).to.have.property('name', name);
|
||||||
|
expect(listItemRequest).to.have.property('numericValue', numericValue);
|
||||||
|
expect(listItemRequest).to.have.property('color', color);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { ListItemResponse } from '../src/models/ListItemResponse';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
|
describe('ListItemResponse', function () {
|
||||||
|
it('should be defined', function () {
|
||||||
|
expect(ListItemResponse).to.not.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a constructor with 1 parameter', function () {
|
||||||
|
expect(ListItemResponse).to.have.property('constructor');
|
||||||
|
expect(ListItemResponse.constructor).to.have.lengthOf(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a constructor that takes an id and sets the id property', function () {
|
||||||
|
const id = 1;
|
||||||
|
const listItemResponse = new ListItemResponse(id);
|
||||||
|
expect(listItemResponse).to.have.property('id', id);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -20,6 +20,8 @@ import { FileInfo } from '../src/models/FileInfo';
|
|||||||
import { File } from '../src/models/File';
|
import { File } from '../src/models/File';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { ListItemRequest } from '../src/models/ListItemRequest';
|
||||||
|
import { ListItemResponse } from '../src/models/ListItemResponse';
|
||||||
|
|
||||||
describe('OnspringClient', function () {
|
describe('OnspringClient', function () {
|
||||||
const baseUrl = 'https://api.onspring.dev';
|
const baseUrl = 'https://api.onspring.dev';
|
||||||
@@ -2108,4 +2110,199 @@ describe('OnspringClient', function () {
|
|||||||
expect(result.data).to.be.null;
|
expect(result.data).to.be.null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('addOrUpdateListItem', function () {
|
||||||
|
it('should be defined', function () {
|
||||||
|
expect(OnspringClient.prototype.addOrUpdateListItem).to.not.be.undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be a function', function () {
|
||||||
|
expect(OnspringClient.prototype.addOrUpdateListItem).to.be.a('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a promise', function () {
|
||||||
|
expect(
|
||||||
|
new OnspringClient(baseUrl, apiKey).addOrUpdateListItem(
|
||||||
|
new ListItemRequest(1, 'id', 'value', 1, 'color')
|
||||||
|
)
|
||||||
|
).to.be.instanceOf(Promise);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a promise that resolves to an api response when request is successful at updating a list item', 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, 'put').returns(
|
||||||
|
Promise.resolve({
|
||||||
|
status: 200,
|
||||||
|
statusText: 'OK',
|
||||||
|
data: { id: '3fa85f64-5717-4562-b3fc-2c963f66afa6' },
|
||||||
|
headers: {},
|
||||||
|
config: {} as InternalAxiosRequestConfig,
|
||||||
|
} as AxiosResponse)
|
||||||
|
);
|
||||||
|
|
||||||
|
sinon.stub(client, '_client' as any).value(mockAxiosClient);
|
||||||
|
|
||||||
|
const result = await client.addOrUpdateListItem(
|
||||||
|
new ListItemRequest(1, 'id', 'value', 1, 'color')
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).to.be.instanceOf(ApiResponse);
|
||||||
|
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(ListItemResponse);
|
||||||
|
expect(result.data).to.have.property(
|
||||||
|
'id',
|
||||||
|
'3fa85f64-5717-4562-b3fc-2c963f66afa6'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a promise that resolves to an api response when request is successful at adding a list item', 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, 'put').returns(
|
||||||
|
Promise.resolve({
|
||||||
|
status: 201,
|
||||||
|
statusText: 'OK',
|
||||||
|
data: { id: '3fa85f64-5717-4562-b3fc-2c963f66afa6' },
|
||||||
|
headers: {},
|
||||||
|
config: {} as InternalAxiosRequestConfig,
|
||||||
|
} as AxiosResponse)
|
||||||
|
);
|
||||||
|
|
||||||
|
sinon.stub(client, '_client' as any).value(mockAxiosClient);
|
||||||
|
|
||||||
|
const result = await client.addOrUpdateListItem(
|
||||||
|
new ListItemRequest(1, 'id', 'value', 1, 'color')
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).to.be.instanceOf(ApiResponse);
|
||||||
|
expect(result).to.have.property('statusCode', 201);
|
||||||
|
expect(result).to.have.property('isSuccessful', true);
|
||||||
|
expect(result).to.have.property('message', '');
|
||||||
|
expect(result.data).to.be.instanceOf(ListItemResponse);
|
||||||
|
expect(result.data).to.have.property(
|
||||||
|
'id',
|
||||||
|
'3fa85f64-5717-4562-b3fc-2c963f66afa6'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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, 'put').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.addOrUpdateListItem(
|
||||||
|
new ListItemRequest(1, 'id', 'value', 1, 'color')
|
||||||
|
);
|
||||||
|
|
||||||
|
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, 'put').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.addOrUpdateListItem(
|
||||||
|
new ListItemRequest(1, 'id', 'value', 1, 'color')
|
||||||
|
);
|
||||||
|
|
||||||
|
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, 'put').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.addOrUpdateListItem(
|
||||||
|
new ListItemRequest(1, 'id', 'value', 1, 'color')
|
||||||
|
);
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user