diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/AWSS3StoragePluginAsyncBehaviorTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/AWSS3StoragePluginAsyncBehaviorTests.swift index 001883ce09..6edc1cce12 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/AWSS3StoragePluginAsyncBehaviorTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/AWSS3StoragePluginAsyncBehaviorTests.swift @@ -114,4 +114,22 @@ class AWSS3StoragePluginAsyncBehaviorTests: XCTestCase { XCTAssertEqual(1, storageService.interactions.count) } + /// - Given: A plugin configured with a mocked service + /// - When: The list API is invoked with subpathStrategy set to .exclude + /// - Then: The list of excluded subpaths and the list of items should be populated + func testPluginListWithCommonPrefixesAsync() async throws { + storageService.listHandler = { (_, _) in + return .init( + items: [.init(path: "path")], + excludedSubpaths: ["subpath1", "subpath2"] + ) + } + let output = try await storagePlugin.list(options: .init(subpathStrategy: .exclude)) + XCTAssertEqual(1, output.items.count, String(describing: output)) + XCTAssertEqual("path", output.items.first?.path) + XCTAssertEqual(2, output.excludedSubpaths.count) + XCTAssertEqual("subpath1", output.excludedSubpaths[0]) + XCTAssertEqual("subpath2", output.excludedSubpaths[1]) + XCTAssertEqual(1, storageService.interactions.count) + } } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Tasks/AWSS3StorageListObjectsTaskTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Tasks/AWSS3StorageListObjectsTaskTests.swift index 922f29974c..10d059d368 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Tasks/AWSS3StorageListObjectsTaskTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Tasks/AWSS3StorageListObjectsTaskTests.swift @@ -38,6 +38,7 @@ class AWSS3StorageListObjectsTaskTests: XCTestCase { storageBehaviour: serviceMock) let value = try await task.value XCTAssertEqual(value.items.count, 2) + XCTAssertTrue(value.excludedSubpaths.isEmpty) XCTAssertEqual(value.nextToken, "continuationToken") XCTAssertEqual(value.items[0].eTag, "tag") XCTAssertEqual(value.items[0].key, "key") @@ -130,4 +131,81 @@ class AWSS3StorageListObjectsTaskTests: XCTestCase { XCTAssertEqual(field, "path", "Field in error should be `path`") } } + + /// - Given: A configured Storage List Objects Task with mocked service + /// - When: AWSS3StorageListObjectsTask value is invoked with subpathStrategy set to .exclude + /// - Then: The delimiter should be set, the list of excluded subpaths and the list of items should be populated + func testListObjectsTask_withSubpathStrategyExclude_shouldSucceed() async throws { + let serviceMock = MockAWSS3StorageService() + let client = serviceMock.client as! MockS3Client + client.listObjectsV2Handler = { input in + XCTAssertNotNil(input.delimiter, "Expected delimiter to be set") + return .init( + commonPrefixes: [ + .init(prefix: "path/subpath1/"), + .init(prefix: "path/subpath2/") + ], + contents: [ + .init(eTag: "tag", key: "path/result", lastModified: Date()) + ], + nextContinuationToken: "continuationToken" + ) + } + + let request = StorageListRequest( + path: StringStoragePath.fromString("path/"), + options: .init( + subpathStrategy: .exclude + ) + ) + let task = AWSS3StorageListObjectsTask( + request, + storageConfiguration: AWSS3StoragePluginConfiguration(), + storageBehaviour: serviceMock + ) + let value = try await task.value + XCTAssertEqual(value.items.count, 1) + XCTAssertEqual(value.items[0].eTag, "tag") + XCTAssertEqual(value.items[0].path, "path/result") + XCTAssertNotNil(value.items[0].lastModified) + XCTAssertEqual(value.excludedSubpaths.count, 2) + XCTAssertEqual(value.excludedSubpaths[0], "path/subpath1/") + XCTAssertEqual(value.excludedSubpaths[1], "path/subpath2/") + XCTAssertEqual(value.nextToken, "continuationToken") + } + + /// - Given: A configured Storage List Objects Task with mocked service + /// - When: AWSS3StorageListObjectsTask value is invoked with subpathStrategy set to .include + /// - Then: The delimiter should not be set, the list of excluded subpaths should be empty and the list of items should be populated + func testListObjectsTask_withSubpathStrategyInclude_shouldSucceed() async throws { + let serviceMock = MockAWSS3StorageService() + let client = serviceMock.client as! MockS3Client + client.listObjectsV2Handler = { input in + XCTAssertNil(input.delimiter, "Expected delimiter to be nil") + return .init( + contents: [ + .init(eTag: "tag", key: "path", lastModified: Date()), + ], + nextContinuationToken: "continuationToken" + ) + } + + let request = StorageListRequest( + path: StringStoragePath.fromString("path"), + options: .init( + subpathStrategy: .include + ) + ) + let task = AWSS3StorageListObjectsTask( + request, + storageConfiguration: AWSS3StoragePluginConfiguration(), + storageBehaviour: serviceMock) + let value = try await task.value + XCTAssertEqual(value.items.count, 1) + XCTAssertEqual(value.items[0].eTag, "tag") + XCTAssertEqual(value.items[0].path, "path") + XCTAssertNotNil(value.items[0].lastModified) + XCTAssertTrue(value.excludedSubpaths.isEmpty) + XCTAssertEqual(value.nextToken, "continuationToken") + } }