55 */
66
77import { describe , it , expect } from 'vitest' ;
8- import { applyOverrides } from '../../../src/services/override-merger.js' ;
8+ import { applyOverrides , hasNamedValueOverride } from '../../../src/services/override-merger.js' ;
99import { ResourceType } from '../../../src/models/resource-types.js' ;
1010import { ResourceDescriptor } from '../../../src/models/types.js' ;
1111import { OverrideConfig } from '../../../src/models/config.js' ;
@@ -655,59 +655,46 @@ describe('override-merger', () => {
655655 expect ( result . properties ) . toHaveProperty ( 'isCurrent' , true ) ;
656656 } ) ;
657657 } ) ;
658-
659658 describe ( 'workspace-scoped overrides' , ( ) => {
660- it ( 'should apply a direct override for a workspace-scoped API' , ( ) => {
661- const descriptor : ResourceDescriptor = {
662- type : ResourceType . Api ,
663- nameParts : [ 'my-api' ] ,
664- workspace : 'ws1' ,
665- } ;
666- const json = { name : 'my-api' , properties : { serviceUrl : 'https://dev.example.com' } } ;
667- const overrideConfig : OverrideConfig = {
668- workspaces : {
669- ws1 : {
670- properties : { } ,
671- children : {
672- apis : {
673- 'my-api' : {
674- properties : { serviceUrl : 'https://prod.example.com' } ,
659+ const overrideConfig : OverrideConfig = {
660+ apis : {
661+ 'my-api' : { properties : { serviceUrl : 'https://service-level.example.com' } } ,
662+ } ,
663+ workspaces : {
664+ 'my-workspace' : {
665+ properties : { description : 'Production workspace' } ,
666+ children : {
667+ apis : {
668+ 'my-api' : {
669+ properties : { serviceUrl : 'https://prod.example.com' } ,
670+ children : {
671+ diagnostics : { applicationinsights : { properties : { verbosity : 'error' } } } ,
672+ policies : { policy : { properties : { format : 'xml' } } } ,
673+ operations : {
674+ 'get-op' : {
675+ properties : { displayName : 'Prod Op' } ,
676+ children : { policies : { policy : { properties : { format : 'xml' } } } } ,
677+ } ,
678+ } ,
675679 } ,
676680 } ,
677681 } ,
678- } ,
679- } ,
680- } ;
681-
682- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
683- expect ( result . properties ) . toHaveProperty ( 'serviceUrl' , 'https://prod.example.com' ) ;
684- } ) ;
685-
686- it ( 'should apply a direct override for a workspace-scoped backend' , ( ) => {
687- const descriptor : ResourceDescriptor = {
688- type : ResourceType . Backend ,
689- nameParts : [ 'orders-backend' ] ,
690- workspace : 'partner-workspace' ,
691- } ;
692- const json = { name : 'orders-backend' , properties : { url : 'https://orders-dev.example.com' } } ;
693- const overrideConfig : OverrideConfig = {
694- workspaces : {
695- 'partner-workspace' : {
696- properties : { } ,
697- children : {
698- backends : {
699- 'orders-backend' : {
700- properties : { url : 'https://orders-prod.example.com' } ,
701- } ,
682+ backends : {
683+ 'my-backend' : { properties : { url : 'https://prod-backend.example.com' } } ,
684+ } ,
685+ namedValues : {
686+ 'My-NV' : { properties : { value : 'prod-value' } } ,
687+ } ,
688+ products : {
689+ 'my-product' : {
690+ properties : { state : 'published' } ,
691+ children : { policies : { policy : { properties : { format : 'xml' } } } } ,
702692 } ,
703693 } ,
704694 } ,
705695 } ,
706- } ;
707-
708- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
709- expect ( result . properties ) . toHaveProperty ( 'url' , 'https://orders-prod.example.com' ) ;
710- } ) ;
696+ } ,
697+ } ;
711698
712699 it ( 'should use the override from the matching workspace when multiple workspaces define the same resource name' , ( ) => {
713700 const descriptor : ResourceDescriptor = {
@@ -716,168 +703,124 @@ describe('override-merger', () => {
716703 workspace : 'ws2' ,
717704 } ;
718705 const json = { name : 'my-api' , properties : { serviceUrl : 'https://dev.example.com' } } ;
719- const overrideConfig : OverrideConfig = {
706+ const overrides : OverrideConfig = {
720707 workspaces : {
721708 ws1 : {
722709 properties : { } ,
723710 children : {
724711 apis : {
725- 'my-api' : {
726- properties : { serviceUrl : 'https://ws1.example.com' } ,
727- } ,
712+ 'my-api' : { properties : { serviceUrl : 'https://ws1.example.com' } } ,
728713 } ,
729714 } ,
730715 } ,
731716 ws2 : {
732717 properties : { } ,
733718 children : {
734719 apis : {
735- 'my-api' : {
736- properties : { serviceUrl : 'https://ws2.example.com' } ,
737- } ,
720+ 'my-api' : { properties : { serviceUrl : 'https://ws2.example.com' } } ,
738721 } ,
739722 } ,
740723 } ,
741724 } ,
742725 } ;
743726
744- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
727+ const result = applyOverrides ( descriptor , json , overrides ) ;
745728 expect ( result . properties ) . toHaveProperty ( 'serviceUrl' , 'https://ws2.example.com' ) ;
746729 } ) ;
747730
748- it ( 'should apply a nested override for a workspace-scoped API diagnostic' , ( ) => {
749- const descriptor : ResourceDescriptor = {
750- type : ResourceType . ApiDiagnostic ,
751- nameParts : [ 'my-api' , 'applicationinsights' ] ,
752- workspace : 'ws1' ,
753- } ;
754- const json = { name : 'applicationinsights' , properties : { loggerId : '/old-logger' } } ;
755- const overrideConfig : OverrideConfig = {
756- workspaces : {
757- ws1 : {
758- properties : { } ,
759- children : {
760- apis : {
761- 'my-api' : {
762- properties : { } ,
763- children : {
764- diagnostics : {
765- applicationinsights : {
766- properties : { loggerId : '/new-logger' } ,
767- } ,
768- } ,
769- } ,
770- } ,
771- } ,
772- } ,
773- } ,
774- } ,
775- } ;
731+ it ( 'should apply override to the workspace container itself' , ( ) => {
732+ const result = applyOverrides (
733+ { type : ResourceType . Workspace , nameParts : [ 'my-workspace' ] } ,
734+ { properties : { description : 'Dev workspace' } } ,
735+ overrideConfig
736+ ) ;
737+ expect ( result . properties ) . toHaveProperty ( 'description' , 'Production workspace' ) ;
738+ } ) ;
776739
777- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
778- expect ( result . properties ) . toHaveProperty ( 'loggerId' , '/new-logger' ) ;
740+ it ( 'should apply nested override to a workspace API (case-insensitive workspace name)' , ( ) => {
741+ const result = applyOverrides (
742+ { type : ResourceType . Api , nameParts : [ 'my-api' ] , workspace : 'MY-WORKSPACE' } ,
743+ { properties : { serviceUrl : 'https://dev.example.com' , path : 'my' } } ,
744+ overrideConfig
745+ ) ;
746+ expect ( result . properties ) . toEqual ( { serviceUrl : 'https://prod.example.com' , path : 'my' } ) ;
779747 } ) ;
780748
781- it ( 'should apply a grandchild override for a workspace-scoped API operation policy' , ( ) => {
782- const descriptor : ResourceDescriptor = {
783- type : ResourceType . ApiOperationPolicy ,
784- nameParts : [ 'my-api' , 'get-pets' ] ,
785- workspace : 'ws1' ,
786- } ;
787- const json = { name : 'policy' , properties : { format : 'xml' } } ;
788- const overrideConfig : OverrideConfig = {
789- workspaces : {
790- ws1 : {
791- properties : { } ,
792- children : {
793- apis : {
794- 'my-api' : {
795- properties : { } ,
796- children : {
797- operations : {
798- 'get-pets' : {
799- properties : { } ,
800- children : {
801- policies : {
802- policy : { properties : { format : 'rawxml' } } ,
803- } ,
804- } ,
805- } ,
806- } ,
807- } ,
808- } ,
809- } ,
810- } ,
811- } ,
812- } ,
813- } ;
749+ it ( 'should apply nested override to a workspace backend and named value' , ( ) => {
750+ const backend = applyOverrides (
751+ { type : ResourceType . Backend , nameParts : [ 'my-backend' ] , workspace : 'my-workspace' } ,
752+ { properties : { url : 'https://dev-backend.example.com' } } ,
753+ overrideConfig
754+ ) ;
755+ expect ( backend . properties ) . toHaveProperty ( 'url' , 'https://prod-backend.example.com' ) ;
814756
815- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
816- expect ( result . properties ) . toHaveProperty ( 'format' , 'rawxml' ) ;
757+ const nv = applyOverrides (
758+ { type : ResourceType . NamedValue , nameParts : [ 'my-nv' ] , workspace : 'my-workspace' } ,
759+ { properties : { value : 'dev-value' } } ,
760+ overrideConfig
761+ ) ;
762+ expect ( nv . properties ) . toHaveProperty ( 'value' , 'prod-value' ) ;
817763 } ) ;
818764
819- it ( 'should not leak a top-level override into a workspace-scoped resource' , ( ) => {
820- const descriptor : ResourceDescriptor = {
821- type : ResourceType . Api ,
822- nameParts : [ 'my-api' ] ,
823- workspace : 'ws1' ,
824- } ;
825- const json = { name : 'my-api' , properties : { serviceUrl : 'https://dev.example.com' } } ;
826- // Same resource name is overridden at the top level, but no workspace-scoped override exists.
827- const overrideConfig : OverrideConfig = {
828- apis : {
829- 'my-api' : {
830- properties : { serviceUrl : 'https://should-not-apply.example.com' } ,
831- } ,
832- } ,
833- } ;
765+ it ( 'should apply overrides to workspace API sub-resources' , ( ) => {
766+ const diag = applyOverrides (
767+ { type : ResourceType . ApiDiagnostic , nameParts : [ 'my-api' , 'applicationinsights' ] , workspace : 'my-workspace' } ,
768+ { properties : { verbosity : 'information' } } ,
769+ overrideConfig
770+ ) ;
771+ expect ( diag . properties ) . toHaveProperty ( 'verbosity' , 'error' ) ;
834772
835- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
836- expect ( result ) . toEqual ( json ) ;
837- } ) ;
773+ const apiPolicy = applyOverrides (
774+ { type : ResourceType . ApiPolicy , nameParts : [ 'my-api' ] , workspace : 'my-workspace' } ,
775+ { properties : { format : 'rawxml' , value : '<policies/>' } } ,
776+ overrideConfig
777+ ) ;
778+ expect ( apiPolicy . properties ) . toEqual ( { format : 'xml' , value : '<policies/>' } ) ;
838779
839- it ( 'should still apply workspace container property overrides (no workspace field on descriptor)' , ( ) => {
840- const descriptor : ResourceDescriptor = {
841- type : ResourceType . Workspace ,
842- nameParts : [ 'ws1' ] ,
843- } ;
844- const json = { name : 'ws1' , properties : { displayName : 'Dev Workspace' } } ;
845- const overrideConfig : OverrideConfig = {
846- workspaces : {
847- ws1 : {
848- properties : { displayName : 'Prod Workspace' } ,
849- } ,
850- } ,
851- } ;
780+ const op = applyOverrides (
781+ { type : ResourceType . ApiOperation , nameParts : [ 'my-api' , 'get-op' ] , workspace : 'my-workspace' } ,
782+ { properties : { displayName : 'Dev Op' } } ,
783+ overrideConfig
784+ ) ;
785+ expect ( op . properties ) . toHaveProperty ( 'displayName' , 'Prod Op' ) ;
852786
853- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
854- expect ( result . properties ) . toHaveProperty ( 'displayName' , 'Prod Workspace' ) ;
787+ const opPolicy = applyOverrides (
788+ { type : ResourceType . ApiOperationPolicy , nameParts : [ 'my-api' , 'get-op' ] , workspace : 'my-workspace' } ,
789+ { properties : { format : 'rawxml' } } ,
790+ overrideConfig
791+ ) ;
792+ expect ( opPolicy . properties ) . toHaveProperty ( 'format' , 'xml' ) ;
793+
794+ const productPolicy = applyOverrides (
795+ { type : ResourceType . ProductPolicy , nameParts : [ 'my-product' ] , workspace : 'my-workspace' } ,
796+ { properties : { format : 'rawxml' } } ,
797+ overrideConfig
798+ ) ;
799+ expect ( productPolicy . properties ) . toHaveProperty ( 'format' , 'xml' ) ;
855800 } ) ;
856801
857- it ( 'should match workspace names case-insensitively' , ( ) => {
858- const descriptor : ResourceDescriptor = {
859- type : ResourceType . Api ,
860- nameParts : [ 'my-api' ] ,
861- workspace : 'ws1' ,
862- } ;
863- const json = { name : 'my-api' , properties : { serviceUrl : 'https://dev.example.com' } } ;
864- const overrideConfig : OverrideConfig = {
865- workspaces : {
866- WS1 : {
867- properties : { } ,
868- children : {
869- apis : {
870- 'my-api' : {
871- properties : { serviceUrl : 'https://prod.example.com' } ,
872- } ,
873- } ,
874- } ,
875- } ,
876- } ,
877- } ;
802+ it ( 'should not apply service-level overrides to workspace-scoped resources' , ( ) => {
803+ const result = applyOverrides (
804+ { type : ResourceType . Api , nameParts : [ 'my-api' ] , workspace : 'other-workspace' } ,
805+ { properties : { serviceUrl : 'https://dev.example.com' } } ,
806+ overrideConfig
807+ ) ;
808+ expect ( result . properties ) . toHaveProperty ( 'serviceUrl' , 'https://dev.example.com' ) ;
809+ } ) ;
878810
879- const result = applyOverrides ( descriptor , json , overrideConfig ) ;
880- expect ( result . properties ) . toHaveProperty ( 'serviceUrl' , 'https://prod.example.com' ) ;
811+ it ( 'should not apply workspace overrides to service-level resources' , ( ) => {
812+ const result = applyOverrides (
813+ { type : ResourceType . Backend , nameParts : [ 'my-backend' ] } ,
814+ { properties : { url : 'https://dev-backend.example.com' } } ,
815+ overrideConfig
816+ ) ;
817+ expect ( result . properties ) . toHaveProperty ( 'url' , 'https://dev-backend.example.com' ) ;
818+ } ) ;
819+
820+ it ( 'should detect named value overrides within a workspace scope' , ( ) => {
821+ expect ( hasNamedValueOverride ( 'my-nv' , overrideConfig , 'my-workspace' ) ) . toBe ( true ) ;
822+ expect ( hasNamedValueOverride ( 'my-nv' , overrideConfig ) ) . toBe ( false ) ;
823+ expect ( hasNamedValueOverride ( 'my-nv' , overrideConfig , 'other-workspace' ) ) . toBe ( false ) ;
881824 } ) ;
882825 } ) ;
883826} ) ;
0 commit comments