Skip to content

Instantly share code, notes, and snippets.

@frfernandezdev
Last active June 25, 2023 20:36
Show Gist options
  • Save frfernandezdev/ff72f691eda0e6e0af07fa88c4ef279a to your computer and use it in GitHub Desktop.
Save frfernandezdev/ff72f691eda0e6e0af07fa88c4ef279a to your computer and use it in GitHub Desktop.
import api from 'api';
import { Pagination } from './Pagination';
import { IProperty, Property } from './Property';
export class EasyBrokerAPI extends Pagination {
private url = '@easybroker-staging/v1.0#887olbbcuq6n';
private authToken = 'l7u502p8v46ba3ppgvj5y2aad50lb9';
private instance: any;
constructor() {
super();
this.instance = api(this.url);
this.authorize();
}
authorize() {
return this.instance.auth(this.authToken);
}
async getProperties(): Promise<IProperty[]|undefined> {
this.handler(
(parameters) => this.instance.getProperties(parameters)
.catch(console.error)
);
await this.init();
await this.all();
return Property.fromPrimitives(this._items);
}
}
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
import api from 'api';
import { EasyBrokerAPI } from "./EasyBrokerAPI";
const _auth = jest.fn();
const _getProperties = jest.fn();
jest.mock('api', () => ({
__esModule: true,
default: jest.fn(() => ({
auth: _auth,
getProperties: _getProperties
}))
}));
const mockedApi = <jest.Mock<typeof api>>api;
describe('EasyBrokerAPI', () => {
const url = '@easybroker-staging/v1.0#887olbbcuq6n';
const authToken = 'l7u502p8v46ba3ppgvj5y2aad50lb9';
describe('test integration with api library', () => {
let easybroker = new EasyBrokerAPI();
const mockResponse = {
data: {
content: [],
pagination: {
total: 1
}
}
}
it('test integration with api library', () => {
expect(mockedApi).toHaveBeenCalledWith(url);
expect(_auth).toHaveBeenCalledWith(authToken);
});
it('test called to method getProperties', () => {
_getProperties.mockResolvedValue(mockResponse);
easybroker.getProperties()
const parameters = { page: 1, limit: 20 }
expect(_getProperties).toHaveBeenCalledWith(parameters);
});
});
describe('test pagination service', () => {
let easybroker = new EasyBrokerAPI();
const mockTotal = 40;
const mockLimit = 20;
const length = Math.ceil(mockTotal / mockLimit);
const mockPagesArray = Array.from({ length }, (v, k) => k+1);
const mockResponse = {
data: {
content: [],
pagination: {
total: mockTotal
}
}
}
beforeEach(() => {
_getProperties.mockClear()
});
it('test called to method all', async () => {
_getProperties.mockResolvedValue(mockResponse);
await easybroker.getProperties();
expect(_getProperties).toHaveBeenCalledTimes(2);
expect(_getProperties).toHaveBeenNthCalledWith(1, { page: 1, limit: mockLimit })
expect(_getProperties).toHaveBeenNthCalledWith(2, { page: 2, limit: mockLimit })
})
});
})
import { EasyBrokerAPI } from "./EasyBrokerAPI";
const easybroker = new EasyBrokerAPI();
easybroker.getProperties()
.then((items) =>
items?.forEach(({ title }) => console.log(title))
);
export interface IOperation {
type: string;
amount: number;
currency: string;
formatted_amount: string;
commission: {
type: string;
};
unit: string;
}
export class Operation implements IOperation {
type: string;
amount: number;
currency: string;
formatted_amount: string;
commission: {
type: string;
};
unit: string;
constructor({
type,
amount,
currency,
formatted_amount,
commission,
unit,
}: IOperation) {
this.type = type;
this.amount = amount;
this.currency = currency;
this.formatted_amount = formatted_amount;
this.commission = commission;
this.unit = unit;
}
static fromPrimitives(items: IOperation[]): IOperation[] {
return items.map((item) => new Operation(item));
}
}
{
"name": "easybroker",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "ts-node ./main.ts",
"test": "jest"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"api": "^5.0.8",
"ts-node": "^10.9.1"
},
"devDependencies": {
"@types/jest": "^29.5.2",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.1.3"
}
}
type Parameters = { page: number, limit: number };
type CallbackFunction = (parameters: Parameters) => Promise<any>;
export class Pagination {
private _page: number = 1;
private _limit: number = 20;
private _total: number = 0;
private _handler: CallbackFunction | null = null;
protected _items: any[] = [];
protected handler(fn: CallbackFunction) {
this._handler = fn;
}
protected execHandler() {
if (!this._handler) {
throw new Error('Not set handler function');
}
return this._handler({
page: this._page,
limit: this._limit
})
}
protected async init() {
const { data } = await this.execHandler();
const { pagination, content } = data;
const { total } = pagination;
this._total = total;
this._items = content;
}
protected async all() {
if (!this._total) {
throw new Error('The first request has not been initialized');
}
const length = Math.ceil(this._total / this._limit);
const iterator = Array.from({ length }, (v, k) => k+1).slice(1);
for (const page of iterator) {
this._page = page;
const { data } = await this.execHandler();;
const { content } = data;
this._items = this._items.concat(content);
}
}
}
import { IOperation, Operation } from "./Operation";
export interface IProperty {
public_id: string;
title: string;
title_image_full: string;
title_image_thumb: string;
location: string;
operations: IOperation[];
bedrooms: number;
bathrooms: number;
parking_spaces: number;
property_type: string;
lot_size: number;
construction_size: number;
agent: string;
show_prices: boolean;
share_commission: boolean;
}
export class Property implements IProperty {
public_id: string;
title: string;
title_image_full: string;
title_image_thumb: string;
location: string;
operations: IOperation[];
bedrooms: number;
bathrooms: number;
parking_spaces: number;
property_type: string;
lot_size: number;
construction_size: number;
agent: string;
show_prices: boolean;
share_commission: boolean;
constructor({
public_id,
title,
title_image_full,
title_image_thumb,
location,
operations,
bedrooms,
bathrooms,
parking_spaces,
property_type,
lot_size,
construction_size,
agent,
show_prices,
share_commission,
}: IProperty) {
this.public_id = public_id;
this.title = title;
this.title_image_full = title_image_full;
this.title_image_thumb = title_image_thumb;
this.location = location;
this.operations = Operation.fromPrimitives(operations);
this.bedrooms = bedrooms;
this.bathrooms = bathrooms;
this.parking_spaces = parking_spaces;
this.property_type = property_type;
this.lot_size = lot_size;
this.construction_size = construction_size;
this.agent = agent;
this.show_prices = show_prices;
this.share_commission = share_commission;
}
static fromPrimitives(items: IProperty[]): IProperty[] {
return items.map((item) => new Property(item));
}
}
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment