From 4a3b7941e109518e7a70e5f43e73fa8c3f6fd4d5 Mon Sep 17 00:00:00 2001 From: Antoine SEIN <142824551+asein-sinch@users.noreply.github.com> Date: Fri, 2 Aug 2024 09:48:06 +0200 Subject: [PATCH 1/3] DEVEXP-506: E2E ElasticSipTrunking/CallsHistory --- .../calls-history/find.ts | 2 +- .../src/models/v1/enum.ts | 2 +- .../src/models/v1/money/money.ts | 2 +- .../calls-history-request-data.ts | 22 +++- .../v1/calls-history/calls-history-api.ts | 8 +- .../calls-history/calls-history-api.test.ts | 6 +- .../v1/calls-history/calls-history.steps.ts | 95 ++++++++++++++++ packages/fax/src/rest/v3/faxes/faxes-api.ts | 37 +------ .../fax/tests/rest/v3/faxes/faxes-api.test.ts | 78 +------------ .../src/client/api-client-helpers.ts | 4 +- packages/sdk-client/src/utils/date.ts | 29 +++++ packages/sdk-client/tests/utils/date.test.ts | 103 ++++++++++++++++++ 12 files changed, 268 insertions(+), 120 deletions(-) create mode 100644 packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history.steps.ts create mode 100644 packages/sdk-client/tests/utils/date.test.ts diff --git a/examples/simple-examples/src/elastic-sip-trunking/calls-history/find.ts b/examples/simple-examples/src/elastic-sip-trunking/calls-history/find.ts index 10dcddfe..18e21eef 100644 --- a/examples/simple-examples/src/elastic-sip-trunking/calls-history/find.ts +++ b/examples/simple-examples/src/elastic-sip-trunking/calls-history/find.ts @@ -27,7 +27,7 @@ const populateCallsList = ( const requestData: ElasticSipTrunking.FindCallsRequestData = { trunkId, callResult: 'COMPLETED', - direction: 'INBOUND', + direction: 'inbound', }; const elasticSipTrunkingService = initElasticSipTrunkingService(); diff --git a/packages/elastic-sip-trunking/src/models/v1/enum.ts b/packages/elastic-sip-trunking/src/models/v1/enum.ts index 312f600f..e9f9a547 100644 --- a/packages/elastic-sip-trunking/src/models/v1/enum.ts +++ b/packages/elastic-sip-trunking/src/models/v1/enum.ts @@ -1,3 +1,3 @@ -export type DirectionEnum = 'INBOUND' | 'OUTBOUND'; +export type DirectionEnum = 'inbound' | 'outbound'; export type CallResult = 'COMPLETED' | 'NO_ANSWER' | 'CANCEL' | 'BUSY' | 'FAILED'; diff --git a/packages/elastic-sip-trunking/src/models/v1/money/money.ts b/packages/elastic-sip-trunking/src/models/v1/money/money.ts index bc45fbfb..6b555751 100644 --- a/packages/elastic-sip-trunking/src/models/v1/money/money.ts +++ b/packages/elastic-sip-trunking/src/models/v1/money/money.ts @@ -5,5 +5,5 @@ export interface Money { /** The 3-letter currency code defined in ISO 4217. */ currencyCode?: string; /** The amount with 4 decimals and decimal delimiter `.`. */ - amount?: string; + amount?: number; } diff --git a/packages/elastic-sip-trunking/src/models/v1/requests/calls-history/calls-history-request-data.ts b/packages/elastic-sip-trunking/src/models/v1/requests/calls-history/calls-history-request-data.ts index f22dc84a..c0faad56 100644 --- a/packages/elastic-sip-trunking/src/models/v1/requests/calls-history/calls-history-request-data.ts +++ b/packages/elastic-sip-trunking/src/models/v1/requests/calls-history/calls-history-request-data.ts @@ -1,4 +1,5 @@ import { CallResult, DirectionEnum } from '../../enum'; +import { DateFormat } from '@sinch/sdk-client'; export interface FindCallsRequestData { /** A phone number that you want to use to filter results. You can pass a partial number to get all calls sent to numbers that start with the number you passed. */ @@ -7,8 +8,10 @@ export interface FindCallsRequestData { 'to'?: string; /** Only include calls made from this trunk. */ 'trunkId'?: string; - /** Filter calls based on `createTime`. You make the query more precise, fewer results will be returned. For example, 2021-02-01 will return all calls from the first of February 2021, and 2021-02-01T14:00:00Z will return all calls after 14:00 on the first of February. This field also supports <= and >= to search for calls in a range ?createTime>=2021-10-01&createTime<=2021-10-30 to get a list if calls for october 2021 It is also possible to submit partial dates for example createTime=2021-02 will return all calls for February ***Defaults to 24 hours*** ***Internal notes*** If a customer submits = and not <> we should add min and max for the date range psueodo sql ``` createTime = 2021-02-01 select * from calls where createTime >= 2021-02-01 and createTime <= 2021-02-01T23:59:59Z createTime = 2021-02-01T08 select * from calls where createTime >= 2021-02-01T08:00:00 and createTime <= 2021-02-01T08:59:59Z ``` but if they submit < or > we should just use the value they submitted and parse it a complete date */ + /** Filter calls based on `createTime`. You make the query more precise, fewer results will be returned. For example, 2021-02-01 will return all calls from the first of February 2021, and 2021-02-01T14:00:00Z will return all calls after 14:00 on the first of February. */ 'createTime'?: string; + /** Filter calls based on `createTime`. It will filter the calls on a range of dates. */ + 'createTimeRange'?: DateRangeFilter; /** only include calls by on the callResult(s), example callResult=COMPLETED will return all calls which have completed normally. */ 'callResult'?: CallResult; /** only include calls by on the direction(s), example direction=INBOUND,OUTBOUND will return all calls that are inbound or outbound. */ @@ -18,3 +21,20 @@ export interface FindCallsRequestData { /** The maximum number of items to return per request. The default is 100 and the maximum is 1000. If you need to export larger amounts and pagination is not suitable for you can use the Export function in the dashboard. */ 'pageSize'?: number; } + +/** + * Filter calls based on `createTime`. If not value is submitted, the default value is the prior week. + * - `from: '2024-02-15'` will return all calls from February 2024, 15th + * - `from: '2024-02-01T14:00:00Z'` will return all calls after 14:00:00 on the first of February 2024. + * - `from: '2024-02-01T14:00:00Z'` + `to: '2024-02-01T15:00:00Z'` will return all calls between 14:00:00 and 15:00:00 (inclusive) on the first of February 2024. + * - `from: '2024-02-01'` + `to: '2024-02-29'` will return all calls for all of February 2024. + * + * Note: It is also possible to submit partial dates. + * - `from: '2024-02'` will return all calls for February 2024 + */ +export interface DateRangeFilter { + /** */ + from?: string | Date | DateFormat; + /** */ + to?: string | Date | DateFormat; +} diff --git a/packages/elastic-sip-trunking/src/rest/v1/calls-history/calls-history-api.ts b/packages/elastic-sip-trunking/src/rest/v1/calls-history/calls-history-api.ts index 6c42951b..81a58167 100644 --- a/packages/elastic-sip-trunking/src/rest/v1/calls-history/calls-history-api.ts +++ b/packages/elastic-sip-trunking/src/rest/v1/calls-history/calls-history-api.ts @@ -7,6 +7,8 @@ import { PaginationEnum, buildPageResultPromise, createIteratorMethodsForPagination, + formatCreateTimeFilter, + formatCreateTimeRangeFilter, } from '@sinch/sdk-client'; import { ElasticSipTrunkingDomainApi } from '../elastic-sip-trunking-domain-api'; @@ -22,16 +24,18 @@ export class CallsHistoryApi extends ElasticSipTrunkingDomainApi { } /** - * Find calls * Find calls by query parameters. * @param { FindCallsRequestData } data - The data to provide to the API call. * @return { ApiListPromise } */ public find(data: FindCallsRequestData): ApiListPromise { this.client = this.getSinchClient(); - data['createTime'] = data['createTime'] !== undefined ? data['createTime'] : 'now-24h'; const getParams = this.client.extractQueryParams(data, [ 'from', 'to', 'trunkId', 'createTime', 'callResult', 'direction', 'page', 'pageSize']); + (getParams as any).createTime = JSON.stringify(formatCreateTimeFilter(data.createTime)); + (getParams as any)['createTime>'] = JSON.stringify(formatCreateTimeRangeFilter(data.createTimeRange?.from)); + (getParams as any)['createTime<'] = JSON.stringify(formatCreateTimeRangeFilter(data.createTimeRange?.to)); + const headers: { [key: string]: string | undefined } = { 'Content-Type': 'application/json', 'Accept': 'application/json', diff --git a/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history-api.test.ts b/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history-api.test.ts index 5801b35f..1a839b51 100644 --- a/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history-api.test.ts +++ b/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history-api.test.ts @@ -28,19 +28,19 @@ describe('CallsApi', () => { callId: '01AQ3D80ZKSSK35TZFKM3JG9CT', to: '+15551239898', from: '+14155553434', - direction: 'INBOUND', + direction: 'inbound', answerTime: new Date('2021-11-01T23:26:50Z'), endTime: new Date('2021-11-01T23:27:35Z'), durationSeconds: 45, callResult: 'COMPLETED', pricePerMinute: { currencyCode: 'USD', - amount: '0.0040', + amount: 0.0040, }, billingDurationSeconds: 60, price: { currencyCode: 'USD', - amount: '0.0040', + amount: 0.0040, }, createTime: new Date('2021-11-01T23:20:50Z'), projectId: '1bf62742-7b84-4666-9cbe-8e5734fd57d0', diff --git a/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history.steps.ts b/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history.steps.ts new file mode 100644 index 00000000..8704b398 --- /dev/null +++ b/packages/elastic-sip-trunking/tests/rest/v1/calls-history/calls-history.steps.ts @@ -0,0 +1,95 @@ +import { ElasticSipTrunking, ElasticSipTrunkingService, CallsHistoryApi } from '../../../../src'; +import { Given, Then, When } from '@cucumber/cucumber'; +import assert from 'assert'; +import { PageResult } from '@sinch/sdk-client'; + +let callsHistoryApi: CallsHistoryApi; +let listResponse: PageResult; +let callsHistoryList: ElasticSipTrunking.Call[]; +let pagesIteration: number; + +Given('the Elastic SIP Trunking service "Calls History" is available', function () { + const elasticSipTrunkingService = new ElasticSipTrunkingService({ + projectId: 'tinyfrog-jump-high-over-lilypadbasin', + keyId: 'keyId', + keySecret: 'keySecret', + authHostname: 'http://localhost:3011', + elasticSipTrunkingHostname: 'http://localhost:3016', + }); + callsHistoryApi = elasticSipTrunkingService.calls; +}); + +When('I send a request to find the a page from the Calls History with no filtering parameters', async () => { + listResponse = await callsHistoryApi.find({}); +}); + +Then('the response contains {string} Calls from history', (expectedAnswer: string) => { + const expectedCallsCount = parseInt(expectedAnswer, 10); + assert.equal(listResponse.data.length, expectedCallsCount); +}); + +Then('a Call History object from the page result contains the Call History details', () => { + const call = listResponse.data[0]; + assert.equal(call.callId, 'N00DL3C4T5'); + assert.equal(call.to, '12017777777'); + assert.equal(call.from, 'sip:12015555555@76.184.202.212'); + const direction: ElasticSipTrunking.DirectionEnum = 'outbound'; + assert.equal(call.direction, direction); + assert.deepEqual(call.answerTime, new Date('2024-06-06T16:57:52Z')); + assert.deepEqual(call.endTime, new Date('2024-06-06T16:57:55Z')); + assert.equal(call.durationSeconds, 4); + assert.equal(call.billingDurationSeconds, 60); + const callResult: ElasticSipTrunking.CallResult = 'COMPLETED'; + assert.equal(call.callResult, callResult); + const price: ElasticSipTrunking.Money = { + amount: 0.004, + currencyCode: 'USD', + }; + assert.deepEqual(call.pricePerMinute, price); + assert.deepEqual(call.price, price); + assert.deepEqual(call.createTime, new Date('2024-06-06T16:57:45+0000')); + assert.equal(call.projectId, 'tinyfrog-jump-high-over-lilypadbasin'); + assert.equal(call.trunkId, '01W4FFL35P4NC4K35SIPTRUNK2'); +}); + +When('I send a request to list all the Calls from the Calls History', async () => { + callsHistoryList = []; + for await (const call of callsHistoryApi.find({})) { + callsHistoryList.push(call); + } +}); + +When('I iterate manually over the Calls History pages', async () => { + callsHistoryList = []; + listResponse = await callsHistoryApi.find({}); + callsHistoryList.push(...listResponse.data); + pagesIteration = 1; + let reachedEndOfPages = false; + while (!reachedEndOfPages) { + if (listResponse.hasNextPage) { + listResponse = await listResponse.nextPage(); + callsHistoryList.push(...listResponse.data); + pagesIteration++; + } else { + reachedEndOfPages = true; + } + } +}); + +Then('the Calls History list contains {string} Calls', (expectedAnswer: string) => { + const expectedSipEndpointsCount = parseInt(expectedAnswer, 10); + assert.equal(callsHistoryList.length, expectedSipEndpointsCount); +}); + +Then('the Calls History iteration result contains the data from {string} pages', (expectedAnswer: string) => { + const expectedPagesCount = parseInt(expectedAnswer, 10); + assert.equal(pagesIteration, expectedPagesCount); +}); + +When('I send a request to find the a page from the Calls History with a createTime range filter', async () => { + listResponse = await callsHistoryApi.find({ + createTimeRange: { + from: '2024-06-06T16:00:00', + }, + }); +}); diff --git a/packages/fax/src/rest/v3/faxes/faxes-api.ts b/packages/fax/src/rest/v3/faxes/faxes-api.ts index 26b77b9a..9704fdc8 100644 --- a/packages/fax/src/rest/v3/faxes/faxes-api.ts +++ b/packages/fax/src/rest/v3/faxes/faxes-api.ts @@ -2,9 +2,9 @@ import { ApiListPromise, buildPageResultPromise, createIteratorMethodsForPagination, - DateFormat, FileBuffer, - formatDate, + formatCreateTimeFilter, + formatCreateTimeRangeFilter, PaginatedApiProperties, PaginationEnum, RequestBody, @@ -137,9 +137,9 @@ export class FaxesApi extends FaxDomainApi { 'from', 'pageSize', 'page']); - (getParams as any).createTime = JSON.stringify(this.formatCreateTimeFilter(data.createTime)); - (getParams as any)['createTime>'] = JSON.stringify(this.formatCreateTimeRangeFilter(data.createTimeRange?.from)); - (getParams as any)['createTime<'] = JSON.stringify(this.formatCreateTimeRangeFilter(data.createTimeRange?.to)); + (getParams as any).createTime = JSON.stringify(formatCreateTimeFilter(data.createTime)); + (getParams as any)['createTime>'] = JSON.stringify(formatCreateTimeRangeFilter(data.createTimeRange?.from)); + (getParams as any)['createTime<'] = JSON.stringify(formatCreateTimeRangeFilter(data.createTimeRange?.to)); const headers: { [key: string]: string | undefined } = { 'Content-Type': 'application/json', @@ -174,33 +174,6 @@ export class FaxesApi extends FaxDomainApi { return listPromise as ApiListPromise; } - formatCreateTimeFilter = (createTime: string | Date | undefined): string | undefined => { - if (createTime !== undefined) { - if (typeof createTime === 'string') { - if (createTime.indexOf('T') > -1) { - return createTime.substring(0, createTime.indexOf('T')); - } - return createTime; - } else { - return formatDate(createTime, 'day'); - } - } - return undefined; - }; - - formatCreateTimeRangeFilter = (timeBoundary: string | Date | DateFormat | undefined): string | undefined => { - if (timeBoundary !== undefined) { - if (typeof timeBoundary === 'string') { - return timeBoundary; - } else if (timeBoundary instanceof Date) { - return formatDate(timeBoundary); - } else { - return formatDate(timeBoundary.date, timeBoundary.unit); - } - } - return undefined; - }; - /** * Send a fax or multiple faxes * Create and send one or multiple faxes. Fax content may be supplied via one or more files or URLs of supported filetypes. diff --git a/packages/fax/tests/rest/v3/faxes/faxes-api.test.ts b/packages/fax/tests/rest/v3/faxes/faxes-api.test.ts index f5fc2ac5..8bc2944f 100644 --- a/packages/fax/tests/rest/v3/faxes/faxes-api.test.ts +++ b/packages/fax/tests/rest/v3/faxes/faxes-api.test.ts @@ -1,4 +1,4 @@ -import { DateFormat, FileBuffer, SinchClientParameters } from '@sinch/sdk-client'; +import { FileBuffer, SinchClientParameters } from '@sinch/sdk-client'; import { Fax, FaxesApi, @@ -151,82 +151,6 @@ describe('FaxesApi', () => { expect(response.data).toBeDefined(); expect(fixture.list).toHaveBeenCalledWith(requestData); }); - - it('should format a createTime parameter', () => { - const dateUndefined = undefined; - let formattedDateFilter = faxesApi.formatCreateTimeFilter(dateUndefined); - expect(formattedDateFilter).toBeUndefined(); - - const dateString = '2024-05-01'; - formattedDateFilter = faxesApi.formatCreateTimeFilter(dateString); - expect(formattedDateFilter).toBe('2024-05-01'); - - const dateWithSecondsString ='2024-05-01T13:00:00Z'; - formattedDateFilter = faxesApi.formatCreateTimeFilter(dateWithSecondsString); - expect(formattedDateFilter).toBe('2024-05-01'); - - const dateWithSeconds = new Date('2024-05-01T13:00:00Z'); - formattedDateFilter = faxesApi.formatCreateTimeFilter(dateWithSeconds); - expect(formattedDateFilter).toBe('2024-05-01'); - }); - - it('should format a datetime range filter', () => { - const dateTimeRangeUndefined = undefined; - let formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeUndefined); - expect(formattedDateTimeRangeFilter).toBeUndefined(); - - const dateTimeRangeString = '2024-05-01'; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeString); - expect(formattedDateTimeRangeFilter).toBe('2024-05-01'); - - const dateTimeRangeNoUnit: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeNoUnit); - expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:15:30Z'); - - const dateTimeRangeWithYear: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - unit: 'year', - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeWithYear); - expect(formattedDateTimeRangeFilter).toBe('2024'); - - const dateTimeRangeWithMonth: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - unit: 'month', - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeWithMonth); - expect(formattedDateTimeRangeFilter).toBe('2024-05'); - - const dateTimeRangeWithDay: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - unit: 'day', - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeWithDay); - expect(formattedDateTimeRangeFilter).toBe('2024-05-01'); - - const dateTimeRangeWithHours: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - unit: 'hour', - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeWithHours); - expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:00:00Z'); - - const dateTimeRangeWithMinutes: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - unit: 'minute', - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeWithMinutes); - expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:15:00Z'); - - const dateTimeRangeWithSeconds: DateFormat = { - date: new Date('2024-05-01T13:15:30Z'), - unit: 'second', - }; - formattedDateTimeRangeFilter = faxesApi.formatCreateTimeRangeFilter(dateTimeRangeWithSeconds); - expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:15:30Z'); - }); }); describe ('sendFax', () => { diff --git a/packages/sdk-client/src/client/api-client-helpers.ts b/packages/sdk-client/src/client/api-client-helpers.ts index ee39b98c..4807191a 100644 --- a/packages/sdk-client/src/client/api-client-helpers.ts +++ b/packages/sdk-client/src/client/api-client-helpers.ts @@ -100,8 +100,8 @@ const isDateString = (value: any): boolean => { }; const addTimezoneIfMissing = (timestampValue: string): string => { - // Check the formats +XX:XX, +XX and Z - const timeZoneRegex = /([+-]\d{2}(:\d{2})|Z)$/; + // Check the formats +XX:XX, +XX, +XXXX and Z + const timeZoneRegex = /([+-]\d{2}(:\d{2})|[+-]\d{4}|Z)$/; if (!timeZoneRegex.test(timestampValue)) { const hourMinutesTimezoneRegex = /([+-]\d{2})$/; // A timestamp with no minutes in the timezone cannot be converted into a Date => assume it's :00 diff --git a/packages/sdk-client/src/utils/date.ts b/packages/sdk-client/src/utils/date.ts index c0d9ef0d..8763e791 100644 --- a/packages/sdk-client/src/utils/date.ts +++ b/packages/sdk-client/src/utils/date.ts @@ -29,3 +29,32 @@ export const formatDate = (date: Date, unit?: ChronoUnit): string => { return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}Z`; } }; + +export const formatCreateTimeFilter = (createTime: string | Date | undefined): string | undefined => { + if (createTime !== undefined) { + if (typeof createTime === 'string') { + if (createTime.indexOf('T') > -1) { + return createTime.substring(0, createTime.indexOf('T')); + } + return createTime; + } else { + return formatDate(createTime, 'day'); + } + } + return undefined; +}; + +export const formatCreateTimeRangeFilter = ( + timeBoundary: string | Date | DateFormat | undefined +): string | undefined => { + if (timeBoundary !== undefined) { + if (typeof timeBoundary === 'string') { + return timeBoundary; + } else if (timeBoundary instanceof Date) { + return formatDate(timeBoundary); + } else { + return formatDate(timeBoundary.date, timeBoundary.unit); + } + } + return undefined; +}; diff --git a/packages/sdk-client/tests/utils/date.test.ts b/packages/sdk-client/tests/utils/date.test.ts new file mode 100644 index 00000000..a3e2440c --- /dev/null +++ b/packages/sdk-client/tests/utils/date.test.ts @@ -0,0 +1,103 @@ +import { + DateFormat, + formatDate, + formatCreateTimeFilter, + formatCreateTimeRangeFilter, +} from '../../src'; + +it('should format a date with its required chrono unit', () => { + const date = new Date('2024-05-01T13:20:50Z'); + let formattedDate = formatDate(date, 'year'); + expect(formattedDate).toBe('2024'); + + formattedDate = formatDate(date, 'month'); + expect(formattedDate).toBe('2024-05'); + + formattedDate = formatDate(date, 'day'); + expect(formattedDate).toBe('2024-05-01'); + + formattedDate = formatDate(date, 'hour'); + expect(formattedDate).toBe('2024-05-01T13:00:00Z'); + + formattedDate = formatDate(date, 'minute'); + expect(formattedDate).toBe('2024-05-01T13:20:00Z'); + + formattedDate = formatDate(date, 'second'); + expect(formattedDate).toBe('2024-05-01T13:20:50Z'); +}); + +it('should format a dateTime filter parameter', () => { + const dateUndefined = undefined; + let formattedDateFilter = formatCreateTimeFilter(dateUndefined); + expect(formattedDateFilter).toBeUndefined(); + + const dateString = '2024-05-01'; + formattedDateFilter = formatCreateTimeFilter(dateString); + expect(formattedDateFilter).toBe('2024-05-01'); + + const dateWithSecondsString ='2024-05-01T13:00:00Z'; + formattedDateFilter = formatCreateTimeFilter(dateWithSecondsString); + expect(formattedDateFilter).toBe('2024-05-01'); + + const dateWithSeconds = new Date('2024-05-01T13:00:00Z'); + formattedDateFilter = formatCreateTimeFilter(dateWithSeconds); + expect(formattedDateFilter).toBe('2024-05-01'); +}); + +it('should format a datetime range filter parameter', () => { + const dateTimeRangeUndefined = undefined; + let formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeUndefined); + expect(formattedDateTimeRangeFilter).toBeUndefined(); + + const dateTimeRangeString = '2024-05-01'; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeString); + expect(formattedDateTimeRangeFilter).toBe('2024-05-01'); + + const dateTimeRangeNoUnit: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeNoUnit); + expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:15:30Z'); + + const dateTimeRangeWithYear: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + unit: 'year', + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeWithYear); + expect(formattedDateTimeRangeFilter).toBe('2024'); + + const dateTimeRangeWithMonth: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + unit: 'month', + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeWithMonth); + expect(formattedDateTimeRangeFilter).toBe('2024-05'); + + const dateTimeRangeWithDay: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + unit: 'day', + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeWithDay); + expect(formattedDateTimeRangeFilter).toBe('2024-05-01'); + + const dateTimeRangeWithHours: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + unit: 'hour', + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeWithHours); + expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:00:00Z'); + + const dateTimeRangeWithMinutes: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + unit: 'minute', + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeWithMinutes); + expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:15:00Z'); + + const dateTimeRangeWithSeconds: DateFormat = { + date: new Date('2024-05-01T13:15:30Z'), + unit: 'second', + }; + formattedDateTimeRangeFilter = formatCreateTimeRangeFilter(dateTimeRangeWithSeconds); + expect(formattedDateTimeRangeFilter).toBe('2024-05-01T13:15:30Z'); +}); From 89d3d4a76d45d2a76535f4e103dd986a7a6117b7 Mon Sep 17 00:00:00 2001 From: Antoine SEIN <142824551+asein-sinch@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:09:43 +0200 Subject: [PATCH 2/3] Fix linter --- packages/conversation/tests/rest/v1/events/events.steps.ts | 2 +- packages/sdk-client/src/utils/date.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/conversation/tests/rest/v1/events/events.steps.ts b/packages/conversation/tests/rest/v1/events/events.steps.ts index 16693d77..5dc7f883 100644 --- a/packages/conversation/tests/rest/v1/events/events.steps.ts +++ b/packages/conversation/tests/rest/v1/events/events.steps.ts @@ -108,7 +108,7 @@ Then('the response contains the conversation event details', () => { }; assert.deepEqual(event.channel_identity, channelIdentity); const composingEvent: Conversation.ComposingEvent = { - composing_event: {} + composing_event: {}, }; assert.deepEqual(event.app_event, composingEvent); }); diff --git a/packages/sdk-client/src/utils/date.ts b/packages/sdk-client/src/utils/date.ts index 8763e791..892bb65c 100644 --- a/packages/sdk-client/src/utils/date.ts +++ b/packages/sdk-client/src/utils/date.ts @@ -45,7 +45,7 @@ export const formatCreateTimeFilter = (createTime: string | Date | undefined): s }; export const formatCreateTimeRangeFilter = ( - timeBoundary: string | Date | DateFormat | undefined + timeBoundary: string | Date | DateFormat | undefined, ): string | undefined => { if (timeBoundary !== undefined) { if (typeof timeBoundary === 'string') { From d6471febb674964037a613bc243b265a39ff21b1 Mon Sep 17 00:00:00 2001 From: Antoine SEIN <142824551+asein-sinch@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:16:41 +0200 Subject: [PATCH 3/3] Install docker compose during CI --- .github/workflows/run-ci.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/run-ci.yaml b/.github/workflows/run-ci.yaml index d6877f13..ab1da6a7 100644 --- a/.github/workflows/run-ci.yaml +++ b/.github/workflows/run-ci.yaml @@ -36,6 +36,10 @@ jobs: run: | cd sinch-sdk-mockserver docker build -t sinch-sdk-mockserver -f Dockerfile . + - name: Install Docker Compose + run: | + sudo apt-get update + sudo apt-get install -y docker-compose - name: Start mock servers with Docker Compose run: | cd sinch-sdk-mockserver