@contrail/flexplm 1.4.0 → 1.5.0-alpha.0d65410

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -509,6 +509,463 @@ describe('getObjectReferenceValue bad value', () =>{
509
509
 
510
510
  });
511
511
 
512
+ describe('setObjectReferenceValue - identity service', () => {
513
+ const baseConfig = (): FCConfig => ({
514
+ apiHost: 'host',
515
+ userName: () => 'user',
516
+ password: () => 'pass',
517
+ urlContext: 'xxx',
518
+ vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
519
+ csrfEndpoint: '/servlet/rest/security/csrf',
520
+ itemPreDevelopmentLifecycleStages: ['concept']
521
+ });
522
+
523
+ const refProp = {
524
+ id: 'cJoZQvoj7dkfCBJq',
525
+ propertyType: 'object_reference',
526
+ slug: 'material',
527
+ label: 'Material',
528
+ referencedTypeRootSlug: 'item',
529
+ referencedTypePath: 'item:material'
530
+ };
531
+
532
+ let identifierSpy: jest.SpyInstance;
533
+ let poolKeySpy: jest.SpyInstance;
534
+ let getByRootAndPathSpy: jest.SpyInstance;
535
+ let filterTypePropertiesSpy: jest.SpyInstance;
536
+
537
+ const setupTypeUtilsSpies = (dc: DataConverter, rootPropSlugs: string[] = ['itemNumber']) => {
538
+ getByRootAndPathSpy = jest.spyOn(dc['typeUtils'], 'getByRootAndPath')
539
+ .mockImplementation(async () => ({ typePath: 'item', typeProperties: [] }) as any);
540
+ filterTypePropertiesSpy = jest.spyOn(dc['typeUtils'], 'filterTypeProperties')
541
+ .mockImplementation(() => rootPropSlugs.map(slug => ({ slug })) as any);
542
+ };
543
+
544
+ afterEach(() => {
545
+ identifierSpy?.mockRestore();
546
+ poolKeySpy?.mockRestore();
547
+ getByRootAndPathSpy?.mockRestore();
548
+ filterTypePropertiesSpy?.mockRestore();
549
+ mockGetFunction.mockReset();
550
+ mockGetFunction.mockImplementation((options) =>
551
+ ((options?.criteria?.id === 1234) ? [mockObj1234] : [mockObj2222]) as any
552
+ );
553
+ });
554
+
555
+ it('flag off - uses getAllObjectReferences path', async () => {
556
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
557
+ setupTypeUtilsSpies(dc, ['itemNumber', 'roles']);
558
+
559
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
560
+ .mockImplementation(async () => ['itemNumber', 'roles']);
561
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
562
+ .mockImplementation(async () => 'item:material');
563
+
564
+ mockGetFunction.mockClear();
565
+ mockGetFunction.mockImplementation(() => [{ id: 'abc123', typePath: 'item:material' }] as any);
566
+
567
+ const nd = { itemNumber: 'MAT-100', roles: ['family'] };
568
+ const result = await dc.setObjectReferenceValue(refProp, nd);
569
+
570
+ expect(mockGetFunction).toHaveBeenCalled();
571
+ const callArg = mockGetFunction.mock.calls[0][0];
572
+ expect(callArg.entityName).toEqual('item');
573
+ expect(callArg.entityName).not.toEqual('identity');
574
+ expect(result).toEqual('abc123');
575
+ expect(poolKeySpy).not.toHaveBeenCalled();
576
+ });
577
+
578
+ it('flag on, single identity match - returns parsed id', async () => {
579
+ const config = baseConfig();
580
+ config.search = { item: { useIdentityServiceForInboundData: true } };
581
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
582
+ setupTypeUtilsSpies(dc);
583
+
584
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
585
+ .mockImplementation(async () => ['itemNumber', 'roles']);
586
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
587
+ .mockImplementation(async () => 'item:material');
588
+
589
+ mockGetFunction.mockClear();
590
+ mockGetFunction.mockImplementation(() => [{ entityReference: 'item:abc123' }] as any);
591
+
592
+ const nd = { itemNumber: 'MAT-100', roles: ['family'] };
593
+ const result = await dc.setObjectReferenceValue(refProp, nd);
594
+
595
+ expect(mockGetFunction).toHaveBeenCalledTimes(1);
596
+ const callArg = mockGetFunction.mock.calls[0][0];
597
+ expect(callArg.entityName).toEqual('identity');
598
+ expect(callArg.criteria).toEqual({
599
+ poolKey: 'item:material',
600
+ propertyName: 'itemNumber',
601
+ propertyValue: 'MAT-100'
602
+ });
603
+ expect(result).toEqual('abc123');
604
+ });
605
+
606
+ it('flag on, no identity match - returns empty and warns', async () => {
607
+ const config = baseConfig();
608
+ config.search = { item: { useIdentityServiceForInboundData: true } };
609
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
610
+ setupTypeUtilsSpies(dc);
611
+
612
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
613
+ .mockImplementation(async () => ['itemNumber', 'roles']);
614
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
615
+ .mockImplementation(async () => 'item:material');
616
+
617
+ mockGetFunction.mockClear();
618
+ mockGetFunction.mockImplementation(() => [] as any);
619
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
620
+ const getAllSpy = jest.spyOn(dc, 'getAllObjectReferences');
621
+
622
+ try {
623
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', roles: ['family'] });
624
+ expect(result).toEqual('');
625
+ expect(warnSpy).toHaveBeenCalled();
626
+ expect(getAllSpy).not.toHaveBeenCalled();
627
+ } finally {
628
+ warnSpy.mockRestore();
629
+ getAllSpy.mockRestore();
630
+ }
631
+ });
632
+
633
+ it('flag on, multiple identity matches - returns empty and does not throw', async () => {
634
+ const config = baseConfig();
635
+ config.search = { item: { useIdentityServiceForInboundData: true } };
636
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
637
+ setupTypeUtilsSpies(dc);
638
+
639
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
640
+ .mockImplementation(async () => ['itemNumber', 'roles']);
641
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
642
+ .mockImplementation(async () => 'item:material');
643
+
644
+ mockGetFunction.mockClear();
645
+ mockGetFunction.mockImplementation(() => [
646
+ { entityReference: 'item:abc123' },
647
+ { entityReference: 'item:def456' }
648
+ ] as any);
649
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
650
+
651
+ try {
652
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', roles: ['family'] });
653
+ expect(result).toEqual('');
654
+ expect(warnSpy).toHaveBeenCalled();
655
+ } finally {
656
+ warnSpy.mockRestore();
657
+ }
658
+ });
659
+
660
+ it('flag on, ambiguous identifier set - falls back to getAllObjectReferences', async () => {
661
+ const config = baseConfig();
662
+ config.search = { item: { useIdentityServiceForInboundData: true } };
663
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
664
+ setupTypeUtilsSpies(dc, ['itemNumber', 'season', 'roles']);
665
+
666
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
667
+ .mockImplementation(async () => ['itemNumber', 'season', 'roles']);
668
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
669
+ .mockImplementation(async () => 'item:material');
670
+
671
+ mockGetFunction.mockClear();
672
+ mockGetFunction.mockImplementation(() => [{ id: 'abc123', typePath: 'item:material' }] as any);
673
+
674
+ const nd = { itemNumber: 'MAT-100', season: 'SS24', roles: ['family'] };
675
+ const result = await dc.setObjectReferenceValue(refProp, nd);
676
+
677
+ expect(mockGetFunction).toHaveBeenCalled();
678
+ const callArg = mockGetFunction.mock.calls[0][0];
679
+ expect(callArg.entityName).toEqual('item');
680
+ expect(callArg.entityName).not.toEqual('identity');
681
+ expect(result).toEqual('abc123');
682
+ expect(poolKeySpy).not.toHaveBeenCalled();
683
+ });
684
+
685
+ it('flag on, cache hit - second call short-circuits', async () => {
686
+ const config = baseConfig();
687
+ config.search = { item: { useIdentityServiceForInboundData: true } };
688
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
689
+ setupTypeUtilsSpies(dc);
690
+
691
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
692
+ .mockImplementation(async () => ['itemNumber', 'roles']);
693
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
694
+ .mockImplementation(async () => 'item:material');
695
+
696
+ mockGetFunction.mockClear();
697
+ mockGetFunction.mockImplementation(() => [{ entityReference: 'item:abc123' }] as any);
698
+
699
+ const nd = { itemNumber: 'MAT-100', roles: ['family'] };
700
+ const r1 = await dc.setObjectReferenceValue(refProp, nd);
701
+ const r2 = await dc.setObjectReferenceValue(refProp, nd);
702
+
703
+ expect(r1).toEqual('abc123');
704
+ expect(r2).toEqual('abc123');
705
+ expect(mockGetFunction).toHaveBeenCalledTimes(1);
706
+ });
707
+
708
+ it('flag on, project-item entityType - roles is filtered, identity path used', async () => {
709
+ const projectItemProp = {
710
+ ...refProp,
711
+ referencedTypeRootSlug: 'project-item',
712
+ referencedTypePath: 'project-item'
713
+ };
714
+ const config = baseConfig();
715
+ config.search = { 'project-item': { useIdentityServiceForInboundData: true } };
716
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
717
+ setupTypeUtilsSpies(dc, ['itemNumber', 'roles']);
718
+
719
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
720
+ .mockImplementation(async () => ['itemNumber', 'roles']);
721
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
722
+ .mockImplementation(async () => 'project-item');
723
+
724
+ mockGetFunction.mockClear();
725
+ mockGetFunction.mockImplementation(() => [{ entityReference: 'project-item:pi-789' }] as any);
726
+
727
+ const result = await dc.setObjectReferenceValue(projectItemProp, { itemNumber: 'X1', roles: ['family'] });
728
+
729
+ expect(mockGetFunction).toHaveBeenCalledTimes(1);
730
+ const callArg = mockGetFunction.mock.calls[0][0];
731
+ expect(callArg.entityName).toEqual('identity');
732
+ expect(callArg.criteria.propertyName).toEqual('itemNumber');
733
+ expect(result).toEqual('pi-789');
734
+ });
735
+
736
+ it('flag on, non-item entityType - roles is NOT filtered, falls back to query path', async () => {
737
+ const colorProp = {
738
+ ...refProp,
739
+ referencedTypeRootSlug: 'color',
740
+ referencedTypePath: 'color'
741
+ };
742
+ const config = baseConfig();
743
+ config.search = { color: { useIdentityServiceForInboundData: true } };
744
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
745
+ setupTypeUtilsSpies(dc, ['colorNumber', 'roles']);
746
+
747
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
748
+ .mockImplementation(async () => ['colorNumber', 'roles']);
749
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
750
+ .mockImplementation(async () => 'color');
751
+
752
+ mockGetFunction.mockClear();
753
+ mockGetFunction.mockImplementation(() => [{ id: 'col-1', typePath: 'color' }] as any);
754
+
755
+ const result = await dc.setObjectReferenceValue(colorProp, { colorNumber: 'C1', roles: ['family'] });
756
+
757
+ expect(mockGetFunction).toHaveBeenCalled();
758
+ const callArg = mockGetFunction.mock.calls[0][0];
759
+ expect(callArg.entityName).toEqual('color');
760
+ expect(callArg.entityName).not.toEqual('identity');
761
+ expect(result).toEqual('col-1');
762
+ expect(poolKeySpy).not.toHaveBeenCalled();
763
+ });
764
+
765
+ it('query path, multiple matches - returns empty with single warn (no double warn)', async () => {
766
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
767
+ setupTypeUtilsSpies(dc, ['itemNumber']);
768
+
769
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
770
+ .mockImplementation(async () => ['itemNumber']);
771
+
772
+ mockGetFunction.mockClear();
773
+ mockGetFunction.mockImplementation(() => [
774
+ { id: 'a1', typePath: 'item:material' },
775
+ { id: 'a2', typePath: 'item:material' }
776
+ ] as any);
777
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
778
+
779
+ try {
780
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100' });
781
+ expect(result).toEqual('');
782
+ expect(warnSpy).toHaveBeenCalledTimes(1);
783
+ expect(warnSpy.mock.calls[0][0]).toMatch(/duplicate records/);
784
+ } finally {
785
+ warnSpy.mockRestore();
786
+ }
787
+ });
788
+
789
+ it('flag on, identity returns null - normalized to empty array, returns empty', async () => {
790
+ const config = baseConfig();
791
+ config.search = { item: { useIdentityServiceForInboundData: true } };
792
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
793
+ setupTypeUtilsSpies(dc);
794
+
795
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
796
+ .mockImplementation(async () => ['itemNumber', 'roles']);
797
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
798
+ .mockImplementation(async () => 'item:material');
799
+
800
+ mockGetFunction.mockClear();
801
+ mockGetFunction.mockImplementation(() => null as any);
802
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
803
+
804
+ try {
805
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', roles: ['family'] });
806
+ expect(result).toEqual('');
807
+ expect(warnSpy).toHaveBeenCalled();
808
+ } finally {
809
+ warnSpy.mockRestore();
810
+ }
811
+ });
812
+
813
+ it('null nd - returns empty string and does not query', async () => {
814
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
815
+ mockGetFunction.mockClear();
816
+ const result = await dc.setObjectReferenceValue(refProp, null);
817
+ expect(result).toEqual('');
818
+ expect(mockGetFunction).not.toHaveBeenCalled();
819
+ });
820
+
821
+ it('zero identifier keys - warns and returns empty string', async () => {
822
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
823
+ setupTypeUtilsSpies(dc);
824
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
825
+ .mockImplementation(async () => []);
826
+ mockGetFunction.mockClear();
827
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
828
+
829
+ try {
830
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100' });
831
+ expect(result).toEqual('');
832
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringMatching(/doesnt have all "identifier" properties/));
833
+ expect(mockGetFunction).not.toHaveBeenCalled();
834
+ } finally {
835
+ warnSpy.mockRestore();
836
+ }
837
+ });
838
+
839
+ it('missing identifier keys on nd - warns and returns empty string', async () => {
840
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
841
+ setupTypeUtilsSpies(dc);
842
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
843
+ .mockImplementation(async () => ['itemNumber', 'season']);
844
+ mockGetFunction.mockClear();
845
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
846
+
847
+ try {
848
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100' });
849
+ expect(result).toEqual('');
850
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringMatching(/doesnt have all "identifier" properties/));
851
+ expect(mockGetFunction).not.toHaveBeenCalled();
852
+ } finally {
853
+ warnSpy.mockRestore();
854
+ }
855
+ });
856
+
857
+ it('transformMapFile set - applyInboundTransformMap is invoked before context build', async () => {
858
+ const config = baseConfig();
859
+ config['transformMapFile'] = 'file1';
860
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
861
+ setupTypeUtilsSpies(dc, ['itemNumber', 'roles']);
862
+
863
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
864
+ .mockImplementation(async () => ['itemNumber', 'roles']);
865
+ const mapKeySpy = jest.spyOn(TypeConversionUtils, 'getMapKeyFromObject')
866
+ .mockImplementation(async () => 'LCSMaterial');
867
+ const applyMapSpy = jest.spyOn(MapUtil, 'applyTransformMap')
868
+ .mockImplementation(async (...args) => args[2]);
869
+
870
+ mockGetFunction.mockClear();
871
+ mockGetFunction.mockImplementation(() => [{ id: 'q-1', typePath: 'item:material' }] as any);
872
+
873
+ try {
874
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', roles: ['family'] });
875
+ expect(mapKeySpy).toHaveBeenCalledTimes(1);
876
+ expect(applyMapSpy).toHaveBeenCalledTimes(1);
877
+ expect(applyMapSpy.mock.calls[0][3]).toEqual('LCSMaterial');
878
+ expect(result).toEqual('q-1');
879
+ } finally {
880
+ mapKeySpy.mockRestore();
881
+ applyMapSpy.mockRestore();
882
+ }
883
+ });
884
+
885
+ it('transformMapFile unset - applyInboundTransformMap does not invoke map utilities', async () => {
886
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
887
+ setupTypeUtilsSpies(dc, ['itemNumber', 'roles']);
888
+
889
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
890
+ .mockImplementation(async () => ['itemNumber', 'roles']);
891
+ const mapKeySpy = jest.spyOn(TypeConversionUtils, 'getMapKeyFromObject');
892
+ const applyMapSpy = jest.spyOn(MapUtil, 'applyTransformMap');
893
+
894
+ mockGetFunction.mockClear();
895
+ mockGetFunction.mockImplementation(() => [{ id: 'q-2', typePath: 'item:material' }] as any);
896
+
897
+ try {
898
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', roles: ['family'] });
899
+ expect(mapKeySpy).not.toHaveBeenCalled();
900
+ expect(applyMapSpy).not.toHaveBeenCalled();
901
+ expect(result).toEqual('q-2');
902
+ } finally {
903
+ mapKeySpy.mockRestore();
904
+ applyMapSpy.mockRestore();
905
+ }
906
+ });
907
+
908
+ it('query path success - writes id to cache (second call short-circuits)', async () => {
909
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
910
+ setupTypeUtilsSpies(dc, ['itemNumber', 'roles']);
911
+
912
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
913
+ .mockImplementation(async () => ['itemNumber', 'roles']);
914
+
915
+ mockGetFunction.mockClear();
916
+ mockGetFunction.mockImplementation(() => [{ id: 'cached-q', typePath: 'item:material' }] as any);
917
+
918
+ const nd = { itemNumber: 'MAT-100', roles: ['family'] };
919
+ const r1 = await dc.setObjectReferenceValue(refProp, nd);
920
+ const callsAfterFirst = mockGetFunction.mock.calls.length;
921
+ const r2 = await dc.setObjectReferenceValue(refProp, nd);
922
+
923
+ expect(r1).toEqual('cached-q');
924
+ expect(r2).toEqual('cached-q');
925
+ expect(mockGetFunction.mock.calls.length).toEqual(callsAfterFirst);
926
+ });
927
+
928
+ it('query path with subtype filter - applies checkKeysAndValues when entityType !== entityTypePath', async () => {
929
+ const dc = new DataConverter(baseConfig(), new MapFileUtil(new Entities()));
930
+ setupTypeUtilsSpies(dc, ['itemNumber']);
931
+
932
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
933
+ .mockImplementation(async () => ['itemNumber', 'season']);
934
+ const checkSpy = jest.spyOn(dc, 'checkKeysAndValues')
935
+ .mockImplementation((_criteria, arr) => arr);
936
+
937
+ mockGetFunction.mockClear();
938
+ mockGetFunction.mockImplementation(() => [{ id: 'sub-1', typePath: 'item:material' }] as any);
939
+
940
+ try {
941
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', season: 'SS24' });
942
+ expect(checkSpy).toHaveBeenCalledTimes(1);
943
+ expect(checkSpy.mock.calls[0][2]).toEqual('item:material');
944
+ expect(result).toEqual('sub-1');
945
+ } finally {
946
+ checkSpy.mockRestore();
947
+ }
948
+ });
949
+
950
+ it('pickSingleResult single result - identity branch parses id from entityReference', async () => {
951
+ const config = baseConfig();
952
+ config.search = { item: { useIdentityServiceForInboundData: true } };
953
+ const dc = new DataConverter(config, new MapFileUtil(new Entities()));
954
+ setupTypeUtilsSpies(dc);
955
+
956
+ identifierSpy = jest.spyOn(TypeConversionUtils, 'getIdentifierPropertiesFromObject')
957
+ .mockImplementation(async () => ['itemNumber', 'roles']);
958
+ poolKeySpy = jest.spyOn(TypeConversionUtils, 'getUniquenessPoolKeyFromObject')
959
+ .mockImplementation(async () => 'item:material');
960
+
961
+ mockGetFunction.mockClear();
962
+ mockGetFunction.mockImplementation(() => [{ entityReference: 'item:parsed-id-from-ref' }] as any);
963
+
964
+ const result = await dc.setObjectReferenceValue(refProp, { itemNumber: 'MAT-100', roles: ['family'] });
965
+ expect(result).toEqual('parsed-id-from-ref');
966
+ });
967
+ });
968
+
512
969
  describe('getObjectReferenceValue - use mapping', () => {
513
970
 
514
971
  const maps = require('./data-converter-spec-mockData');
@@ -594,6 +1051,51 @@ describe('getObjectReferenceValue - use mapping', () => {
594
1051
  });
595
1052
  });
