From d99fd286c886e9411b0705f3b449afe9033d9e26 Mon Sep 17 00:00:00 2001 From: Kyle Welch Date: Tue, 29 Jan 2019 11:57:00 -0600 Subject: [PATCH] feat: Add organizations api helper (#54) ## Description Adds helper methods for making calls to the organizations api. Currently this only adds the get organizations by user id call. ## How Has This Been Tested? Tests have been added to cover the new API call. ## Screenshots (if appropriate): ## Checklist: * [x] I have read the [**CONTRIBUTING** document](https://github.com/eventbrite/eventbrite-sdk-javascript/blob/master/CONTRIBUTING.md). * [x] I have updated the documentation accordingly. * [x] I have added tests to cover my changes. * [x] I have run `yarn validate` to ensure that tests, typescript and linting are all in order. --- .eslintrc.json | 3 +- docs/README.md | 1 + docs/organizations.md | 39 +++++++++++++++++ src/__tests__/__fixtures__/index.ts | 50 +++++++++++++++++++++ src/__tests__/organizations.spec.ts | 67 +++++++++++++++++++++++++++++ src/organizations.ts | 23 ++++++++++ src/types.ts | 14 ++++++ 7 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 docs/organizations.md create mode 100644 src/__tests__/organizations.spec.ts create mode 100644 src/organizations.ts diff --git a/.eslintrc.json b/.eslintrc.json index cda4c53..c6a8aea 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,7 +21,8 @@ "typescript/no-array-constructor": "error", "typescript/no-empty-interface": "error", "typescript/no-use-before-define": "error", - "typescript/type-annotation-spacing": "error" + "typescript/type-annotation-spacing": "error", + "jest/lowercase-name": "none" }, "settings": { "import/resolver": { diff --git a/docs/README.md b/docs/README.md index 5544a6c..ead9102 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,7 @@ This SDK interface closely mirors the [Eventbrite v3 REST API](https://www.event - [Configuring a SDK object](#configuring-a-sdk-object) - [`request()`](./request.md) - [Users](./users.md) +- [Organizations](./organizations.md) ## Including the package diff --git a/docs/organizations.md b/docs/organizations.md new file mode 100644 index 0000000..bb4ee10 --- /dev/null +++ b/docs/organizations.md @@ -0,0 +1,39 @@ +# Organizations + +This is a collection of methods that are intended to be helpful wrappers around the [organizations API endpoints](organization-api-docs). + +View the [Organizations response object](organization-object-reference) for details on the properties you'll get back with each response. + +## Table on Contents + +- [`sdk.organizations.getByUser(id)`](#getByUser) + + + +## `sdk.organizations.getByUser(id)` +Gets the details for a specific user by their user id. + +**Read [`/users/:userId/organizations/` documentation](organization-by-user) for more details.** + +### API +```js +sdk.organizations.getByUser(userId: string): Promise> +``` + +### Example + +```js +const eventbrite = require('eventbrite'); + +// Create configured Eventbrite SDK +const sdk = eventbrite({token: 'OATH_TOKEN_HERE'}); + +sdk.organizations.getByUser('1234567890').then((paginatedResponse) => { + console.log(`Here are your organizations: ${paginatedResponse.organizations.join(' ')}.`); +}); +``` + + +[organization-api-docs]: https://www.eventbrite.com/platform/api#/reference/organization +[organization-object-reference]: https://www.eventbrite.com/platform/api#/reference/organization +[organization-by-user]: https://www.eventbrite.com/platform/api#/reference/organization/list-organizations-by-user \ No newline at end of file diff --git a/src/__tests__/__fixtures__/index.ts b/src/__tests__/__fixtures__/index.ts index 4d446ff..b37811c 100644 --- a/src/__tests__/__fixtures__/index.ts +++ b/src/__tests__/__fixtures__/index.ts @@ -42,3 +42,53 @@ export const MOCK_ARGUMENTS_ERROR_RESPOSNE_DATA = { error_description: 'There are errors with your arguments: status - INVALID', error: 'ARGUMENTS_ERROR', }; + +export const MOCK_ORGS_BY_USER_SUCCESS_RESPONSE = { + pagination: { + object_count: 3, + page_number: 1, + page_size: 10, + page_count: 1, + continuation: 'some_fake_continuation_key', + has_more_items: false, + }, + organizations: [ + { + id: '1', + name: 'Organization 1', + }, + { + id: '2', + name: 'Organization 2', + }, + { + id: '3', + name: 'Organization 3', + }, + ], +}; + +export const MOCK_TRANSFORMED_ORGS_BY_USER = { + pagination: { + objectCount: 3, + pageNumber: 1, + pageSize: 10, + pageCount: 1, + continuation: 'some_fake_continuation_key', + hasMoreItems: false, + }, + organizations: [ + { + id: '1', + name: 'Organization 1', + }, + { + id: '2', + name: 'Organization 2', + }, + { + id: '3', + name: 'Organization 3', + }, + ], +}; diff --git a/src/__tests__/organizations.spec.ts b/src/__tests__/organizations.spec.ts new file mode 100644 index 0000000..178f50d --- /dev/null +++ b/src/__tests__/organizations.spec.ts @@ -0,0 +1,67 @@ +import { + mockFetch, + getMockFetch, + getMockResponse, + restoreMockFetch, +} from './utils'; +import { + MOCK_ORGS_BY_USER_SUCCESS_RESPONSE, + MOCK_TRANSFORMED_ORGS_BY_USER, +} from './__fixtures__'; + +import request from '../request'; +import {OrganizationsApi} from '../organizations'; + +describe('OrganizationsApi', () => { + describe('getByUser()', () => { + it('calls fetch and calls fetch with appropriate defaults', async() => { + const organizations = new OrganizationsApi(request); + + mockFetch(getMockResponse(MOCK_ORGS_BY_USER_SUCCESS_RESPONSE)); + + await expect(organizations.getByUser('fake_id')).resolves.toEqual( + MOCK_TRANSFORMED_ORGS_BY_USER + ); + + expect(getMockFetch()).toHaveBeenCalledTimes(1); + expect(getMockFetch()).toHaveBeenCalledWith( + '/users/fake_id/organizations/', + expect.objectContaining({}) + ); + + restoreMockFetch(); + }); + + it('handle token missing requests', async() => { + const organizations = new OrganizationsApi(request); + + mockFetch( + getMockResponse( + { + status_code: 401, + error_description: + 'An OAuth token is required for all requests', + error: 'NO_AUTH', + }, + {status: 401} + ) + ); + + await expect( + organizations.getByUser('fake_id') + ).rejects.toMatchObject({ + response: expect.objectContaining({ + status: 401, + statusText: 'Unauthorized', + ok: false, + }), + parsedError: { + description: 'An OAuth token is required for all requests', + error: 'NO_AUTH', + }, + }); + + restoreMockFetch(); + }); + }); +}); diff --git a/src/organizations.ts b/src/organizations.ts new file mode 100644 index 0000000..82fff65 --- /dev/null +++ b/src/organizations.ts @@ -0,0 +1,23 @@ +import {BaseApi} from './baseApi'; +import {PaginatedResponse} from './types'; + +export interface Organization { + id: string; + name: string; + imageId: string; + locale?: string; + vertical?: 'Default' | 'Music'; +} + +/** + * API for working with Organizations + */ +export class OrganizationsApi extends BaseApi> { + /** + * Get organizations based off a user id. + * @param {string} userId + */ + getByUser(userId: string) { + return this.request(`/users/${userId}/organizations/`); + } +} diff --git a/src/types.ts b/src/types.ts index 159a2b3..f5c0920 100644 --- a/src/types.ts +++ b/src/types.ts @@ -31,3 +31,17 @@ export interface JSONResponseData { [propName: string]: any; }; } + +export interface Pagination { + objectCount: number; + pageNumber: number; + pageSize: number; + pageCount: number; + continuation: string; + hasMoreItems: boolean; +} + +export interface PaginatedResponse { + pagination: Pagination; + [key: string]: T[] | Pagination; +}