Skip to content

Commit

Permalink
feat(client|redux): expose closet endpoints
Browse files Browse the repository at this point in the history
This exposes user closet endpoints
  • Loading branch information
andreecosta committed Aug 30, 2023
1 parent a33b504 commit 36018cc
Show file tree
Hide file tree
Showing 56 changed files with 1,969 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,7 @@ Object {
"deleteToken": [Function],
"deleteUserAddress": [Function],
"deleteUserAttribute": [Function],
"deleteUserClosetItem": [Function],
"deleteUserContact": [Function],
"deleteUserDefaultContactAddress": [Function],
"deleteUserExternalLogin": [Function],
Expand Down Expand Up @@ -1146,6 +1147,8 @@ Object {
"getUserAttribute": [Function],
"getUserAttributes": [Function],
"getUserBenefits": [Function],
"getUserCloset": [Function],
"getUserClosets": [Function],
"getUserContact": [Function],
"getUserContacts": [Function],
"getUserCreditBalance": [Function],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type ExchangeFilterCondition = ExchangeFilterLogicOperatorData;
export type ExchangeFilterLogicOperatorData = {
criteria: ExchangeFilterLogicOperatorCriteria;
comparator: ExchangeFilterLogicOperatorComparator;
value: string | string[];
values: string | string[];
};

export enum ExchangeFilterLogicOperatorCriteria {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { rest, type RestHandler } from 'msw';

const path = '/api/account/v1/users/:userId/closets/:closetId/items/:itemId';

const fixtures = {
success: (response: number): RestHandler =>
rest.delete(path, (_req, res, ctx) =>
res(ctx.status(200), ctx.json(response)),
),
failure: (): RestHandler =>
rest.delete(path, (_req, res, ctx) =>
res(ctx.status(404), ctx.json({ message: 'stub error' })),
),
};

export default fixtures;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { rest, type RestHandler } from 'msw';
import type { Closet } from '../index.js';

const path = '/api/account/v1/users/:userId/closets/:closetId';

const fixtures = {
success: (response: Closet[]): RestHandler =>
rest.get(path, (_req, res, ctx) =>
res(ctx.status(200), ctx.json(response)),
),
failure: (): RestHandler =>
rest.get(path, (_req, res, ctx) =>
res(ctx.status(404), ctx.json({ message: 'stub error' })),
),
};

export default fixtures;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { rest, type RestHandler } from 'msw';
import type { ClosetSummary } from '../index.js';

const path = '/api/account/v1/users/:userId/closets';

const fixtures = {
success: (response: ClosetSummary[]): RestHandler =>
rest.get(path, (_req, res, ctx) =>
res(ctx.status(200), ctx.json(response)),
),
failure: (): RestHandler =>
rest.get(path, (_req, res, ctx) =>
res(ctx.status(404), ctx.json({ message: 'stub error' })),
),
};

export default fixtures;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`deleteUserClosetItem should receive a client request error 1`] = `
Object {
"code": "-1",
"message": "stub error",
"name": "AxiosError",
"status": 404,
"transportLayerErrorCode": "ERR_BAD_REQUEST",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`getUserCloset should receive a client request error 1`] = `
Object {
"code": "-1",
"message": "stub error",
"name": "AxiosError",
"status": 404,
"transportLayerErrorCode": "ERR_BAD_REQUEST",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`getUserClosets should receive a client request error 1`] = `
Object {
"code": "-1",
"message": "stub error",
"name": "AxiosError",
"status": 404,
"transportLayerErrorCode": "ERR_BAD_REQUEST",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
closetId,
closetItemId,
userId,
} from 'tests/__fixtures__/users/index.mjs';
import { deleteUserClosetItem } from '../index.js';
import client from '../../../helpers/client/index.js';
import fixtures from '../__fixtures__/deleteUserClosetItem.fixtures.js';
import mswServer from '../../../../tests/mswServer.js';

describe('deleteUserClosetItem', () => {
const expectedConfig = undefined;
const spy = jest.spyOn(client, 'delete');

beforeEach(() => jest.clearAllMocks());

it('should handle a client request successfully', async () => {
const response = 200;

mswServer.use(fixtures.success(response));

await expect(
deleteUserClosetItem(userId, closetId, closetItemId),
).resolves.toBe(response);

expect(spy).toHaveBeenCalledWith(
`/account/v1/users/${userId}/closets/${closetId}/items/${closetItemId}`,
expectedConfig,
);
});

it('should receive a client request error', async () => {
mswServer.use(fixtures.failure());

await expect(
deleteUserClosetItem(userId, closetId, closetItemId),
).rejects.toMatchSnapshot();

expect(spy).toHaveBeenCalledWith(
`/account/v1/users/${userId}/closets/${closetId}/items/${closetItemId}`,
expectedConfig,
);
});
});
40 changes: 40 additions & 0 deletions packages/client/src/users/closets/__tests__/getUserCloset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
closetId,
mockGetUserClosetResponse,
userId,
} from 'tests/__fixtures__/users/index.mjs';
import { getUserCloset } from '../index.js';
import client from '../../../helpers/client/index.js';
import fixtures from '../__fixtures__/getUserCloset.fixtures.js';
import mswServer from '../../../../tests/mswServer.js';

describe('getUserCloset', () => {
const expectedConfig = undefined;
const spy = jest.spyOn(client, 'get');

beforeEach(() => jest.clearAllMocks());

it('should handle a client request successfully', async () => {
mswServer.use(fixtures.success(mockGetUserClosetResponse));

await expect(getUserCloset(userId, closetId)).resolves.toStrictEqual(
mockGetUserClosetResponse,
);

expect(spy).toHaveBeenCalledWith(
`/account/v1/users/${userId}/closets/${closetId}`,
expectedConfig,
);
});

it('should receive a client request error', async () => {
mswServer.use(fixtures.failure());

await expect(getUserCloset(userId, closetId)).rejects.toMatchSnapshot();

expect(spy).toHaveBeenCalledWith(
`/account/v1/users/${userId}/closets/${closetId}`,
expectedConfig,
);
});
});
39 changes: 39 additions & 0 deletions packages/client/src/users/closets/__tests__/getUserClosets.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { getUserClosets } from '../index.js';
import {
mockGetUserClosetsResponse,
userId,
} from 'tests/__fixtures__/users/index.mjs';
import client from '../../../helpers/client/index.js';
import fixtures from '../__fixtures__/getUserClosets.fixtures.js';
import mswServer from '../../../../tests/mswServer.js';

describe('getUserClosets', () => {
const expectedConfig = undefined;
const spy = jest.spyOn(client, 'get');

beforeEach(() => jest.clearAllMocks());

it('should handle a client request successfully', async () => {
mswServer.use(fixtures.success(mockGetUserClosetsResponse));

await expect(getUserClosets(userId)).resolves.toStrictEqual(
mockGetUserClosetsResponse,
);

expect(spy).toHaveBeenCalledWith(
`/account/v1/users/${userId}/closets`,
expectedConfig,
);
});

it('should receive a client request error', async () => {
mswServer.use(fixtures.failure());

await expect(getUserClosets(userId)).rejects.toMatchSnapshot();

expect(spy).toHaveBeenCalledWith(
`/account/v1/users/${userId}/closets`,
expectedConfig,
);
});
});
39 changes: 39 additions & 0 deletions packages/client/src/users/closets/deleteUserClosetItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { adaptError } from '../../helpers/client/formatError.js';
import client from '../../helpers/client/index.js';
import join from 'proper-url-join';
import type { DeleteUserClosetItem } from './types/index.js';

/**
* Method responsible for deleting a user closet.
*
* @param userId - Universal identifier of the user.
* @param closetId - Closet identifier.
* @param itemId - Closet item identifier.
* @param config - Custom configurations to send to the client instance (axios).
*
* @returns Promise that will resolve when the call to the endpoint finishes.
*/
const deleteUserCloset: DeleteUserClosetItem = (
userId,
closetId,
itemId,
config,
) =>
client
.delete(
join(
'/account/v1/users',
userId,
'/closets/',
closetId,
'/items/',
itemId,
),
config,
)
.then(response => response.status)
.catch(error => {
throw adaptError(error);
});

export default deleteUserCloset;
27 changes: 27 additions & 0 deletions packages/client/src/users/closets/getUserCloset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { adaptError } from '../../helpers/client/formatError.js';
import client from '../../helpers/client/index.js';
import join from 'proper-url-join';
import type { GetUserCloset } from './types/index.js';

/**
* Method responsible for getting a specific user closet.
*
* @param userId - Universal identifier of the user.
* @param closetId - Closet identifier.
* @param query - Query params.
* @param config - Custom configurations to send to the client instance (axios).
*
* @returns Promise that will resolve when the call to the endpoint finishes.
*/
const getUserCloset: GetUserCloset = (userId, closetId, query, config) =>
client
.get(
join('/account/v1/users/', userId, '/closets/', closetId, { query }),
config,
)
.then(response => response.data)
.catch(error => {
throw adaptError(error);
});

export default getUserCloset;
22 changes: 22 additions & 0 deletions packages/client/src/users/closets/getUserClosets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { adaptError } from '../../helpers/client/formatError.js';
import client from '../../helpers/client/index.js';
import join from 'proper-url-join';
import type { GetUserClosets } from './types/index.js';

/**
* Method responsible for getting user closets.
*
* @param userId - Universal identifier of the user.
* @param config - Custom configurations to send to the client instance (axios).
*
* @returns Promise that will resolve when the call to the endpoint finishes.
*/
const getUserClosets: GetUserClosets = (userId, config) =>
client
.get(join('/account/v1/users/', userId, '/closets'), config)
.then(response => response.data)
.catch(error => {
throw adaptError(error);
});

export default getUserClosets;
4 changes: 4 additions & 0 deletions packages/client/src/users/closets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { default as deleteUserClosetItem } from './deleteUserClosetItem.js';
export { default as getUserCloset } from './getUserCloset.js';
export { default as getUserClosets } from './getUserClosets.js';
export * from './types/index.js';
31 changes: 31 additions & 0 deletions packages/client/src/users/closets/types/closet.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Brand } from '../../../brands/index.js';
import type {
Color,
PagedResponse,
ProductImageGroup,
ProductVariantAttribute,
} from '../../../types/index.js';
import type { Order } from '../../../orders/index.js';
import type { Price, Product } from '../../../products/index.js';
import type { ProductCategory } from '../../../categories/index.js';

export type Closet = PagedResponse<ClosetItem>;

export type ClosetItem = {
id: string;
orderId: Order['id'];
merchantId: number;
productId: Product['result']['id'];
productName: string;
productDescription: string;
attributes: ProductVariantAttribute[];
images: ProductImageGroup;
categories: ProductCategory[];
colors: Color[];
price: Price;
purchasePrice: Price;
brand: Brand;
customAttributes: string;
isAvailable: boolean;
createdDate: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type ClosetSummary = {
id: string;
createdDate: string;
totalItems: number;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { ClosetItem } from './closet.types.js';
import type { ClosetSummary } from './closetSummary.types.js';
import type { Config } from '../../../types/index.js';
import type { User } from '../../authentication/types/user.types.js';

export type DeleteUserClosetItem = (
userId: User['id'],
closetId: ClosetSummary['id'],
itemId: ClosetItem['id'],
config?: Config,
) => Promise<number>;
Loading

0 comments on commit 36018cc

Please sign in to comment.