596
1053
 
1054
+ describe('getEntityValues', () => {
1055
+ const config: FCConfig = {
1056
+ apiHost: 'host',
1057
+ userName: () => 'user',
1058
+ password: () => 'pass',
1059
+ urlContext: 'xxx',
1060
+ vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
1061
+ csrfEndpoint: '/servlet/rest/security/csrf',
1062
+ itemPreDevelopmentLifecycleStages: ['concept']
1063
+ };
1064
+ const mapFileUtil = new MapFileUtil(new Entities());
1065
+ const dc = new DataConverter(config, mapFileUtil);
1066
+
1067
+ const runWithStubs = async (typePath: string, objectClass: string, data: any) => {
1068
+ const tcoSpy = jest.spyOn(dc['typeUtils'], 'getEntityTypeClientOptionsUsingMapping')
1069
+ .mockImplementation(async () => ({ root: 'item' }));
1070
+ const typeSpy = jest.spyOn(dc['typeUtils'], 'getByRootAndPath')
1071
+ .mockImplementation(async () => ({ typePath, typeProperties: [] }));
1072
+ const filterSpy = jest.spyOn(dc['typeUtils'], 'filterTypeProperties')
1073
+ .mockImplementation(() => []);
1074
+ try {
1075
+ return await dc.getEntityValues(objectClass, data);
1076
+ } finally {
1077
+ tcoSpy.mockRestore();
1078
+ typeSpy.mockRestore();
1079
+ filterSpy.mockRestore();
1080
+ }
1081
+ };
1082
+
1083
+ it('LCSProduct -> roles family', async () => {
1084
+ const result = await runWithStubs('item', 'LCSProduct', { itemNumber: 'X1' });
1085
+ expect(result['roles']).toEqual(['family']);
1086
+ });
1087
+
1088
+ it('LCSSKU -> roles color, option', async () => {
1089
+ const result = await runWithStubs('item', 'LCSSKU', { itemNumber: 'X1' });
1090
+ expect(result['roles']).toEqual(['color', 'option']);
1091
+ });
1092
+
1093
+ it('LCSMaterial -> roles family', async () => {
1094
+ const result = await runWithStubs('item:material', 'LCSMaterial', { itemNumber: 'MAT-100' });
1095
+ expect(result['roles']).toEqual(['family']);
1096
+ });
1097
+ });
1098
+
597
1099
  describe('setEnumerationKeys', () =>{
598
1100
  const config: FCConfig = {
599
1101
  apiHost: 'host',