diff --git a/src/constants.test.ts b/src/constants.test.ts index 21aafe65d..c66316361 100644 --- a/src/constants.test.ts +++ b/src/constants.test.ts @@ -678,3 +678,691 @@ describe('constants', () => { }) }) }) + +import { + NODE_VTEX_API_VERSION, + DEFAULT_WORKSPACE, + IS_IO, + PID, + HeaderKeys, + AttributeKeys, + BODY_HASH, + UP_SIGNAL, + MAX_AGE, + HTTP_SERVER_PORT, + MAX_WORKERS, + LINKED, + REGION, + CLUSTER_ID, + CLUSTER_ROLE, + PUBLIC_ENDPOINT, + APP, + NODE_ENV, + ACCOUNT, + WORKSPACE, + PRODUCTION, + INSPECT_DEBUGGER_PORT, + cancellableMethods, + LOG_CLIENT_INIT_TIMEOUT_MS, + METRIC_CLIENT_INIT_TIMEOUT_MS, + OTEL_EXPORTER_OTLP_ENDPOINT, + DK_APP_ID, + DIAGNOSTICS_TELEMETRY_ENABLED, + CACHE_CONTROL_HEADER, + SEGMENT_HEADER, + SESSION_HEADER, + PRODUCT_HEADER, + LOCALE_HEADER, + FORWARDED_HOST_HEADER, + TENANT_HEADER, + BINDING_HEADER, + META_HEADER, + META_HEADER_BUCKET, + ETAG_HEADER, + ACCOUNT_HEADER, + CREDENTIAL_HEADER, + REQUEST_ID_HEADER, + ROUTER_CACHE_HEADER, + OPERATION_ID_HEADER, + PLATFORM_HEADER, + WORKSPACE_IS_PRODUCTION_HEADER, + WORKSPACE_HEADER, + EVENT_KEY_HEADER, + EVENT_SENDER_HEADER, + EVENT_SUBJECT_HEADER, + EVENT_HANDLER_ID_HEADER, + COLOSSUS_ROUTE_DECLARER_HEADER, + COLOSSUS_ROUTE_ID_HEADER, + COLOSSUS_PARAMS_HEADER, + TRACE_ID_HEADER, + PROVIDER_HEADER, + VaryHeaders +} from './constants' + +describe('constants.ts - Extended Coverage', () => { + describe('MetricClientInitTimeout', () => { + test('METRIC_CLIENT_INIT_TIMEOUT_MS should be a positive number', () => { + // Arrange & Act + const timeout = METRIC_CLIENT_INIT_TIMEOUT_MS + + // Assert + expect(typeof timeout).toBe('number') + expect(timeout).toBeGreaterThan(0) + expect(Number.isInteger(timeout)).toBe(true) + }) + + test('METRIC_CLIENT_INIT_TIMEOUT_MS should equal LOG_CLIENT_INIT_TIMEOUT_MS', () => { + // Arrange & Act + const logTimeout = LOG_CLIENT_INIT_TIMEOUT_MS + const metricTimeout = METRIC_CLIENT_INIT_TIMEOUT_MS + + // Assert + expect(metricTimeout).toBe(logTimeout) + }) + + test('METRIC_CLIENT_INIT_TIMEOUT_MS should be reasonable timeout value', () => { + // Arrange & Act + const timeout = METRIC_CLIENT_INIT_TIMEOUT_MS + + // Assert + expect(timeout).toBeLessThan(60000) // Less than 1 minute + expect(timeout).toBeGreaterThanOrEqual(1000) // At least 1 second + }) + }) + + describe('OTelExporter Configuration', () => { + test('OTEL_EXPORTER_OTLP_ENDPOINT should be a string or empty', () => { + // Arrange & Act + const endpoint = OTEL_EXPORTER_OTLP_ENDPOINT + + // Assert + expect(typeof endpoint).toBe('string') + }) + + test('OTEL_EXPORTER_OTLP_ENDPOINT should reflect environment variable', () => { + // Arrange & Act + const endpoint = OTEL_EXPORTER_OTLP_ENDPOINT + const envValue = process.env.OTEL_EXPORTER_OTLP_ENDPOINT + + // Assert + expect(endpoint).toBe(envValue as string) + }) + + test('OTEL_EXPORTER_OTLP_ENDPOINT when set should be valid URL format', () => { + // Arrange + const endpoint = OTEL_EXPORTER_OTLP_ENDPOINT + + // Act & Assert + if (endpoint && endpoint.length > 0) { + expect(endpoint).toMatch(/^(http|https):\/\/.+/) // Basic URL pattern + } + }) + }) + + describe('DK_APP_ID Configuration', () => { + test('DK_APP_ID should be a non-empty string', () => { + // Arrange & Act + const dkAppId = DK_APP_ID + + // Assert + expect(typeof dkAppId).toBe('string') + expect(dkAppId.length).toBeGreaterThan(0) + }) + + test('DK_APP_ID should have fallback value', () => { + // Arrange & Act + const dkAppId = DK_APP_ID + + // Assert + // Default fallback is "apps-team" + expect(dkAppId).toBe(process.env.NODE_VTEX_API_DK_APP_ID || 'apps-team') + }) + + test('DK_APP_ID should not be undefined or null', () => { + // Arrange & Act + const dkAppId = DK_APP_ID + + // Assert + expect(dkAppId).toBeDefined() + expect(dkAppId).not.toBeNull() + }) + + test('DK_APP_ID should prefer environment variable when set', () => { + // Arrange + const expectedValue = DK_APP_ID + + // Act + if (process.env.NODE_VTEX_API_DK_APP_ID) { + // Assert + expect(expectedValue).toBe(process.env.NODE_VTEX_API_DK_APP_ID) + } else { + // Assert - should use fallback + expect(expectedValue).toBe('apps-team') + } + }) + }) + + describe('DiagnosticsTelemetry Configuration', () => { + test('DIAGNOSTICS_TELEMETRY_ENABLED should be a boolean', () => { + // Arrange & Act + const enabled = DIAGNOSTICS_TELEMETRY_ENABLED + + // Assert + expect(typeof enabled).toBe('boolean') + }) + + test('DIAGNOSTICS_TELEMETRY_ENABLED should reflect string comparison with "true"', () => { + // Arrange & Act + const enabled = DIAGNOSTICS_TELEMETRY_ENABLED + const expectedValue = process.env.VTEX_DIAGNOSTICS_TELEMETRY_ENABLED === 'true' + + // Assert + expect(enabled).toBe(expectedValue) + }) + + test('DIAGNOSTICS_TELEMETRY_ENABLED should be false when env var is not "true"', () => { + // Arrange + const envValue = process.env.VTEX_DIAGNOSTICS_TELEMETRY_ENABLED + + // Act + const enabled = DIAGNOSTICS_TELEMETRY_ENABLED + + // Assert + if (envValue !== 'true') { + expect(enabled).toBe(false) + } + }) + + test('DIAGNOSTICS_TELEMETRY_ENABLED should only be true for exact "true" string', () => { + // Arrange + // Test that only exact match 'true' results in true + const testCases = ['true', 'false', 'True', 'TRUE', '1', 'yes', '', undefined] + + // Act & Assert + testCases.forEach(testValue => { + const result = testValue === 'true' + if (testValue === 'true') { + expect(result).toBe(true) + } else { + expect(result).toBe(false) + } + }) + }) + }) + + describe('HeaderKeys - Extended Coverage', () => { + test('HeaderKeys should contain all COLOSSUS headers', () => { + // Arrange & Act & Assert + expect(HeaderKeys).toHaveProperty('COLOSSUS_ROUTE_DECLARER') + expect(HeaderKeys).toHaveProperty('COLOSSUS_ROUTE_ID') + expect(HeaderKeys).toHaveProperty('COLOSSUS_PARAMS') + + expect(HeaderKeys.COLOSSUS_ROUTE_DECLARER).toBe('x-colossus-route-declarer') + expect(HeaderKeys.COLOSSUS_ROUTE_ID).toBe('x-colossus-route-id') + expect(HeaderKeys.COLOSSUS_PARAMS).toBe('x-colossus-params') + }) + + test('HeaderKeys should contain all EVENT headers', () => { + // Arrange & Act & Assert + expect(HeaderKeys).toHaveProperty('EVENT_KEY') + expect(HeaderKeys).toHaveProperty('EVENT_SENDER') + expect(HeaderKeys).toHaveProperty('EVENT_SUBJECT') + expect(HeaderKeys).toHaveProperty('EVENT_HANDLER_ID') + + expect(HeaderKeys.EVENT_KEY).toBe('x-event-key') + expect(HeaderKeys.EVENT_SENDER).toBe('x-event-sender') + expect(HeaderKeys.EVENT_SUBJECT).toBe('x-event-subject') + expect(HeaderKeys.EVENT_HANDLER_ID).toBe('x-event-handler-id') + }) + + test('HeaderKeys should contain USER_AGENT and VTEX_USER_AGENT', () => { + // Arrange & Act & Assert + expect(HeaderKeys).toHaveProperty('USER_AGENT') + expect(HeaderKeys).toHaveProperty('VTEX_USER_AGENT') + + expect(HeaderKeys.USER_AGENT).toBe('user-agent') + expect(HeaderKeys.VTEX_USER_AGENT).toBe('x-vtex-user-agent') + }) + + test('HeaderKeys should contain IO caller and app service headers', () => { + // Arrange & Act & Assert + expect(HeaderKeys).toHaveProperty('VTEX_IO_CALLER') + expect(HeaderKeys).toHaveProperty('VTEX_APP_SERVICE') + expect(HeaderKeys).toHaveProperty('VTEX_APP_KEY') + expect(HeaderKeys).toHaveProperty('VTEX_RETRY_COUNT') + + expect(HeaderKeys.VTEX_IO_CALLER).toBe('x-vtex-io-caller') + expect(HeaderKeys.VTEX_APP_SERVICE).toBe('x-vtex-app-service') + expect(HeaderKeys.VTEX_APP_KEY).toBe('x-vtex-app-key') + expect(HeaderKeys.VTEX_RETRY_COUNT).toBe('x-vtex-retry-count') + }) + + test('all HeaderKeys values should be lowercase', () => { + // Arrange & Act & Assert + Object.values(HeaderKeys).forEach(headerValue => { + expect(headerValue).toBe(headerValue.toLowerCase()) + }) + }) + + test('HeaderKeys should not have duplicate values', () => { + // Arrange + const headerValues = Object.values(HeaderKeys) + const uniqueValues = new Set(headerValues) + + // Act & Assert + expect(uniqueValues.size).toBe(headerValues.length) + }) + + test('HeaderKeys count should be reasonable', () => { + // Arrange & Act + const headerCount = Object.keys(HeaderKeys).length + + // Assert + expect(headerCount).toBeGreaterThan(20) + expect(headerCount).toBeLessThan(100) + }) + }) + + describe('APP Object - Extended Edge Cases', () => { + test('APP.MAJOR should be empty string when VERSION is not set', () => { + // Arrange + const originalVersion = process.env.VTEX_APP_VERSION + + // Act + delete process.env.VTEX_APP_VERSION + // Re-import would be needed for dynamic testing, so we check the logic + const hasVersion = process.env.VTEX_APP_VERSION + + // Assert + if (!hasVersion) { + expect(APP.MAJOR).toBe('') + } + + // Cleanup + if (originalVersion) { + process.env.VTEX_APP_VERSION = originalVersion + } + }) + + test('APP.IS_THIRD_PARTY should return true for vendor not in exclusion list', () => { + // Arrange & Act + const result = APP.IS_THIRD_PARTY() + + // Assert + if (APP.VENDOR !== 'vtex' && APP.VENDOR !== 'gocommerce') { + expect(result).toBe(true) + } + }) + + test('APP.IS_THIRD_PARTY should return false for vtex vendor', () => { + // Arrange + const mockApp = { + VENDOR: 'vtex', + IS_THIRD_PARTY() { + return 'vtex' !== this.VENDOR && 'gocommerce' !== this.VENDOR + } + } + + // Act + const result = mockApp.IS_THIRD_PARTY() + + // Assert + expect(result).toBe(false) + }) + + test('APP.IS_THIRD_PARTY should return false for gocommerce vendor', () => { + // Arrange + const mockApp = { + VENDOR: 'gocommerce', + IS_THIRD_PARTY() { + return 'vtex' !== this.VENDOR && 'gocommerce' !== this.VENDOR + } + } + + // Act + const result = mockApp.IS_THIRD_PARTY() + + // Assert + expect(result).toBe(false) + }) + + test('APP properties should be consistent with environment', () => { + // Arrange & Act & Assert + expect(APP.ID).toBe(process.env.VTEX_APP_ID as string) + expect(APP.NAME).toBe(process.env.VTEX_APP_NAME as string) + expect(APP.VENDOR).toBe(process.env.VTEX_APP_VENDOR as string) + expect(APP.VERSION).toBe(process.env.VTEX_APP_VERSION as string) + }) + }) + + describe('CancellableMethods - Extended Coverage', () => { + test('cancellableMethods should be immutable Set', () => { + // Arrange & Act + const methodsBefore = Array.from(cancellableMethods) + + // Assert + expect(cancellableMethods).toBeInstanceOf(Set) + expect(cancellableMethods.size).toBeGreaterThan(0) + + // Verify contents + expect(Array.from(cancellableMethods)).toEqual(methodsBefore) + }) + + test('cancellableMethods should contain exactly three methods', () => { + // Arrange & Act & Assert + expect(cancellableMethods.size).toBe(3) + }) + + test('cancellableMethods entries should be uppercase strings', () => { + // Arrange & Act & Assert + cancellableMethods.forEach((method: any) => { + expect(typeof method).toBe('string') + expect(method).toMatch(/^[A-Z]+$/) + }) + }) + + test('cancellableMethods should work with Set methods', () => { + // Arrange & Act + const hasGet = cancellableMethods.has('GET') + const hasPost = cancellableMethods.has('POST') + const size = cancellableMethods.size + + // Assert + expect(hasGet).toBe(true) + expect(hasPost).toBe(false) + expect(size).toBe(3) + }) + }) + + describe('String Constants - Special Values', () => { + test('BODY_HASH should be a specific underscore-delimited string', () => { + // Arrange & Act & Assert + expect(BODY_HASH).toBe('__graphqlBodyHash') + expect(typeof BODY_HASH).toBe('string') + expect(BODY_HASH).toMatch(/^__[a-zA-Z]+__?$/) + }) + + test('UP_SIGNAL should be uppercase signal value', () => { + // Arrange & Act & Assert + expect(UP_SIGNAL).toBe('UP') + expect(typeof UP_SIGNAL).toBe('string') + expect(UP_SIGNAL).toMatch(/^[A-Z]+$/) + }) + + test('DEFAULT_WORKSPACE should be master', () => { + // Arrange & Act & Assert + expect(DEFAULT_WORKSPACE).toBe('master') + expect(typeof DEFAULT_WORKSPACE).toBe('string') + }) + }) + + describe('MAX_AGE Constants - Boundary Tests', () => { + test('MAX_AGE.SHORT should be smallest value', () => { + // Arrange & Act & Assert + expect(MAX_AGE.SHORT).toBeLessThan(MAX_AGE.MEDIUM) + expect(MAX_AGE.SHORT).toBeLessThan(MAX_AGE.LONG) + }) + + test('MAX_AGE.MEDIUM should be middle value', () => { + // Arrange & Act & Assert + expect(MAX_AGE.MEDIUM).toBeGreaterThan(MAX_AGE.SHORT) + expect(MAX_AGE.MEDIUM).toBeLessThan(MAX_AGE.LONG) + }) + + test('MAX_AGE.LONG should be largest value', () => { + // Arrange & Act & Assert + expect(MAX_AGE.LONG).toBeGreaterThan(MAX_AGE.MEDIUM) + expect(MAX_AGE.LONG).toBeGreaterThan(MAX_AGE.SHORT) + }) + + test('MAX_AGE values should represent realistic cache durations', () => { + // Arrange & Act & Assert + // SHORT: 120 seconds = 2 minutes + expect(MAX_AGE.SHORT).toBe(120) + // MEDIUM: 3600 seconds = 1 hour + expect(MAX_AGE.MEDIUM).toBe(3600) + // LONG: 86400 seconds = 24 hours + expect(MAX_AGE.LONG).toBe(86400) + }) + }) + + describe('Port Constants - Network Configuration', () => { + test('HTTP_SERVER_PORT should be a valid port number', () => { + // Arrange & Act & Assert + expect(typeof HTTP_SERVER_PORT).toBe('number') + expect(HTTP_SERVER_PORT).toBeGreaterThan(0) + expect(HTTP_SERVER_PORT).toBeLessThan(65536) + }) + + test('HTTP_SERVER_PORT should be 5050', () => { + // Arrange & Act & Assert + expect(HTTP_SERVER_PORT).toBe(5050) + }) + + test('INSPECT_DEBUGGER_PORT should be a valid port number', () => { + // Arrange & Act & Assert + expect(typeof INSPECT_DEBUGGER_PORT).toBe('number') + expect(INSPECT_DEBUGGER_PORT).toBeGreaterThan(0) + expect(INSPECT_DEBUGGER_PORT).toBeLessThan(65536) + }) + + test('INSPECT_DEBUGGER_PORT should be 5858', () => { + // Arrange & Act & Assert + expect(INSPECT_DEBUGGER_PORT).toBe(5858) + }) + + test('ports should be different', () => { + // Arrange & Act & Assert + expect(HTTP_SERVER_PORT).not.toBe(INSPECT_DEBUGGER_PORT) + }) + }) + + describe('Timeout Constants - Time Configuration', () => { + test('LOG_CLIENT_INIT_TIMEOUT_MS should be 5000 milliseconds', () => { + // Arrange & Act & Assert + expect(LOG_CLIENT_INIT_TIMEOUT_MS).toBe(5000) + }) + + test('METRIC_CLIENT_INIT_TIMEOUT_MS should be 5000 milliseconds', () => { + // Arrange & Act & Assert + expect(METRIC_CLIENT_INIT_TIMEOUT_MS).toBe(5000) + }) + + test('timeout constants should be milliseconds', () => { + // Arrange & Act & Assert + expect(LOG_CLIENT_INIT_TIMEOUT_MS).toBeGreaterThanOrEqual(1000) + expect(METRIC_CLIENT_INIT_TIMEOUT_MS).toBeGreaterThanOrEqual(1000) + expect(LOG_CLIENT_INIT_TIMEOUT_MS).toBeLessThan(30000) + expect(METRIC_CLIENT_INIT_TIMEOUT_MS).toBeLessThan(30000) + }) + }) + + describe('Worker Constants', () => { + test('MAX_WORKERS should be a positive integer', () => { + // Arrange & Act & Assert + expect(typeof MAX_WORKERS).toBe('number') + expect(MAX_WORKERS).toBeGreaterThan(0) + expect(Number.isInteger(MAX_WORKERS)).toBe(true) + }) + + test('MAX_WORKERS should be 4', () => { + // Arrange & Act & Assert + expect(MAX_WORKERS).toBe(4) + }) + + test('MAX_WORKERS should be reasonable for typical systems', () => { + // Arrange & Act & Assert + expect(MAX_WORKERS).toBeGreaterThanOrEqual(1) + expect(MAX_WORKERS).toBeLessThanOrEqual(16) + }) + }) + + describe('PUBLIC_ENDPOINT Configuration', () => { + test('PUBLIC_ENDPOINT should be a string', () => { + // Arrange & Act & Assert + expect(typeof PUBLIC_ENDPOINT).toBe('string') + expect(PUBLIC_ENDPOINT.length).toBeGreaterThan(0) + }) + + test('PUBLIC_ENDPOINT should have default fallback', () => { + // Arrange & Act + const endpoint = PUBLIC_ENDPOINT + const envValue = process.env.VTEX_PUBLIC_ENDPOINT + + // Assert + expect(endpoint).toBe(envValue || 'myvtex.com') + }) + + test('PUBLIC_ENDPOINT should contain valid domain format', () => { + // Arrange & Act & Assert + expect(PUBLIC_ENDPOINT).toMatch(/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/) + }) + }) + + describe('DeprecatedHeaderConstants - Consistency', () => { + test('all deprecated header constants should match HeaderKeys', () => { + // Arrange & Act & Assert + const headerMappings = [ + [CACHE_CONTROL_HEADER, HeaderKeys.CACHE_CONTROL], + [SEGMENT_HEADER, HeaderKeys.SEGMENT], + [SESSION_HEADER, HeaderKeys.SESSION], + [PRODUCT_HEADER, HeaderKeys.PRODUCT], + [LOCALE_HEADER, HeaderKeys.LOCALE], + [FORWARDED_HOST_HEADER, HeaderKeys.FORWARDED_HOST], + [TENANT_HEADER, HeaderKeys.TENANT], + [BINDING_HEADER, HeaderKeys.BINDING], + [META_HEADER, HeaderKeys.META], + [META_HEADER_BUCKET, HeaderKeys.META_BUCKET], + [ETAG_HEADER, HeaderKeys.ETAG], + [ACCOUNT_HEADER, HeaderKeys.ACCOUNT], + [CREDENTIAL_HEADER, HeaderKeys.CREDENTIAL], + [REQUEST_ID_HEADER, HeaderKeys.REQUEST_ID], + [ROUTER_CACHE_HEADER, HeaderKeys.ROUTER_CACHE], + [OPERATION_ID_HEADER, HeaderKeys.OPERATION_ID], + [PLATFORM_HEADER, HeaderKeys.PLATFORM], + [WORKSPACE_IS_PRODUCTION_HEADER, HeaderKeys.WORKSPACE_IS_PRODUCTION], + [WORKSPACE_HEADER, HeaderKeys.WORKSPACE], + [EVENT_KEY_HEADER, HeaderKeys.EVENT_KEY], + [EVENT_SENDER_HEADER, HeaderKeys.EVENT_SENDER], + [EVENT_SUBJECT_HEADER, HeaderKeys.EVENT_SUBJECT], + [EVENT_HANDLER_ID_HEADER, HeaderKeys.EVENT_HANDLER_ID], + [COLOSSUS_ROUTE_DECLARER_HEADER, HeaderKeys.COLOSSUS_ROUTE_DECLARER], + [COLOSSUS_ROUTE_ID_HEADER, HeaderKeys.COLOSSUS_ROUTE_ID], + [COLOSSUS_PARAMS_HEADER, HeaderKeys.COLOSSUS_PARAMS], + [TRACE_ID_HEADER, HeaderKeys.TRACE_ID], + [PROVIDER_HEADER, HeaderKeys.PROVIDER] + ] + + headerMappings.forEach(([deprecated, current]) => { + expect(deprecated).toBe(current) + }) + }) + + test('deprecated constants should not be null or undefined', () => { + // Arrange & Act & Assert + const deprecatedConstants = [ + CACHE_CONTROL_HEADER, + SEGMENT_HEADER, + SESSION_HEADER, + PRODUCT_HEADER, + LOCALE_HEADER, + FORWARDED_HOST_HEADER, + TENANT_HEADER, + BINDING_HEADER, + META_HEADER, + META_HEADER_BUCKET, + ETAG_HEADER, + ACCOUNT_HEADER, + CREDENTIAL_HEADER, + REQUEST_ID_HEADER, + ROUTER_CACHE_HEADER, + OPERATION_ID_HEADER, + PLATFORM_HEADER, + WORKSPACE_IS_PRODUCTION_HEADER, + WORKSPACE_HEADER, + EVENT_KEY_HEADER, + EVENT_SENDER_HEADER, + EVENT_SUBJECT_HEADER, + EVENT_HANDLER_ID_HEADER, + COLOSSUS_ROUTE_DECLARER_HEADER, + COLOSSUS_ROUTE_ID_HEADER, + COLOSSUS_PARAMS_HEADER, + TRACE_ID_HEADER, + PROVIDER_HEADER + ] + + deprecatedConstants.forEach(constant => { + expect(constant).toBeDefined() + expect(constant).not.toBeNull() + expect(typeof constant).toBe('string') + }) + }) + }) + + describe('Type Compatibility - VaryHeaders', () => { + test('VaryHeaders type should accept valid HeaderKeys values', () => { + // Arrange + const varyHeaderValues: VaryHeaders[] = [ + HeaderKeys.SEGMENT, + HeaderKeys.SESSION, + HeaderKeys.PRODUCT, + HeaderKeys.LOCALE + ] + + // Act & Assert + expect(varyHeaderValues).toHaveLength(4) + varyHeaderValues.forEach(header => { + expect(typeof header).toBe('string') + expect(header).toMatch(/^x-vtex-/) + }) + }) + }) + + describe('Environment Variable Reflections - Integration', () => { + test('constants should reflect environment at module load time', () => { + // Arrange & Act & Assert + expect(REGION).toBe(process.env.VTEX_REGION as string) + expect(CLUSTER_ID).toBe(process.env.VTEX_CLUSTER_ID as string) + expect(CLUSTER_ROLE).toBe(process.env.VTEX_CLUSTER_ROLE as string) + expect(NODE_ENV).toBe(process.env.NODE_ENV as string) + expect(ACCOUNT).toBe(process.env.VTEX_ACCOUNT as string) + expect(WORKSPACE).toBe(process.env.VTEX_WORKSPACE as string) + expect(IS_IO).toBe(process.env.VTEX_IO) + }) + + test('LINKED should reflect VTEX_APP_LINK presence', () => { + // Arrange & Act + const expectedLinked = !!process.env.VTEX_APP_LINK + + // Assert + expect(LINKED).toBe(expectedLinked) + }) + + test('PRODUCTION should be true only when VTEX_PRODUCTION is "true"', () => { + // Arrange & Act + const expectedProduction = process.env.VTEX_PRODUCTION === 'true' + + // Assert + expect(PRODUCTION).toBe(expectedProduction) + }) + }) + + describe('PID and Version Constants', () => { + test('PID should be the current process ID', () => { + // Arrange & Act & Assert + expect(PID).toBe(process.pid) + expect(typeof PID).toBe('number') + expect(PID).toBeGreaterThan(0) + }) + + test('NODE_VTEX_API_VERSION should be from package.json', () => { + // Arrange & Act + const pkg = require('../package.json') + + // Assert + expect(NODE_VTEX_API_VERSION).toBe(pkg.version) + expect(typeof NODE_VTEX_API_VERSION).toBe('string') + expect(NODE_VTEX_API_VERSION).toMatch(/^\d+\.\d+\.\d+/) + }) + }) +}) \ No newline at end of file