From 8c6d6d3de4943aa2db36c1c1c68aa42195ad8a05 Mon Sep 17 00:00:00 2001 From: Brage Sekse Aarset Date: Fri, 8 Sep 2023 10:14:18 +0300 Subject: [PATCH] feat: add contacts query (#108) * feat: add contacts query * feat: add test --- src/calls/contact/__tests__/contact.test.ts | 85 +++++++++++++++++++++ src/calls/contact/contact.ts | 77 +++++++++++++++++++ src/calls/contact/models/contact.ts | 34 +++++++++ 3 files changed, 196 insertions(+) create mode 100644 src/calls/contact/__tests__/contact.test.ts create mode 100644 src/calls/contact/contact.ts create mode 100644 src/calls/contact/models/contact.ts diff --git a/src/calls/contact/__tests__/contact.test.ts b/src/calls/contact/__tests__/contact.test.ts new file mode 100644 index 0000000..4633c81 --- /dev/null +++ b/src/calls/contact/__tests__/contact.test.ts @@ -0,0 +1,85 @@ +import { endOfMonth, startOfMonth } from 'date-fns'; +import nock from 'nock'; +import { invariant } from 'ts-invariant'; +import { parseRuntypeValidationError } from '../../../utils'; +import { TripletexContact } from '../contact'; + +const baseUrl = process.env.BASE_URL || 'https://api.tripletex.io/'; +const sessionToken = process.env.SESSION_TOKEN || 'a-session-token'; + +describe('activity class', () => { + let client: TripletexContact; + + beforeEach(() => { + client = new TripletexContact({ baseUrl }, sessionToken); + }); + + it('should list contacts', async () => { + nock('https://api.tripletex.io:443', { encodedQueryParams: true }) + .get('/v2/contact') + .reply(200, { + fullResultSize: 1, + from: 0, + count: 1, + versionDigest: 'Checksum not yet supported for this endpoint', + values: [ + { + id: 1734852, + version: 1, + url: 'api.tripletex.io/v2/contact/1734852', + firstName: 'Simen A. W. Olsen', + lastName: 'API Testuser', + displayName: 'Simen A. W. Olsen API Testuser', + email: 'an@email.co.uk', + phoneNumberMobileCountry: { + id: 161, + url: 'api.tripletex.io/v2/country/161', + }, + phoneNumberMobile: '', + phoneNumberWork: '', + customer: { + id: 88885, + url: 'api.tripletex.io/v2/customer/88885', + }, + department: { + id: 88885, + url: 'api.tripletex.io/v2/department/88885', + }, + isInactive: false, + }, + ], + }); + const entries = await client.list(); + + parseRuntypeValidationError(entries.error); + invariant(entries.success); + expect(entries.body.values).toMatchInlineSnapshot(` +Array [ + Object { + "customer": Object { + "id": 88885, + "url": "api.tripletex.io/v2/customer/88885", + }, + "department": Object { + "id": 88885, + "url": "api.tripletex.io/v2/department/88885", + }, + "displayName": "Simen A. W. Olsen API Testuser", + "email": "an@email.co.uk", + "firstName": "Simen A. W. Olsen", + "id": 1734852, + "isInactive": false, + "lastName": "API Testuser", + "phoneNumberMobile": "", + "phoneNumberMobileCountry": Object { + "id": 161, + "url": "api.tripletex.io/v2/country/161", + }, + "phoneNumberWork": "", + "url": "api.tripletex.io/v2/contact/1734852", + "version": 1, + }, +] +`); + }); +}); diff --git a/src/calls/contact/contact.ts b/src/calls/contact/contact.ts new file mode 100644 index 0000000..835ba1f --- /dev/null +++ b/src/calls/contact/contact.ts @@ -0,0 +1,77 @@ +import { DefaultTripletexInputs } from "../../types"; +import { serializeQuery, withRuntype } from "../../utils"; +import { TripletexBase } from "../base"; +import { listContactsResponseRt } from "./models/contact"; + +export interface ListContactsInput extends DefaultTripletexInputs { + /** + * List of IDs + */ + id?: string[]; + + /** + * Containing + */ + firstName?: string; + + /** + * Containing + */ + lastName?: string; + + /** + * Containing + */ + email?: string; + + /** + * List of IDs + */ + customerId?: string; + + /** + * List of IDs + */ + departmentId?: string; + + /** + * From index + */ + includeContacts?: boolean; + + /** + * List of IDs + */ + deploymentId?: string[]; + + /** + * Number of elements to return + */ + count: number; + + /** + * Sorting pattern + */ + sorting: string; + + /** + * Fields filter pattern + */ + fields: string; +} + +export class TripletexContact extends TripletexBase { + list(input?: ListContactsInput) { + const call = this.authenticatedCall() // + .args<{ + input?: ListContactsInput; + }>() + .path('/v2/contact') + .query(args => (args.input ? serializeQuery(args.input) : {})) + .method('get') + .parseJson(withRuntype(listContactsResponseRt)) + .build(); + + return this.performRequest(sessionToken => call({ input, sessionToken })); + } +} \ No newline at end of file diff --git a/src/calls/contact/models/contact.ts b/src/calls/contact/models/contact.ts new file mode 100644 index 0000000..e45e6f4 --- /dev/null +++ b/src/calls/contact/models/contact.ts @@ -0,0 +1,34 @@ +import * as rt from 'runtypes'; +import { multipleValuesEnvelope } from '../../../utils'; + +const contactRt = rt.Record({ + id: rt.Number, + version: rt.Number.nullable().optional(), + url: rt.String, + firstName: rt.String, + lastName: rt.String, + displayName: rt.String.nullable().optional(), + email: rt.String.nullable().optional(), + phoneNumberMobileCountry: rt + .Record({ + id: rt.Number, + }) + .nullable() + .optional(), + phoneNumberMobile: rt.String.nullable().optional(), + phoneNumberWork: rt.String.nullable().optional(), + customer: rt.Record({ + id: rt.Number, + url: rt.String, + }), + department: rt.Record({ + id: rt.Number, + url: rt.String, + }), + isInactive: rt.Boolean.nullable().optional(), +}) + +export type Contact = rt.Static; + + +export const listContactsResponseRt = multipleValuesEnvelope(contactRt); \ No newline at end of file