1- import { GetResourceCommandOutput , ResourceNotFoundException } from '@aws-sdk/client-cloudcontrol' ;
1+ import {
2+ GetResourceCommandOutput ,
3+ PrivateTypeException ,
4+ ResourceNotFoundException ,
5+ } from '@aws-sdk/client-cloudcontrol' ;
26import { DateTime } from 'luxon' ;
37import { afterEach , beforeEach , describe , expect , it , vi } from 'vitest' ;
8+ import { ResponseError } from 'vscode-languageserver' ;
49import { ResourceStateManager } from '../../../src/resourceState/ResourceStateManager' ;
510import { CombinedSchemas } from '../../../src/schema/CombinedSchemas' ;
611import { CcapiService } from '../../../src/services/CcapiService' ;
712import { S3Service } from '../../../src/services/S3Service' ;
813import { createMockSchemaRetriever } from '../../utils/MockServerComponents' ;
14+ import { combinedSchemas } from '../../utils/SchemaUtils' ;
915
1016describe ( 'ResourceStateManager' , ( ) => {
1117 const mockCcapiService = {
@@ -175,6 +181,19 @@ describe('ResourceStateManager', () => {
175181
176182 expect ( result ) . toBeUndefined ( ) ;
177183 } ) ;
184+
185+ it ( 'should handle private resource exceptions' , async ( ) => {
186+ const error = new PrivateTypeException ( {
187+ message : 'Private type error' ,
188+ $metadata : { } ,
189+ } ) ;
190+ vi . mocked ( mockCcapiService . listResources ) . mockRejectedValue ( error ) ;
191+
192+ await expect ( manager . listResources ( 'MyOrg::Custom::Resource' ) ) . rejects . toThrow ( ResponseError ) ;
193+ await expect ( manager . listResources ( 'MyOrg::Custom::Resource' ) ) . rejects . toThrow (
194+ "Failed to list identifiers for MyOrg::Custom::Resource. Cloud Control API hasn't received a valid response from the resource handler, due to a configuration error. This includes issues such as the resource handler returning an invalid response, or timing out." ,
195+ ) ;
196+ } ) ;
178197 } ) ;
179198
180199 describe ( 'searchResourceByIdentifier()' , ( ) => {
@@ -427,9 +446,9 @@ describe('ResourceStateManager', () => {
427446 it ( 'should filter out resource types without list support' , ( ) => {
428447 const mockSchemas : CombinedSchemas = {
429448 schemas : new Map ( [
430- [ 'AWS::S3::Bucket' , { } ] ,
431- [ 'AWS::IAM::Role' , { } ] ,
432- [ 'AWS::IAM::RolePolicy' , { } ] ,
449+ [ 'AWS::S3::Bucket' , { typeName : 'AWS::S3::Bucket' , handlers : { list : { } } } ] ,
450+ [ 'AWS::IAM::Role' , { typeName : 'AWS::IAM::Role' , handlers : { list : { } } } ] ,
451+ [ 'AWS::IAM::RolePolicy' , { typeName : 'AWS::IAM::RolePolicy' , handlers : { list : { } } } ] ,
433452 ] ) ,
434453 } as CombinedSchemas ;
435454 const managerWithSchemas = new ResourceStateManager (
@@ -448,9 +467,9 @@ describe('ResourceStateManager', () => {
448467 it ( 'should filter out resource types requiring resource model properties' , ( ) => {
449468 const mockSchemas : CombinedSchemas = {
450469 schemas : new Map ( [
451- [ 'AWS::S3::Bucket' , { } ] ,
452- [ 'AWS::EKS::Cluster' , { } ] ,
453- [ 'AWS::EKS::AddOn' , { } ] ,
470+ [ 'AWS::S3::Bucket' , { typeName : 'AWS::S3::Bucket' , handlers : { list : { } } } ] ,
471+ [ 'AWS::EKS::Cluster' , { typeName : 'AWS::EKS::Cluster' , handlers : { list : { } } } ] ,
472+ [ 'AWS::EKS::AddOn' , { typeName : 'AWS::EKS::AddOn' , handlers : { list : { } } } ] ,
454473 ] ) ,
455474 } as CombinedSchemas ;
456475 const managerWithSchemas = new ResourceStateManager (
@@ -465,5 +484,40 @@ describe('ResourceStateManager', () => {
465484 expect ( result ) . toContain ( 'AWS::EKS::Cluster' ) ;
466485 expect ( result ) . not . toContain ( 'AWS::EKS::AddOn' ) ;
467486 } ) ;
487+
488+ it ( 'should return all supported public types' , ( ) => {
489+ const testSchemas = combinedSchemas ( ) ;
490+ const resourceManagerWithRealSchemas = new ResourceStateManager (
491+ mockCcapiService ,
492+ createMockSchemaRetriever ( testSchemas ) ,
493+ mockS3Service ,
494+ ) ;
495+
496+ const result = resourceManagerWithRealSchemas . getResourceTypes ( ) ;
497+
498+ expect ( result ) . toContain ( 'AWS::S3::Bucket' ) ;
499+ expect ( result ) . toContain ( 'AWS::IAM::Role' ) ;
500+ expect ( result ) . toContain ( 'AWS::Lambda::Function' ) ;
501+ expect ( result . every ( ( type ) => type . startsWith ( 'AWS::' ) ) ) . toBe ( true ) ;
502+ } ) ;
503+
504+ it ( 'should not return private resource types with no list handler permissions' , ( ) => {
505+ const mockSchemas : CombinedSchemas = {
506+ schemas : new Map ( [
507+ [ 'AWS::S3::Bucket' , { typeName : 'AWS::S3::Bucket' , handlers : { list : { } } } ] ,
508+ [ 'MyOrg::Custom::Resource' , { typeName : 'MyOrg::Custom::Resource' } ] ,
509+ ] ) ,
510+ } as CombinedSchemas ;
511+ const managerWithSchemas = new ResourceStateManager (
512+ mockCcapiService ,
513+ createMockSchemaRetriever ( mockSchemas ) ,
514+ mockS3Service ,
515+ ) ;
516+
517+ const result = managerWithSchemas . getResourceTypes ( ) ;
518+
519+ expect ( result ) . toContain ( 'AWS::S3::Bucket' ) ;
520+ expect ( result ) . not . toContain ( 'MyOrg::Custom::Resource' ) ;
521+ } ) ;
468522 } ) ;
469523} ) ;
0 commit comments