diff --git a/.env.example b/.env.example index 0d0e8def04..9dba2e3707 100644 --- a/.env.example +++ b/.env.example @@ -57,6 +57,8 @@ LOG_LEVEL=info # ############################################################################### +TZ=UTC + # Configure where integrations will be loaded from NANGO_INTEGRATIONS_FULL_PATH= diff --git a/packages/shared/lib/services/sync/data/records.service.integration.test.ts b/packages/shared/lib/services/sync/data/records.service.integration.test.ts index 539676be8e..430dfeacec 100644 --- a/packages/shared/lib/services/sync/data/records.service.integration.test.ts +++ b/packages/shared/lib/services/sync/data/records.service.integration.test.ts @@ -25,10 +25,9 @@ describe('Records service', () => { expect(success).toBe(true); expect(error).toBe(null); expect(response?.records.length).toBe(n); - const timestampRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{5,6}\+\d{2}:\d{2}$/; expect(response?.records[0]?.['_nango_metadata']).toMatchObject({ - first_seen_at: expect.stringMatching(timestampRegex), - last_modified_at: expect.stringMatching(timestampRegex), + first_seen_at: expect.toBeIsoDateTimezone(), + last_modified_at: expect.toBeIsoDateTimezone(), last_action: 'ADDED', deleted_at: null, cursor: expect.stringMatching(/^[A-Za-z0-9+/]+={0,2}$/) // base64 encoded string diff --git a/packages/shared/lib/vitest.d.ts b/packages/shared/lib/vitest.d.ts new file mode 100644 index 0000000000..55290dadb4 --- /dev/null +++ b/packages/shared/lib/vitest.d.ts @@ -0,0 +1,14 @@ +export * from 'vitest'; + +/* eslint-disable @typescript-eslint/no-empty-interface */ +interface CustomMatchers { + toBeIsoDate: () => TR; + toBeIsoDateTimezone: () => TR; + toBeUUID: () => TR; +} + +declare module 'vitest' { + export interface Assertion extends CustomMatchers {} + export interface AsymmetricMatchersContaining extends CustomMatchers {} + export interface ExpectStatic extends CustomMatchers {} +} diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 41b9c5a4f3..d2f585f7ef 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json @@ -4,6 +4,10 @@ "rootDir": ".", "outDir": "dist" }, - "references": [{ "path": "../node-client" }], + "references": [ + { + "path": "../node-client" + } + ], "include": ["lib/**/*"] } diff --git a/tests/setupFiles.ts b/tests/setupFiles.ts new file mode 100644 index 0000000000..bceed8e6cf --- /dev/null +++ b/tests/setupFiles.ts @@ -0,0 +1,43 @@ +import { expect } from 'vitest'; + +const dateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{1,6}Z$/; +const dateRegexWithTZ = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{1,6}\+\d{2}:\d{2}$/; +const uuidRegex = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; + +expect.extend({ + toBeIsoDate: (received: any) => { + if (received instanceof Date) { + return { pass: true, message: () => '' }; + } else if (typeof received === 'string' && dateRegex.test(received)) { + return { pass: true, message: () => '' }; + } + + return { + message: () => `expected ${received} to be an ISO Date`, + pass: false + }; + }, + + toBeIsoDateTimezone: (received: any) => { + if (received instanceof Date) { + return { pass: true, message: () => '' }; + } else if (typeof received === 'string' && dateRegexWithTZ.test(received)) { + return { pass: true, message: () => '' }; + } + + return { + message: () => `expected ${received} to be an ISO Date`, + pass: false + }; + }, + + toBeUUID: (received: any) => { + if (!uuidRegex.test(received)) { + return { + message: () => `expected ${received} to be a UUID v4`, + pass: false + }; + } + return { pass: true, message: () => '' }; + } +}); diff --git a/vite.integration.config.ts b/vite.integration.config.ts index d2a1c279ce..bed8c12869 100644 --- a/vite.integration.config.ts +++ b/vite.integration.config.ts @@ -1,13 +1,15 @@ /// - // Configure Vitest (https://vitest.dev/config/) import { defineConfig } from 'vite'; +process.env.TZ = 'UTC'; + export default defineConfig({ test: { include: ['**/*.integration.{test,spec}.?(c|m)[jt]s?(x)'], globalSetup: './tests/setup.ts', + setupFiles: './tests/setupFiles.ts', threads: false, testTimeout: 20000 }