Skip to content

Commit

Permalink
feat(customers): add customers handler with count and getAll methods
Browse files Browse the repository at this point in the history
  • Loading branch information
erezsob committed Oct 11, 2018
1 parent cd6c648 commit deff6b5
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,17 @@ export class BranchesCountFailed extends BaseError {
super(message)
}
}

export class CustomersFetchFailed extends BaseError {
public name = 'CustomersFetchFailed'
constructor(public message: string = 'Could not fetch customers') {
super(message)
}
}

export class CustomersCountFailed extends BaseError {
public name = 'CustomersCountFailed'
constructor(public message: string = 'Could not count the customers') {
super(message)
}
}
18 changes: 18 additions & 0 deletions src/tillhub-js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,24 @@ export class TillhubClient {

return new v0.Branches({ user: this.auth.user, base: this.options.base }, this.http)
}

/**
* Create an authenticated customers instance
*
*/
customers(): v0.Customers {
if (
!this.options ||
!this.options.base ||
!this.http ||
!this.auth ||
!this.auth.authenticated
) {
throw new errors.UninstantiatedClient()
}

return new v0.Customers({ user: this.auth.user, base: this.options.base }, this.http)
}
}

export class Tillhub extends TillhubClient {
Expand Down
79 changes: 79 additions & 0 deletions src/v0/customers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Client } from '../client'
import * as errors from '../errors'

export interface CustomersOptions {
user?: string
base?: string
}

export interface CustomersQuery {
limit?: number
uri?: string
}

export interface CustomersResponse {
data: object[]
metadata: object
}

export class Customers {
endpoint: string
http: Client
public options: CustomersOptions

constructor(options: CustomersOptions, http: Client) {
this.options = options
this.http = http

this.endpoint = '/api/v0/customers'
this.options.base = this.options.base || 'https://api.tillhub.com'
}

getAll(query?: CustomersQuery | undefined): Promise<CustomersResponse> {
return new Promise(async (resolve, reject) => {
let next

try {
let uri
if (query && query.uri) {
uri = query.uri
} else {
uri = `${this.options.base}${this.endpoint}/${this.options.user}`
}

const response = await this.http.getClient().get(uri)
if (response.status !== 200) reject(new errors.CustomersFetchFailed())

if (response.data.cursor && response.data.cursor.next) {
next = this.getAll({ uri: response.data.cursor.next })
}

return resolve({
data: response.data.results,
metadata: { cursor: response.data.cursor },
next
} as CustomersResponse)
} catch (err) {
return reject(new errors.CustomersFetchFailed())
}
})
}

count(): Promise<CustomersResponse> {
return new Promise(async (resolve, reject) => {
let uri = `${this.options.base}${this.endpoint}/${this.options.user}/meta`

try {
const response = await this.http.getClient().get(uri)
if (response.status !== 200) reject(new errors.CustomersCountFailed())

return resolve({
data: response.data.results,
metadata: { count: response.data.count }
} as CustomersResponse)
} catch (err) {
return reject(new errors.CustomersCountFailed())
}
})
}
}
13 changes: 12 additions & 1 deletion src/v0/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,16 @@ import { ProductGroups } from './product_groups'
import { Accounts } from './accounts'
import { Configurations } from './configurations'
import { Branches } from './branches'
import { Customers } from './customers'

export { Auth, Transactions, Taxes, Deliveries, ProductGroups, Accounts, Configurations, Branches }
export {
Auth,
Transactions,
Taxes,
Deliveries,
ProductGroups,
Accounts,
Configurations,
Branches,
Customers
}
125 changes: 125 additions & 0 deletions test/customers/count.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import * as dotenv from 'dotenv'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
dotenv.config()
import { TillhubClient, v0 } from '../../src/tillhub-js'

let user = {
username: 'test@example.com',
password: '12345678',
clientAccount: 'someuuid',
apiKey: '12345678'
}

if (process.env.SYSTEM_TEST) {
user.username = process.env.SYSTEM_TEST_USERNAME || user.username
user.password = process.env.SYSTEM_TEST_PASSWORD || user.password
user.clientAccount = process.env.SYSTEM_TEST_CLIENT_ACCOUNT_ID || user.clientAccount
user.apiKey = process.env.SYSTEM_TEST_API_KEY || user.apiKey
}

