@@ -535,6 +535,138 @@ describe('constants', () => {
535535 expect ( typeof LOCALE_HEADER ) . toBe ( 'string' )
536536 expect ( typeof SEGMENT_HEADER ) . toBe ( 'string' )
537537 } )
538+
539+ test ( 'constants can be used as object keys without runtime errors' , ( ) => {
540+ // This is how IO apps use them in practice
541+ const headers = {
542+ [ TENANT_HEADER ] : 'example-value' ,
543+ [ BINDING_HEADER ] : 'example-binding' ,
544+ [ LOCALE_HEADER ] : 'en-US' ,
545+ [ SEGMENT_HEADER ] : 'segment-token' ,
546+ [ SESSION_HEADER ] : 'session-token' ,
547+ [ ACCOUNT_HEADER ] : 'account-name' ,
548+ [ WORKSPACE_HEADER ] : 'master'
549+ }
550+
551+ expect ( headers [ 'x-vtex-tenant' ] ) . toBe ( 'example-value' )
552+ expect ( headers [ 'x-vtex-binding' ] ) . toBe ( 'example-binding' )
553+ expect ( headers [ 'x-vtex-locale' ] ) . toBe ( 'en-US' )
554+ expect ( headers [ 'x-vtex-segment' ] ) . toBe ( 'segment-token' )
555+ expect ( Object . keys ( headers ) ) . toHaveLength ( 7 )
556+
557+ // Verify no undefined keys were created
558+ Object . keys ( headers ) . forEach ( key => {
559+ expect ( key ) . not . toBe ( 'undefined' )
560+ expect ( headers [ key ] ) . toBeDefined ( )
561+ } )
562+ } )
563+
564+ test ( 'constants can be destructured from module exports' , ( ) => {
565+ // Simulates: import { TENANT_HEADER, BINDING_HEADER } from '@vtex/api'
566+ const constants = require ( './constants' )
567+ const {
568+ TENANT_HEADER : tenant ,
569+ BINDING_HEADER : binding ,
570+ LOCALE_HEADER : locale ,
571+ SEGMENT_HEADER : segment
572+ } = constants
573+
574+ expect ( tenant ) . toBeDefined ( )
575+ expect ( binding ) . toBeDefined ( )
576+ expect ( locale ) . toBeDefined ( )
577+ expect ( segment ) . toBeDefined ( )
578+
579+ expect ( tenant ) . toBe ( 'x-vtex-tenant' )
580+ expect ( binding ) . toBe ( 'x-vtex-binding' )
581+ expect ( locale ) . toBe ( 'x-vtex-locale' )
582+ expect ( segment ) . toBe ( 'x-vtex-segment' )
583+
584+ // Ensure they're not undefined
585+ expect ( tenant ) . not . toBe ( undefined )
586+ expect ( binding ) . not . toBe ( undefined )
587+ } )
588+
589+ test ( 'individual constants are compatible with VaryHeaders type' , ( ) => {
590+ // VaryHeaders type uses HeaderKeys internally, but should accept old constants
591+ const varyHeaderValues : string [ ] = [ SEGMENT_HEADER , SESSION_HEADER , PRODUCT_HEADER , LOCALE_HEADER ]
592+
593+ varyHeaderValues . forEach ( header => {
594+ expect ( typeof header ) . toBe ( 'string' )
595+ expect ( header . length ) . toBeGreaterThan ( 0 )
596+ // VTEX headers follow x-vtex- pattern, except standard headers like cache-control
597+ expect ( header ) . toMatch ( / ^ x - v t e x - | ^ c a c h e - c o n t r o l $ | ^ e t a g $ / )
598+ } )
599+
600+ // Verify they match the type definition (HeaderKeys values)
601+ const expectedVaryHeaders = [
602+ HeaderKeys . SEGMENT ,
603+ HeaderKeys . SESSION ,
604+ HeaderKeys . PRODUCT ,
605+ HeaderKeys . LOCALE
606+ ]
607+
608+ expect ( varyHeaderValues ) . toEqual ( expectedVaryHeaders )
609+
610+ // Ensure VaryHeaders type inference works
611+ expect ( SEGMENT_HEADER ) . toBe ( HeaderKeys . SEGMENT )
612+ expect ( SESSION_HEADER ) . toBe ( HeaderKeys . SESSION )
613+ expect ( PRODUCT_HEADER ) . toBe ( HeaderKeys . PRODUCT )
614+ expect ( LOCALE_HEADER ) . toBe ( HeaderKeys . LOCALE )
615+ } )
616+
617+ test ( 'constants work correctly as header keys in realistic scenarios' , ( ) => {
618+ // Simulates IO apps usage patterns
619+ const mockBinding = { locale : 'en-US' , currency : 'USD' }
620+ const mockTenant = { locale : 'pt-BR' }
621+ const mockSegmentToken = 'eyJjYW1wYWlnbnMiOm51bGx9'
622+ const mockSessionToken = 'session-abc-123'
623+
624+ // Pattern 1: Building headers object
625+ const requestHeaders = {
626+ [ BINDING_HEADER ] : JSON . stringify ( mockBinding ) ,
627+ [ TENANT_HEADER ] : mockTenant . locale ,
628+ [ LOCALE_HEADER ] : 'en-US' ,
629+ [ SEGMENT_HEADER ] : mockSegmentToken ,
630+ [ SESSION_HEADER ] : mockSessionToken ,
631+ [ ACCOUNT_HEADER ] : 'vtexstore' ,
632+ [ WORKSPACE_HEADER ] : 'master'
633+ }
634+
635+ expect ( requestHeaders [ 'x-vtex-binding' ] ) . toBe ( JSON . stringify ( mockBinding ) )
636+ expect ( requestHeaders [ 'x-vtex-tenant' ] ) . toBe ( 'pt-BR' )
637+ expect ( requestHeaders [ 'x-vtex-locale' ] ) . toBe ( 'en-US' )
638+ expect ( requestHeaders [ 'x-vtex-segment' ] ) . toBe ( mockSegmentToken )
639+ expect ( requestHeaders [ 'x-vtex-session' ] ) . toBe ( mockSessionToken )
640+
641+ // Pattern 2: Conditional header setting
642+ const conditionalHeaders : Record < string , string > = { }
643+ if ( mockSegmentToken ) {
644+ conditionalHeaders [ SEGMENT_HEADER ] = mockSegmentToken
645+ }
646+ if ( mockSessionToken ) {
647+ conditionalHeaders [ SESSION_HEADER ] = mockSessionToken
648+ }
649+
650+ expect ( conditionalHeaders [ 'x-vtex-segment' ] ) . toBe ( mockSegmentToken )
651+ expect ( conditionalHeaders [ 'x-vtex-session' ] ) . toBe ( mockSessionToken )
652+ expect ( Object . keys ( conditionalHeaders ) ) . toHaveLength ( 2 )
653+
654+ // Pattern 3: Reading from headers object
655+ const incomingHeaders = {
656+ 'x-vtex-tenant' : 'es-AR' ,
657+ 'x-vtex-binding' : '{"locale":"es-AR"}' ,
658+ 'x-vtex-account' : 'mystore'
659+ }
660+
661+ expect ( incomingHeaders [ TENANT_HEADER ] ) . toBe ( 'es-AR' )
662+ expect ( incomingHeaders [ BINDING_HEADER ] ) . toBe ( '{"locale":"es-AR"}' )
663+ expect ( incomingHeaders [ ACCOUNT_HEADER ] ) . toBe ( 'mystore' )
664+
665+ // Verify no undefined keys in any pattern
666+ expect ( TENANT_HEADER ) . not . toBe ( 'undefined' )
667+ expect ( BINDING_HEADER ) . not . toBe ( 'undefined' )
668+ expect ( SEGMENT_HEADER ) . not . toBe ( 'undefined' )
669+ } )
538670 } )
539671 } )
540672} )
0 commit comments