diff --git a/src/App.vue b/src/App.vue index 0f7e68255..1049eee73 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,6 +5,7 @@ import { useAccountStore } from '@/stores/account' import { storeToRefs } from 'pinia' import { themeSelect } from '@/helpers' + import '@modules/real-time-metrics/helpers/convert-date' import '@/helpers/store-handler' /** @type {import('@/plugins/analytics/AnalyticsTrackerAdapter').AnalyticsTrackerAdapter} */ const tracker = inject('tracker') diff --git a/src/helpers/convert-date.js b/src/helpers/convert-date.js index 4063a3c57..6bd132fd6 100644 --- a/src/helpers/convert-date.js +++ b/src/helpers/convert-date.js @@ -1,4 +1,5 @@ -const HOURS_TO_MSEC = 3_600_000 +const MINUTE_IN_MILLISECONDS = 60_000 +const HOUR_IN_MILLISECONDS = 3_600_000 /** * Converts a given value to a date string in a specific format. @@ -19,22 +20,6 @@ const convertValueToDate = (value) => { return date.toLocaleString('en-US', options) } -/** - * Remove the specified amount of hours from the given date - * - * @param {number} pOffset - The number of hours to remove - * @param {Date} pDate - The date from which to remove the hours - * @returns {Date} The new date after removing the specified hours - */ -function removeSelectedAmountOfHours(pOffset, pDate) { - const offset = Number(pOffset) - const offsetTimestamp = offset * HOURS_TO_MSEC - const calculatedTimestamp = pDate.getTime() - offsetTimestamp - const calculatedDate = new Date(calculatedTimestamp) - - return calculatedDate -} - /** * Formats a given date to ISO format without milliseconds. * @@ -68,88 +53,20 @@ const convertOffsetToDecimal = (offset) => { return `${offsetSign}${hours}.${decimalMinutes}` } -export { - removeSelectedAmountOfHours, - formatToEndOfDayIsoDate, - convertOffsetToDecimal, - convertValueToDate -} - -/** - * Set the current date to UTC0 and remove Timezone tag - * - * @returns {string} Date without timezone - */ -Date.prototype.removeZone = function () { - const dateWithUserTimezone = this.toISOString() - const dateWithoutZone = dateWithUserTimezone.replace(/(\..+)/, '') - return dateWithoutZone -} - -/** - * Convert current date to the UTC informed - * - * @param {number} userUTC - The UTC offset to convert the date to - * @returns {Date} The new date converted to the specified UTC - */ -Date.prototype.toUTC = function (userUTC = 0) { - const tz = Number(userUTC) - const tzTimeStamp = (tz / 100) * HOURS_TO_MSEC - const dateWithUserTimezone = new Date(this.getTime() + tzTimeStamp) - const dateWithoutZone = dateWithUserTimezone.toBeholderFormat() - return new Date(dateWithoutZone) -} - -/** - * Reset the current date according to the specified UTC offset - * - * @param {number} userUTC - The UTC offset to reset the date to - * @returns {Date} The new date reset to the specified UTC - */ -Date.prototype.resetUTC = function (userUTC = 0) { - const regexpChangeUTC = /(.+)([+|-]\d+)(.+)/g - const injectUserUTC = this.toString().replace(regexpChangeUTC, `$1${userUTC}$3`) - - return new Date(injectUserUTC) -} - -/** - * Format date as the Beholder standard - * - * @returns {string} Date in Beholder format - */ -Date.prototype.toBeholderFormat = function () { - return this.toISOString().replace(/(\..+)/, '') -} - -/** - * Convert the date from the local format to the Beholder format - * - * @returns {string} Date in Beholder format - */ -Date.prototype.fromLocaletoBeholderFormat = function () { - const toLocale = this.toLocaleString('en-GB') - const parts = toLocale.split(/\/|, /) - const day = parts[0] - const month = parts[1] - const year = parts[2] - const time = parts[3] - - return `${year}-${month}-${day}T${time}` -} - /** * Converts the instance of Date to the local timezone based on the provided UTC offset. * * @param {string} utcOffset - The UTC offset for the desired timezone. * @returns {string} The date converted to the local timezone in ISO format. */ -Date.prototype.convertDateToLocalTimezone = function (utcOffset) { +const convertDateToLocalTimezone = (date, utcOffset) => { const userOffset = convertOffsetToDecimal(utcOffset) - const timeZoneOffsetMinutesToMilli = this.getTimezoneOffset() * 60000 - const toUTC = this.getTime() + timeZoneOffsetMinutesToMilli - const offsetHoursToMilli = userOffset * 3600000 + const timeZoneOffsetMinutesToMilli = date.getTimezoneOffset() * MINUTE_IN_MILLISECONDS + const toUTC = date.getTime() + timeZoneOffsetMinutesToMilli + const offsetHoursToMilli = userOffset * HOUR_IN_MILLISECONDS const userRealDate = new Date(toUTC + offsetHoursToMilli) return formatToEndOfDayIsoDate(userRealDate) } + +export { convertValueToDate, convertDateToLocalTimezone } diff --git a/src/helpers/index.js b/src/helpers/index.js index 06522039f..421011b16 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -17,6 +17,7 @@ import InviteSession from './invite-session' import { metricsPlaygroundOpener } from './metrics-playground-opener' import { parseCamelToSnake, parseSnakeToCamel } from './parse-api-body' import { themeSelect } from './theme-select' +import { convertValueToDate, convertDateToLocalTimezone } from './convert-date' export { InviteSession, @@ -37,5 +38,7 @@ export { openSearchResult, parseCamelToSnake, parseSnakeToCamel, - themeSelect + themeSelect, + convertValueToDate, + convertDateToLocalTimezone } diff --git a/src/modules/real-time-metrics/constants/time-intervals.js b/src/modules/real-time-metrics/constants/time-intervals.js index 894600952..24fd3f0d8 100644 --- a/src/modules/real-time-metrics/constants/time-intervals.js +++ b/src/modules/real-time-metrics/constants/time-intervals.js @@ -46,7 +46,8 @@ const RESAMPLING_INTERVALS = { const TIME_INTERVALS = { DATE_TIME_FILTER_INTERVALS, - RESAMPLING_INTERVALS + RESAMPLING_INTERVALS, + HOUR_IN_MILLISECONDS } export default TIME_INTERVALS diff --git a/src/modules/real-time-metrics/helpers/convert-date.js b/src/modules/real-time-metrics/helpers/convert-date.js new file mode 100644 index 000000000..178a1f408 --- /dev/null +++ b/src/modules/real-time-metrics/helpers/convert-date.js @@ -0,0 +1,76 @@ +import { TIME_INTERVALS } from '@modules/real-time-metrics/constants' + +/** + * Remove the specified amount of hours from the given date + * + * @param {number} pOffset - The number of hours to remove + * @returns {Date} The new date after removing the specified hours + */ +Date.prototype.removeSelectedAmountOfHours = function (pOffset) { + const offset = Number(pOffset) + const offsetTimestamp = offset * TIME_INTERVALS.HOUR_IN_MILLISECONDS + const calculatedTimestamp = this.getTime() - offsetTimestamp + const calculatedDate = new Date(calculatedTimestamp) + + return calculatedDate +} + +/** + * Set the current date to UTC0 and remove Timezone tag + * + * @returns {string} Date without timezone + */ +Date.prototype.removeZone = function () { + const dateWithUserTimezone = this.toISOString() + const dateWithoutZone = dateWithUserTimezone.replace(/(\..+)/, '') + return dateWithoutZone +} + +/** + * Convert current date to the UTC informed + * + * @param {number} userUTC - The UTC offset to convert the date to + * @returns {Date} The new date converted to the specified UTC + */ +Date.prototype.toUTC = function (userUTC = 0) { + const tz = Number(userUTC) + const tzTimeStamp = (tz / 100) * TIME_INTERVALS.HOUR_IN_MILLISECONDS + const dateWithUserTimezone = new Date(this.getTime() + tzTimeStamp) + const dateWithoutZone = dateWithUserTimezone.toBeholderFormat() + return new Date(dateWithoutZone) +} + +/** + * Reset the current date according to the specified UTC offset + * + * @param {number} userUTC - The UTC offset to reset the date to + * @returns {Date} The new date reset to the specified UTC + */ +Date.prototype.resetUTC = function (userUTC = 0) { + const regexpChangeUTC = /(.+)([+|-]\d+)(.+)/g + const injectUserUTC = this.toString().replace(regexpChangeUTC, `$1${userUTC}$3`) + + return new Date(injectUserUTC) +} + +/** + * Format date as the Beholder standard + * + * @returns {string} Date in Beholder format + */ +Date.prototype.toBeholderFormat = function () { + return this.toISOString().replace(/(\..+)/, '') +} + +/** + * Convert the date from the local format to the Beholder format + * + * @returns {string} Date in Beholder format + */ +Date.prototype.fromLocaletoBeholderFormat = function () { + const toLocale = this.toLocaleString('en-GB') + const parts = toLocale.split(/\/|, /) + const [day, month, year, time] = parts + + return `${year}-${month}-${day}T${time}` +} diff --git a/src/router/routes/personal-tokens-routes/index.js b/src/router/routes/personal-tokens-routes/index.js index 5d1fc90f4..5e3f94f3d 100644 --- a/src/router/routes/personal-tokens-routes/index.js +++ b/src/router/routes/personal-tokens-routes/index.js @@ -30,7 +30,8 @@ export const personalTokensRoutes = { component: () => import('@views/PersonalTokens/CreateView.vue'), props: { createPersonalTokenService: PersonalTokensService.createPersonalToken, - clipboardWrite: Helpers.clipboardWrite + clipboardWrite: Helpers.clipboardWrite, + convertDateToLocalTimezone: Helpers.convertDateToLocalTimezone }, meta: { breadCrumbs: [ diff --git a/src/tests/helpers/convert-date.test.js b/src/tests/helpers/convert-date.test.js index 4093b2c29..e8844f897 100644 --- a/src/tests/helpers/convert-date.test.js +++ b/src/tests/helpers/convert-date.test.js @@ -1,79 +1,21 @@ -import { describe, expect, it } from 'vitest' -import '@/helpers/convert-date' -import { - removeSelectedAmountOfHours, - formatToEndOfDayIsoDate, - convertOffsetToDecimal -} from '@/helpers/convert-date' +import { describe, it, expect } from 'vitest' +import { convertValueToDate, convertDateToLocalTimezone } from '@/helpers/convert-date' describe('convertDate', () => { - describe('removeSelectedAmountOfHours', () => { - it('should remove the specified amount of hours from a date', () => { - const date = new Date('2022-01-01T05:00:00Z') - const hoursToRemove = 2 - const expectedDate = new Date('2022-01-01T03:00:00Z') + it('should convert a given value to a date string in a specific format', () => { + const value = '2022-01-01T00:00:00' + const expectedDate = 'January 1, 2022 at 12:00 AM' - expect(removeSelectedAmountOfHours(hoursToRemove, date)).toEqual(expectedDate) - }) + expect(convertValueToDate(value)).toBe(expectedDate) }) - describe('formatToEndOfDayIsoDate', () => { - it('should format a date to ISO format without milliseconds', () => { - const date = new Date('2022-01-01T23:59:59.999Z') - const expectedFormattedDate = '2022-01-01T23:59:59' + it('should convert a date to the local timezone', () => { + const utcOffset = '+0300' + const dateInUtcFormat = new Date('2022-01-01T00:00:00Z') - expect(formatToEndOfDayIsoDate(date)).toBe(expectedFormattedDate) - }) - }) - - describe('convertOffsetToDecimal', () => { - it('should convert a UTC offset to decimal format', () => { - const offset = '+0300' - const expectedDecimal = '+03.00' - - expect(convertOffsetToDecimal(offset)).toBe(expectedDecimal) - }) - }) - - describe('Date.prototype methods', () => { - it('should convert date to UTC based on user offset', () => { - const date = new Date('2022-01-01T00:00:00Z') - const expectedDate = new Date('2022-01-01T00:00:00.000Z') - - expect(date.toUTC(0)).toEqual(expectedDate) - }) - - it('should reset date to specified UTC offset', () => { - const date = new Date('2022-01-01T00:00:00Z') - const userUTC = '+0200' - const expectedDate = new Date('2021-12-31T22:00:00Z') - - expect(date.resetUTC(userUTC)).toEqual(expectedDate) - }) - - it('should format date to Beholder format', () => { - const date = new Date('2022-01-01T00:00:00.000Z') - const expectedFormattedDate = '2022-01-01T00:00:00' - - expect(date.toBeholderFormat()).toBe(expectedFormattedDate) - }) - - it('should convert local date to Beholder format', () => { - const date = new Date('2022-01-01T00:00:00') - date.toLocaleString = () => '01/01/2022, 00:00:00' - const expectedFormattedDate = '2022-01-01T00:00:00' - - expect(date.fromLocaletoBeholderFormat()).toBe(expectedFormattedDate) - }) - - it('should convert a date to the local timezone', () => { - const utcOffset = '+0200' - const dateInUtcFormat = new Date('2022-01-01T00:00:00Z') - - const convertedDate = dateInUtcFormat.convertDateToLocalTimezone(utcOffset) - const expectedDate = '2022-01-01T23:59:59' + const convertedDate = convertDateToLocalTimezone(dateInUtcFormat, utcOffset) + const expectedDate = '2022-01-01T23:59:59' - expect(convertedDate).toBe(expectedDate) - }) + expect(convertedDate).toBe(expectedDate) }) }) diff --git a/src/tests/modules/real-time-metrics/helpers/convert-date.test.js b/src/tests/modules/real-time-metrics/helpers/convert-date.test.js new file mode 100644 index 000000000..771bd1247 --- /dev/null +++ b/src/tests/modules/real-time-metrics/helpers/convert-date.test.js @@ -0,0 +1,63 @@ +import { describe, expect, it } from 'vitest' +import '@modules/real-time-metrics/helpers/convert-date' + +describe('Date.prototype', () => { + it('should contain added prototype methods', () => { + const addedMethods = [ + 'removeSelectedAmountOfHours', + 'removeZone', + 'toUTC', + 'resetUTC', + 'toBeholderFormat', + 'fromLocaletoBeholderFormat' + ] + + const prototypeMethods = Object.keys(Date.prototype) + + expect(addedMethods).toEqual(prototypeMethods) + }) + + it('should remove the specified amount of hours from a date', () => { + const date = new Date('2022-01-01T05:00:00Z') + const hoursToRemove = 2 + const expectedDate = new Date('2022-01-01T03:00:00Z') + + expect(date.removeSelectedAmountOfHours(hoursToRemove)).toEqual(expectedDate) + }) + + it('should set the current date to UTC0 and remove Timezone tag', () => { + const date = new Date('2022-01-01T00:00:00Z') + const expectedDate = '2022-01-01T00:00:00' + + expect(date.removeZone()).toBe(expectedDate) + }) + + it('should convert date to UTC based on user offset', () => { + const date = new Date('2022-01-01T00:00:00Z') + const expectedDate = new Date('2022-01-01T00:03:00.000Z') + + expect(date.toUTC(5)).toEqual(expectedDate) + }) + + it('should reset date to specified UTC offset', () => { + const date = new Date('2022-01-01T00:00:00Z') + const userUTC = '+0200' + const expectedDate = new Date('2021-12-31T22:00:00Z') + + expect(date.resetUTC(userUTC)).toEqual(expectedDate) + }) + + it('should format date to Beholder format', () => { + const date = new Date('2022-01-01T00:00:00.000Z') + const expectedFormattedDate = '2022-01-01T00:00:00' + + expect(date.toBeholderFormat()).toBe(expectedFormattedDate) + }) + + it('should convert local date to Beholder format', () => { + const date = new Date('2022-01-01T00:00:00') + const expectedFormattedDate = '2022-01-01T00:00:00' + + expect(date.fromLocaletoBeholderFormat()).toBe(expectedFormattedDate) + }) +}) diff --git a/src/tests/services/real-time-metrics-services/make-domains-base-url.test.js b/src/tests/services/real-time-metrics-services/make-domains-base-url.test.js new file mode 100644 index 000000000..4417fb597 --- /dev/null +++ b/src/tests/services/real-time-metrics-services/make-domains-base-url.test.js @@ -0,0 +1,22 @@ +import { makeDomainsBaseUrl } from '@/services/real-time-metrics-services/make-domains-base-url' +import { expect, describe, it } from 'vitest' + +const makeSut = () => { + const sut = makeDomainsBaseUrl + + return { + sut + } +} + +describe('RealTimeMetricsServices', () => { + it('should return the API base url to domains service', () => { + const { sut } = makeSut() + const version = 'v3' + const correctApiUrl = `${version}/domains` + + const baseUrl = sut() + + expect(baseUrl).toEqual(correctApiUrl) + }) +}) diff --git a/src/tests/services/real-time-metrics-services/make-edge-dns-base-url.test.js b/src/tests/services/real-time-metrics-services/make-edge-dns-base-url.test.js new file mode 100644 index 000000000..8af8288c3 --- /dev/null +++ b/src/tests/services/real-time-metrics-services/make-edge-dns-base-url.test.js @@ -0,0 +1,22 @@ +import { makeEdgeDNSBaseUrl } from '@/services/real-time-metrics-services/make-edge-dns-base-url' +import { expect, describe, it } from 'vitest' + +const makeSut = () => { + const sut = makeEdgeDNSBaseUrl + + return { + sut + } +} + +describe('RealTimeMetricsServices', () => { + it('should return the API base url to domains service', () => { + const { sut } = makeSut() + const version = 'v3' + const correctApiUrl = `${version}/intelligent_dns` + + const baseUrl = sut() + + expect(baseUrl).toEqual(correctApiUrl) + }) +}) diff --git a/src/tests/services/real-time-metrics-services/make-edge-functions-base-url.test.js b/src/tests/services/real-time-metrics-services/make-edge-functions-base-url.test.js new file mode 100644 index 000000000..244810a0b --- /dev/null +++ b/src/tests/services/real-time-metrics-services/make-edge-functions-base-url.test.js @@ -0,0 +1,22 @@ +import { makeEdgeFunctionsBaseUrl } from '@/services/real-time-metrics-services/make-edge-functions-base-url' +import { expect, describe, it } from 'vitest' + +const makeSut = () => { + const sut = makeEdgeFunctionsBaseUrl + + return { + sut + } +} + +describe('RealTimeMetricsServices', () => { + it('should return the API base url to domains service', () => { + const { sut } = makeSut() + const version = 'v3' + const correctApiUrl = `${version}/edge_functions` + + const baseUrl = sut() + + expect(baseUrl).toEqual(correctApiUrl) + }) +}) diff --git a/src/tests/services/real-time-metrics-services/search-domains-service.test.js b/src/tests/services/real-time-metrics-services/search-domains-service.test.js new file mode 100644 index 000000000..c0de4b76c --- /dev/null +++ b/src/tests/services/real-time-metrics-services/search-domains-service.test.js @@ -0,0 +1,87 @@ +import { AxiosHttpClientAdapter } from '@/services/axios/AxiosHttpClientAdapter' +import { searchDomainsService } from '@/services/real-time-metrics-services' +import { describe, expect, it, vi } from 'vitest' +import * as Errors from '@services/axios/errors' + +const makeSut = () => { + const sut = searchDomainsService + + return { + sut + } +} + +describe('RealTimeMetricsServices', () => { + it('should call api with correct params', async () => { + const requestSpy = vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode: 200, + body: { results: [] } + }) + + const { sut } = makeSut() + const version = 'v3' + await sut({}) + + expect(requestSpy).toHaveBeenCalledWith({ + url: `${version}/domains?order_by=name&sort=asc&page=1&page_size=200`, + method: 'GET', + cancelToken: expect.anything() + }) + }) + + it('should return a list of domains', async () => { + vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode: 200, + body: { + results: [ + { id: 1, name: 'test' }, + { id: 2, name: 'test2' } + ] + } + }) + + const { sut } = makeSut() + const results = await sut({}) + + expect(results).toEqual([ + { value: 1, label: 'test' }, + { value: 2, label: 'test2' } + ]) + }) + + it.each([ + { + statusCode: 400, + expectedError: new Errors.InvalidApiRequestError().message + }, + { + statusCode: 403, + expectedError: new Errors.PermissionError().message + }, + { + statusCode: 404, + expectedError: new Errors.NotFoundError().message + }, + { + statusCode: 500, + expectedError: new Errors.InternalServerError().message + }, + { + statusCode: 'unmappedStatusCode', + expectedError: new Errors.UnexpectedError().message + } + ])( + 'should throw when request fails with statusCode $statusCode', + async ({ statusCode, expectedError }) => { + vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode, + body: [] + }) + const { sut } = makeSut() + + const response = sut({}) + + expect(response).rejects.toBe(expectedError) + } + ) +}) diff --git a/src/tests/services/real-time-metrics-services/search-edge-dns-service.test.js b/src/tests/services/real-time-metrics-services/search-edge-dns-service.test.js new file mode 100644 index 000000000..0aae1c372 --- /dev/null +++ b/src/tests/services/real-time-metrics-services/search-edge-dns-service.test.js @@ -0,0 +1,87 @@ +import { AxiosHttpClientAdapter } from '@/services/axios/AxiosHttpClientAdapter' +import { searchEdgeDnsService } from '@/services/real-time-metrics-services' +import { describe, expect, it, vi } from 'vitest' +import * as Errors from '@services/axios/errors' + +const makeSut = () => { + const sut = searchEdgeDnsService + + return { + sut + } +} + +describe('RealTimeMetricsServices', () => { + it('should call api with correct params', async () => { + const requestSpy = vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode: 200, + body: { results: [] } + }) + + const { sut } = makeSut() + const version = 'v3' + await sut({}) + + expect(requestSpy).toHaveBeenCalledWith({ + url: `${version}/intelligent_dns?order_by=name&sort=asc&page=1&page_size=200`, + method: 'GET', + cancelToken: expect.anything() + }) + }) + + it('should return a list of edge dns', async () => { + vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode: 200, + body: { + results: [ + { id: 1, name: 'test' }, + { id: 2, name: 'test2' } + ] + } + }) + + const { sut } = makeSut() + const results = await sut({}) + + expect(results).toEqual([ + { value: 1, label: 'test' }, + { value: 2, label: 'test2' } + ]) + }) + + it.each([ + { + statusCode: 400, + expectedError: new Errors.InvalidApiRequestError().message + }, + { + statusCode: 403, + expectedError: new Errors.PermissionError().message + }, + { + statusCode: 404, + expectedError: new Errors.NotFoundError().message + }, + { + statusCode: 500, + expectedError: new Errors.InternalServerError().message + }, + { + statusCode: 'unmappedStatusCode', + expectedError: new Errors.UnexpectedError().message + } + ])( + 'should throw when request fails with statusCode $statusCode', + async ({ statusCode, expectedError }) => { + vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode, + body: [] + }) + const { sut } = makeSut() + + const response = sut({}) + + expect(response).rejects.toBe(expectedError) + } + ) +}) diff --git a/src/tests/services/real-time-metrics-services/search-edge-functions-service.test.js b/src/tests/services/real-time-metrics-services/search-edge-functions-service.test.js new file mode 100644 index 000000000..49e93a306 --- /dev/null +++ b/src/tests/services/real-time-metrics-services/search-edge-functions-service.test.js @@ -0,0 +1,87 @@ +import { AxiosHttpClientAdapter } from '@/services/axios/AxiosHttpClientAdapter' +import { searchEdgeFunctionsService } from '@/services/real-time-metrics-services' +import { describe, expect, it, vi } from 'vitest' +import * as Errors from '@services/axios/errors' + +const makeSut = () => { + const sut = searchEdgeFunctionsService + + return { + sut + } +} + +describe('RealTimeMetricsServices', () => { + it('should call api with correct params', async () => { + const requestSpy = vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode: 200, + body: { results: [] } + }) + + const { sut } = makeSut() + const version = 'v3' + await sut({}) + + expect(requestSpy).toHaveBeenCalledWith({ + url: `${version}/edge_functions?order_by=name&sort=asc&page=1&page_size=200`, + method: 'GET', + cancelToken: expect.anything() + }) + }) + + it('should return a list of edge functions', async () => { + vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode: 200, + body: { + results: [ + { id: 1, name: 'test' }, + { id: 2, name: 'test2' } + ] + } + }) + + const { sut } = makeSut() + const results = await sut({}) + + expect(results).toEqual([ + { value: 1, label: 'test' }, + { value: 2, label: 'test2' } + ]) + }) + + it.each([ + { + statusCode: 400, + expectedError: new Errors.InvalidApiRequestError().message + }, + { + statusCode: 403, + expectedError: new Errors.PermissionError().message + }, + { + statusCode: 404, + expectedError: new Errors.NotFoundError().message + }, + { + statusCode: 500, + expectedError: new Errors.InternalServerError().message + }, + { + statusCode: 'unmappedStatusCode', + expectedError: new Errors.UnexpectedError().message + } + ])( + 'should throw when request fails with statusCode $statusCode', + async ({ statusCode, expectedError }) => { + vi.spyOn(AxiosHttpClientAdapter, 'request').mockResolvedValueOnce({ + statusCode, + body: [] + }) + const { sut } = makeSut() + + const response = sut({}) + + expect(response).rejects.toBe(expectedError) + } + ) +}) diff --git a/src/views/PersonalTokens/CreateView.vue b/src/views/PersonalTokens/CreateView.vue index bc9315597..04d690249 100644 --- a/src/views/PersonalTokens/CreateView.vue +++ b/src/views/PersonalTokens/CreateView.vue @@ -8,7 +8,6 @@ import PageHeadingBlock from '@/templates/page-heading-block' import FormFieldsPersonalToken from '@/views/PersonalTokens/FormFields/FormFieldsPersonalToken' import CopyTokenDialog from '@/views/PersonalTokens/Dialog/CopyTokenDialog' - import '@/helpers/convert-date' import { useAccountStore } from '@/stores/account' import { storeToRefs } from 'pinia' import * as yup from 'yup' @@ -22,6 +21,10 @@ clipboardWrite: { type: Function, required: true + }, + convertDateToLocalTimezone: { + type: Function, + required: true } }) @@ -50,7 +53,7 @@ const tomorrow = new Date(today) const userUtcOffset = account.value.utc_offset - return tomorrow.convertDateToLocalTimezone(userUtcOffset) + return props.convertDateToLocalTimezone(tomorrow, userUtcOffset) } const initialValues = { @@ -108,6 +111,7 @@ :personalTokenKey="personalTokenKey" :copyPersonalToken="copyPersonalToken" :userUtcOffset="account?.utc_offset" + :convertDateToLocalTimezone="convertDateToLocalTimezone" /> { if (selectedValue === 'custom') { customExpiration.value = tomorrow - const customExpirationInUserTimezone = customExpiration.value.convertDateToLocalTimezone( + const customExpirationInUserTimezone = props.convertDateToLocalTimezone( + customExpiration.value, props.userUtcOffset ) setExpiration(customExpirationInUserTimezone) @@ -80,7 +85,8 @@ const newExpirationDate = new Date() const daysToAdd = parseInt(selectedExpiration.value) newExpirationDate.setDate(newExpirationDate.getDate() + daysToAdd) - const newExpirationInUserTimezone = newExpirationDate.convertDateToLocalTimezone( + const newExpirationInUserTimezone = props.convertDateToLocalTimezone( + newExpirationDate, props.userUtcOffset ) setExpiration(newExpirationInUserTimezone) @@ -92,7 +98,8 @@ * @param {Date} newExpirationDate - The new expiration date. */ const updateExpiration = (newExpirationDate) => { - const newExpirationInUserTimezone = newExpirationDate.convertDateToLocalTimezone( + const newExpirationInUserTimezone = props.convertDateToLocalTimezone( + newExpirationDate, props.userUtcOffset ) setExpiration(newExpirationInUserTimezone) diff --git a/src/views/RealTimeEvents/blocks/interval-filter-block.vue b/src/views/RealTimeEvents/blocks/interval-filter-block.vue index 40667b87c..fc59de09d 100644 --- a/src/views/RealTimeEvents/blocks/interval-filter-block.vue +++ b/src/views/RealTimeEvents/blocks/interval-filter-block.vue @@ -1,5 +1,4 @@