describe('v0: Branches: can get count number of all customers', () => {
it("Tillhub's branches are instantiable", async () => {
if (process.env.SYSTEM_TEST !== 'true') {
const mock = new MockAdapter(axios)
const legacyId = '4564'

mock.onPost('https://api.tillhub.com/api/v0/users/login').reply(function(config) {
return [
200,
{
token: '',
user: {
id: '123',
legacy_id: legacyId
}
}
]
})

mock
.onGet(`https://api.tillhub.com/api/v0/customers/${legacyId}/meta`)
.reply(function(config) {
return [
200,
{
count: 50,
results: [{ count: 50 }]
}
]
})
}

const options = {
credentials: {
username: user.username,
password: user.password
},
base: process.env.TILLHUB_BASE
}

const th = new TillhubClient()

th.init(options)
await th.auth.loginUsername({
username: user.username,
password: user.password
})

const customers = th.customers()

expect(customers).toBeInstanceOf(v0.Customers)

const { data } = await customers.count()

expect(Array.isArray(data)).toBe(true)
})

it('rejects on status codes that are not 200', async () => {
if (process.env.SYSTEM_TEST !== 'true') {
const mock = new MockAdapter(axios)
const legacyId = '4564'

mock.onPost('https://api.tillhub.com/api/v0/users/login').reply(function(config) {
return [
200,
{
token: '',
user: {
id: '123',
legacy_id: legacyId
}
}
]
})

mock
.onGet(`https://api.tillhub.com/api/v0/customers/${legacyId}/meta`)
.reply(function(config) {
return [205]
})
}

const options = {
credentials: {
username: user.username,
password: user.password
},
base: process.env.TILLHUB_BASE
}

const th = new TillhubClient()

th.init(options)
await th.auth.loginUsername({
username: user.username,
password: user.password
})

try {
await th.customers().count()
} catch (err) {
expect(err.name).toBe('CustomersCountFailed')
}
})
})
121 changes: 121 additions & 0 deletions test/customers/get-all.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import * as dotenv from 'dotenv'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
dotenv.config()
import { TillhubClient, v0 } from '../../src/tillhub-js'

let user = {
username: 'test@example.com',
password: '12345678',
clientAccount: 'someuuid',
apiKey: '12345678'
}

if (process.env.SYSTEM_TEST) {
user.username = process.env.SYSTEM_TEST_USERNAME || user.username
user.password = process.env.SYSTEM_TEST_PASSWORD || user.password
user.clientAccount = process.env.SYSTEM_TEST_CLIENT_ACCOUNT_ID || user.clientAccount
user.apiKey = process.env.SYSTEM_TEST_API_KEY || user.apiKey
}

describe('v0: customers: can get all', () => {
const legacyId = '4564'
const mock = new MockAdapter(axios)
afterEach(() => {
mock.reset()
})

it("Tillhub's customers are instantiable", async () => {
if (process.env.SYSTEM_TEST !== 'true') {
mock.onPost('https://api.tillhub.com/api/v0/users/login').reply(function(config) {
return [
200,
{
token: '',
user: {
id: '123',
legacy_id: legacyId
}
}
]
})

mock.onGet(`https://api.tillhub.com/api/v0/customers/${legacyId}`).reply(function(config) {
return [
200,
{
count: 1,
results: [{}]
}
]
})
}

const options = {
credentials: {
username: user.username,
password: user.password
},
base: process.env.TILLHUB_BASE
}

const th = new TillhubClient()

th.init(options)
await th.auth.loginUsername({
username: user.username,
password: user.password
})

const customers = th.customers()

expect(customers).toBeInstanceOf(v0.Customers)

const { data } = await customers.getAll()

expect(Array.isArray(data)).toBe(true)
})

it('rejects on status codes that are not 200', async () => {
if (process.env.SYSTEM_TEST !== 'true') {
mock.onPost('https://api.tillhub.com/api/v0/users/login').reply(function(config) {
return [
200,
{
token: '',
user: {
id: '123',
legacy_id: legacyId
}
}
]
})

mock.onGet(`https://api.tillhub.com/api/v0/customers/${legacyId}`).reply(function(config) {
return [205]
})
}

const options = {
credentials: {
username: user.username,
password: user.password
},
base: process.env.TILLHUB_BASE
}

const th = new TillhubClient()

th.init(options)
await th.auth.loginUsername({
username: user.username,
password: user.password
})

try {
await th.customers().getAll()
} catch (err) {
expect(err.name).toBe('CustomersFetchFailed')
}
})
})

0 comments on commit deff6b5

Please sign in to comment.