diff --git a/src/api/v2/routes/support/tags.js b/src/api/v2/routes/support/tags.js index d756a20..c32e2eb 100644 --- a/src/api/v2/routes/support/tags.js +++ b/src/api/v2/routes/support/tags.js @@ -1,56 +1,79 @@ -module.exports = ({ instance, headers }) => ({ - list: () => ({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/tags.json`, - headers - }), - - show: ({ type, id }) => ({ - method: 'GET', - url: { - tickets: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - organizations: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - users: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json` - }[type], - headers - }), - - set: ({ type, id, data }) => ({ - method: 'POST', - url: { - tickets: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - organizations: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - users: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json` - }[type], - headers, - data - }), - - add: ({ type, id, data }) => ({ - method: 'PUT', - url: { - tickets: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - organizations: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - users: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json` - }[type], - headers, - data - }), - - remove: ({ type, id, data }) => ({ - method: 'DELETE', - url: { - tickets: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - organizations: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - users: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json` - }[type], - headers, - data - }), - - autocomplete: ({ name }) => ({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/autocomplete/tags.json?name=${name}`, - headers - }) -}); +const validate = require('../../validators/support/tags'); + +module.exports = ({ instance, headers }) => { + const url = `https://${instance}.zendesk.com`; + + return { + list: (options = null) => { + if (options) throw new Error('no options are allowed'); + + return { + method: 'GET', + url: `${url}/api/v2/tags.json`, + headers + }; + }, + + show: (options = {}) => { + const { error } = validate.show(options); + if (error) throw new Error(error.details[0].message); + + const { type, id } = options; + return { + method: 'GET', + url: `${url}/api/v2/${type}/${id}/tags.json`, + headers + }; + }, + + set: (options = {}) => { + const { error } = validate.set(options); + if (error) throw new Error(error.details[0].message); + + const { type, id, data } = options; + return { + method: 'POST', + url: `${url}/api/v2/${type}/${id}/tags.json`, + headers, + data + }; + }, + + add: (options = {}) => { + const { error } = validate.add(options); + if (error) throw new Error(error.details[0].message); + + const { type, id, data } = options; + return { + method: 'PUT', + url: `${url}/api/v2/${type}/${id}/tags.json`, + headers, + data + }; + }, + + remove: (options = {}) => { + const { error } = validate.remove(options); + if (error) throw new Error(error.details[0].message); + + const { type, id } = options; + return { + method: 'DELETE', + url: `${url}/api/v2/${type}/${id}/tags.json`, + headers + }; + }, + + autocomplete: (options = {}) => { + const { error } = validate.autocomplete(options); + if (error) throw new Error(error.details[0].message); + + const { name } = options; + return { + method: 'GET', + url: `${url}/api/v2/autocomplete/tags.json?name=${name}`, + headers + }; + } + }; +}; diff --git a/src/api/v2/validators/support/tags.js b/src/api/v2/validators/support/tags.js new file mode 100644 index 0000000..2d9f6a7 --- /dev/null +++ b/src/api/v2/validators/support/tags.js @@ -0,0 +1,27 @@ +const Joi = require('@hapi/joi'); + +const type = Joi.string().valid('tickets', 'organizations', 'users'); +const id = Joi.number().min(1); +const name = Joi.string().min(1); +const data = Joi.object(); + +module.exports = { + list: null, // no options + show: options => + Joi.validate(options, { type: type.required(), id: id.required() }), + set: options => + Joi.validate(options, { + type: type.required(), + id: id.required(), + data: data.required() + }), + add: options => + Joi.validate(options, { + type: type.required(), + id: id.required(), + data: data.required() + }), + remove: options => + Joi.validate(options, { type: type.required(), id: id.required() }), + autocomplete: options => Joi.validate(options, { name: name.required() }) +}; diff --git a/tests/src/api/v2/routes/support/tags.test.js b/tests/src/api/v2/routes/support/tags.test.js index 36d75e0..a0eb5c6 100644 --- a/tests/src/api/v2/routes/support/tags.test.js +++ b/tests/src/api/v2/routes/support/tags.test.js @@ -1,127 +1,195 @@ const endpoint = require('../../../../../../src/api/v2/routes/support/tags'); const instance = 'instance'; -const headers = {}; +const url = `https://${instance}.zendesk.com`; +const headers = { + 'Content-Type': 'application/json', + Authorization: 'Basic <64bit_encoded_credentials>' +}; describe('tags', () => { - let tags, id, data, name; - - beforeEach(() => { - tags = endpoint({ instance, headers }); - id = 123; - data = {}; - name = 'tag_name'; - }); - - afterEach(() => { - tags = null; - id = 0; - data = null; - name = ''; - }); - - test('list tags', () => { - expect(tags.list()).toEqual({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/tags.json`, - headers + let tags; + + beforeEach(() => (tags = endpoint({ instance, headers }))); + afterEach(() => (tags = null)); + + describe('list tags', () => { + it('should process w/ valid input', () => { + expect(tags.list()).toEqual({ + method: 'GET', + url: `${url}/api/v2/tags.json`, + headers + }); }); - }); - test('show tags', () => { - expect(tags.show({ type: 'tickets', id })).toEqual({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - headers + it('should throw error w/ invalid input', () => { + expect(() => tags.list('invalid')).toThrowError(); }); + }); - expect(tags.show({ type: 'organizations', id })).toEqual({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - headers + describe('show tags', () => { + it('should process w/ valid input', () => { + expect(tags.show({ type: 'tickets', id: 123 })).toEqual({ + method: 'GET', + url: `${url}/api/v2/tickets/123/tags.json`, + headers + }); + + expect(tags.show({ type: 'organizations', id: 123 })).toEqual({ + method: 'GET', + url: `${url}/api/v2/organizations/123/tags.json`, + headers + }); + + expect(tags.show({ type: 'users', id: 123 })).toEqual({ + method: 'GET', + url: `${url}/api/v2/users/123/tags.json`, + headers + }); }); - expect(tags.show({ type: 'users', id })).toEqual({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json`, - headers + it('should throw error w/ invalid input', () => { + expect(() => tags.show()).toThrowError(); + expect(() => tags.show('invalid')).toThrowError(); + expect(() => tags.show({})).toThrowError(); + expect(() => tags.show({ invalid: '' })).toThrowError(); + expect(() => tags.show({ type: '' })).toThrowError(); + expect(() => tags.show({ type: 'tickets' })).toThrowError(); + expect(() => tags.show({ type: 'tickets', id: 0 })).toThrowError(); + expect(() => + tags.show({ type: 'tickets', id: 'invalid' }) + ).toThrowError(); }); }); - test('set tags', () => { - expect(tags.set({ type: 'tickets', id, data })).toEqual({ - method: 'POST', - url: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - headers, - data + describe('set tags', () => { + it('should process w/ valid input', () => { + expect(tags.set({ type: 'tickets', id: 123, data: {} })).toEqual({ + method: 'POST', + url: `${url}/api/v2/tickets/123/tags.json`, + headers, + data: {} + }); + + expect(tags.set({ type: 'organizations', id: 123, data: {} })).toEqual({ + method: 'POST', + url: `${url}/api/v2/organizations/123/tags.json`, + headers, + data: {} + }); + + expect(tags.set({ type: 'users', id: 123, data: {} })).toEqual({ + method: 'POST', + url: `${url}/api/v2/users/123/tags.json`, + headers, + data: {} + }); }); - expect(tags.set({ type: 'organizations', id, data })).toEqual({ - method: 'POST', - url: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - headers, - data - }); - - expect(tags.set({ type: 'users', id, data })).toEqual({ - method: 'POST', - url: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json`, - headers, - data + it('should throw error w/ invalid input', () => { + expect(() => tags.set()).toThrowError(); + expect(() => tags.set('invalid')).toThrowError(); + expect(() => tags.set({})).toThrowError(); + expect(() => tags.set({ type: 'invalid' })).toThrowError(); + expect(() => tags.set({ type: 'tickets' })).toThrowError(); + expect(() => tags.set({ type: 'tickets', id: 0 })).toThrowError(); + expect(() => tags.set({ type: 'tickets', id: 123 })).toThrowError(); + expect(() => + tags.set({ type: 'tickets', id: 123, data: 'invalid' }) + ).toThrowError(); }); }); - test('add tags', () => { - expect(tags.add({ type: 'tickets', id, data })).toEqual({ - method: 'PUT', - url: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - headers, - data - }); - - expect(tags.add({ type: 'organizations', id, data })).toEqual({ - method: 'PUT', - url: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - headers, - data + describe('add tags', () => { + it('should process w/ valid input', () => { + expect(tags.add({ type: 'tickets', id: 123, data: {} })).toEqual({ + method: 'PUT', + url: `${url}/api/v2/tickets/123/tags.json`, + headers, + data: {} + }); + + expect(tags.add({ type: 'organizations', id: 123, data: {} })).toEqual({ + method: 'PUT', + url: `${url}/api/v2/organizations/123/tags.json`, + headers, + data: {} + }); + + expect(tags.add({ type: 'users', id: 123, data: {} })).toEqual({ + method: 'PUT', + url: `${url}/api/v2/users/123/tags.json`, + headers, + data: {} + }); }); - expect(tags.add({ type: 'users', id, data })).toEqual({ - method: 'PUT', - url: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json`, - headers, - data + it('should throw error w/ invalid input', () => { + expect(() => tags.add()).toThrowError(); + expect(() => tags.add('invalid')).toThrowError(); + expect(() => tags.add({})).toThrowError(); + expect(() => tags.add({ type: 'invalid' })).toThrowError(); + expect(() => tags.add({ type: 'tickets', id: 'invalid' })).toThrowError(); + expect(() => tags.add({ type: 'tickets', id: 0 })).toThrowError(); + expect(() => tags.add({ type: 'tickets', id: 123 })).toThrowError(); + expect(() => + tags.add({ type: 'tickets', id: 123, data: 'invalid' }) + ).toThrowError(); }); }); - test('remove tags', () => { - expect(tags.remove({ type: 'tickets', id, data })).toEqual({ - method: 'DELETE', - url: `https://${instance}.zendesk.com/api/v2/tickets/${id}/tags.json`, - headers, - data + describe('remove tags', () => { + it('should process w/ valid input', () => { + expect(tags.remove({ type: 'tickets', id: 123 })).toEqual({ + method: 'DELETE', + url: `${url}/api/v2/tickets/123/tags.json`, + headers + }); + + expect(tags.remove({ type: 'organizations', id: 123 })).toEqual({ + method: 'DELETE', + url: `${url}/api/v2/organizations/123/tags.json`, + headers + }); + + expect(tags.remove({ type: 'users', id: 123 })).toEqual({ + method: 'DELETE', + url: `${url}/api/v2/users/123/tags.json`, + headers + }); }); - expect(tags.remove({ type: 'organizations', id, data })).toEqual({ - method: 'DELETE', - url: `https://${instance}.zendesk.com/api/v2/organizations/${id}/tags.json`, - headers, - data + it('should throw error w/ invalid input', () => { + expect(() => tags.remove()).toThrowError(); + expect(() => tags.remove('invalid')).toThrowError(); + expect(() => tags.remove({})).toThrowError(); + expect(() => tags.remove({ invalid: '' })).toThrowError(); + expect(() => tags.remove({ type: '' })).toThrowError(); + expect(() => tags.remove({ type: 'tickets' })).toThrowError(); + expect(() => tags.remove({ type: 'tickets', id: 0 })).toThrowError(); + expect(() => + tags.remove({ type: 'tickets', id: 'invalid' }) + ).toThrowError(); + expect(() => + tags.remove({ type: 'tickets', id: 123, invalid: '' }) + ).toThrowError(); }); + }); - expect(tags.remove({ type: 'users', id, data })).toEqual({ - method: 'DELETE', - url: `https://${instance}.zendesk.com/api/v2/users/${id}/tags.json`, - headers, - data + describe('autocomplete tags', () => { + it('should process w/ valid input', () => { + expect(tags.autocomplete({ name: 'name' })).toEqual({ + method: 'GET', + url: `${url}/api/v2/autocomplete/tags.json?name=name`, + headers + }); }); - }); - test('autocomplete tags', () => { - expect(tags.autocomplete({ name })).toEqual({ - method: 'GET', - url: `https://${instance}.zendesk.com/api/v2/autocomplete/tags.json?name=${name}`, - headers + it('should throw error w/ invalid input', () => { + expect(() => tags.autocomplete()).toThrowError(); + expect(() => tags.autocomplete('invalid')).toThrowError(); + expect(() => tags.autocomplete({})).toThrowError(); + expect(() => tags.autocomplete({ name: 0 })).toThrowError(); }); }); });