From 7c3b6df8b9b19c7de240188a0fb62b526794b38c Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 10:18:03 +0530 Subject: [PATCH 1/9] fix(entity): null-safe updateColumns for entities without columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PATCH on a File without columns (PDF/image/etc.) NPEs in ColumnEntityUpdater.updateColumns because FileRepository.entitySpecificUpdate unconditionally invokes the columns updater. recordListChange already null-coalesces internally, but the subsequent `for (Column updated : updatedColumns)` iteration does not — any updater calling updateColumns with a null list hits the same path. Null-coalesce origColumns and updatedColumns at the top of ColumnEntityUpdater.updateColumns so any optional-columns entity is safe. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../openmetadata/it/tests/FileResourceIT.java | 26 +++++++++++++++++++ .../service/jdbi3/EntityRepository.java | 2 ++ 2 files changed, 28 insertions(+) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java index da75ae9acd04..94bb1aa531c7 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java @@ -421,4 +421,30 @@ void test_createPdfFileWithoutColumns(TestNamespace ns) { // PDF files should not have columns assertNull(createdFile.getColumns()); } + + @Test + void test_patchFileWithoutColumns_doesNotNpe(TestNamespace ns) { + // Regression: PATCH on a file without columns must not NPE in + // ColumnEntityUpdater.updateColumns. Reproduces the failure seen when + // editing tags/description on PDF/image files (no columns defined). + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + String fileName = ns.prefix("patch_no_columns"); + File createdFile = + Files.create() + .name(fileName) + .withService(driveService.getFullyQualifiedName()) + .withFileType(FileType.PDF) + .withMimeType("application/pdf") + .withDescription("Initial description") + .execute(); + + assertNull(createdFile.getColumns()); + + createdFile.setDescription("Updated description"); + File patched = SdkClients.adminClient().files().update(createdFile.getId(), createdFile); + + assertEquals("Updated description", patched.getDescription()); + assertNull(patched.getColumns()); + } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java index a02f786c1573..bbcd40434df1 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java @@ -8746,6 +8746,8 @@ public void updateColumns( List origColumns, List updatedColumns, BiPredicate columnMatch) { + origColumns = listOrEmpty(origColumns); + updatedColumns = listOrEmpty(updatedColumns); List deletedColumns = new ArrayList<>(); List addedColumns = new ArrayList<>(); HashMap originalUpdatedColumnFqns = new HashMap<>(); From f9adbaa4d3e6fb94837b42c8cf34c136b3a44c3e Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 10:22:03 +0530 Subject: [PATCH 2/9] test(entity): generic PATCH-add-tag and PATCH-add-glossary-term coverage Add two generic tests to BaseEntityIT that any entity inheriting from it must pass: - patch_addClassificationTag_200_OK - patch_addGlossaryTerm_200_OK Both create a minimal entity, set a single tag/glossary-term label, PATCH, and assert the label is present. Gated on supportsTags && supportsPatch, so an entity that opts out keeps doing so. This gives every new EntityRepository subclass (e.g. the next entity type someone adds) automatic defense against the class of bug where the tag/glossary PATCH path NPEs on an unrelated optional field (updateColumns with null columns being the original instance). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../openmetadata/it/tests/BaseEntityIT.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java index 046896796584..75d4b6c686d0 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java @@ -1083,6 +1083,50 @@ void test_entityWithInvalidTag(TestNamespace ns) { "Patching entity with invalid tag should fail"); } + /** + * Generic regression: adding a classification tag via PATCH must succeed for any entity + * regardless of which optional fields (columns, dataModel, etc.) are populated. New + * EntityRepository subclasses get this coverage automatically by extending BaseEntityIT. + */ + @Test + void patch_addClassificationTag_200_OK(TestNamespace ns) { + if (!supportsTags || !supportsPatch) { + return; + } + + T entity = createEntity(createMinimalRequest(ns)); + TagLabel tag = personalDataTagLabel(); + entity.setTags(List.of(tag)); + + T patched = patchEntity(entity.getId().toString(), entity); + + T fetched = getEntityWithFields(patched.getId().toString(), "tags"); + assertNotNull(fetched.getTags(), "tags should not be null after PATCH"); + assertTagsContain(fetched.getTags(), List.of(tag)); + } + + /** + * Generic regression: adding a glossary term via PATCH must succeed for any entity. Mirrors + * the classification-tag test but with TagSource.GLOSSARY, which exercises a different + * server-side application path. + */ + @Test + void patch_addGlossaryTerm_200_OK(TestNamespace ns) { + if (!supportsTags || !supportsPatch) { + return; + } + + T entity = createEntity(createMinimalRequest(ns)); + TagLabel term = glossaryTermLabel(); + entity.setTags(List.of(term)); + + T patched = patchEntity(entity.getId().toString(), entity); + + T fetched = getEntityWithFields(patched.getId().toString(), "tags"); + assertNotNull(fetched.getTags(), "tags should not be null after PATCH"); + assertTagsContain(fetched.getTags(), List.of(term)); + } + @Test void test_tagUpdateOptimization_PUT(TestNamespace ns) { if (!supportsTags) { From 793b30a7fea9f98a604d134a8256c05015a169b6 Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 11:06:24 +0530 Subject: [PATCH 3/9] test(it): migrate drive entity ITs to BaseEntityIT, add FolderResourceIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate FileResourceIT, DirectoryResourceIT, and SpreadsheetResourceIT onto BaseEntityIT so they automatically inherit the ~60 generic entity tests (CRUD, owners, tags PATCH, glossary PATCH, soft-delete, versions, custom extensions, etc.). Add a brand-new FolderResourceIT covering the previously untested folder entity type. The previous standalone harnesses were a migration gap from the bulk "Faster tests" PR (#24948) — only WorksheetResourceIT got the full BaseEntityIT plumbing; the rest of the drive family did not. This meant bugs like the updateColumns NPE fixed in this PR did not surface in the IT suite for File and friends. Each entity sets feature flags conservatively: - supportsFollowers/Domains/DataProducts/CustomExtension/BulkAPI/ DataContract = false (matches the existing minimal surface area) - Folder additionally sets supportsVersionHistory/GetByVersion = false since the FolderResource doesn't expose /versions Entity-specific tests (column handling, directory hierarchy, root filter, FQN structure, etc.) are preserved. Existing redundant smoke tests (createMinimal, deleteById, getByName, ID/name not-found) are removed since BaseEntityIT covers them. Also add openmetadata-sdk/.../drives/FolderService.java so Folder has SDK access (basePath /v1/drive/folders). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../it/tests/DirectoryResourceIT.java | 344 +++------ .../openmetadata/it/tests/FileResourceIT.java | 389 ++++------ .../it/tests/FolderResourceIT.java | 202 +++++ .../it/tests/SpreadsheetResourceIT.java | 729 +++--------------- .../sdk/services/drives/FolderService.java | 23 + 5 files changed, 610 insertions(+), 1077 deletions(-) create mode 100644 openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java create mode 100644 openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/drives/FolderService.java diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java index 5396fbb823b8..64749ba9675c 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java @@ -5,291 +5,196 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; import org.openmetadata.it.factories.DriveServiceTestFactory; import org.openmetadata.it.util.SdkClients; import org.openmetadata.it.util.TestNamespace; -import org.openmetadata.it.util.TestNamespaceExtension; +import org.openmetadata.schema.api.data.CreateDirectory; import org.openmetadata.schema.entity.data.Directory; import org.openmetadata.schema.entity.services.DriveService; +import org.openmetadata.schema.type.EntityHistory; import org.openmetadata.sdk.fluent.Directories; - +import org.openmetadata.sdk.models.ListParams; +import org.openmetadata.sdk.models.ListResponse; +import org.openmetadata.sdk.services.drives.DirectoryService; + +/** + * Integration tests for Directory entity operations. + * + *

Extends BaseEntityIT to inherit common entity tests. Adds Directory-specific tests for + * drive-service linkage and naming. + */ @Execution(ExecutionMode.CONCURRENT) -@ExtendWith(TestNamespaceExtension.class) -public class DirectoryResourceIT { +public class DirectoryResourceIT extends BaseEntityIT { + + { + supportsFollowers = false; + supportsDomains = false; + supportsDataProducts = false; + supportsCustomExtension = false; + supportsBulkAPI = false; + supportsDataContract = false; + } @BeforeAll static void setup() { Directories.setDefaultClient(SdkClients.adminClient()); } - @Test - void test_createAndGetDirectory(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - - String directoryName = ns.prefix("test_directory"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory") - .withDescription("A test directory created by integration test") - .execute(); - - assertNotNull(created); - assertNotNull(created.getId()); - assertEquals(directoryName, created.getName()); - assertEquals("Test Directory", created.getDisplayName()); - assertEquals("A test directory created by integration test", created.getDescription()); - assertNotNull(created.getService()); - assertEquals( - driveService.getFullyQualifiedName(), created.getService().getFullyQualifiedName()); - - Directory fetched = Directories.get(created.getId().toString()); - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getName(), fetched.getName()); - assertEquals(created.getDisplayName(), fetched.getDisplayName()); - } + // =================================================================== + // ABSTRACT METHOD IMPLEMENTATIONS (Required by BaseEntityIT) + // =================================================================== - @Test - void test_getByName(TestNamespace ns) { + @Override + protected CreateDirectory createMinimalRequest(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - - String directoryName = ns.prefix("test_directory_by_name"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory By Name") - .execute(); - - assertNotNull(created); - assertNotNull(created.getFullyQualifiedName()); - - Directory fetched = Directories.getByName(created.getFullyQualifiedName()); - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getName(), fetched.getName()); - assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + return new CreateDirectory() + .withName(ns.prefix("directory")) + .withService(driveService.getFullyQualifiedName()) + .withDescription("Test directory created by integration test"); } - @Test - void test_getByNameWithFields(TestNamespace ns) { + @Override + protected CreateDirectory createRequest(String name, TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - - String directoryName = ns.prefix("test_directory_with_fields"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory With Fields") - .execute(); - - assertNotNull(created); - assertNotNull(created.getFullyQualifiedName()); - - Directory fetched = Directories.getByName(created.getFullyQualifiedName(), "service,owners"); - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertNotNull(fetched.getService()); + return new CreateDirectory().withName(name).withService(driveService.getFullyQualifiedName()); } - @Test - void test_deleteDirectory(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - - String directoryName = ns.prefix("test_directory_delete"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory To Delete") - .execute(); - - assertNotNull(created); - String directoryId = created.getId().toString(); - - Directories.delete(directoryId); + @Override + protected Directory createEntity(CreateDirectory createRequest) { + return getDirectoryService().create(createRequest); + } - assertThrows( - Exception.class, - () -> Directories.get(directoryId), - "Getting deleted directory should fail"); + @Override + protected Directory getEntity(String id) { + return getDirectoryService().get(id); } - @Test - void test_createDirectoryMinimalRequest(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); + @Override + protected Directory getEntityByName(String fqn) { + return getDirectoryService().getByName(fqn); + } - String directoryName = ns.prefix("test_directory_minimal"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .execute(); + @Override + protected Directory patchEntity(String id, Directory entity) { + return getDirectoryService().update(id, entity); + } - assertNotNull(created); - assertNotNull(created.getId()); - assertEquals(directoryName, created.getName()); - assertNotNull(created.getService()); + @Override + protected void deleteEntity(String id) { + getDirectoryService().delete(id); } - @Test - void test_createDirectoryWithoutService_fails(TestNamespace ns) { - String directoryName = ns.prefix("test_directory_no_service"); + @Override + protected void restoreEntity(String id) { + getDirectoryService().restore(id); + } - assertThrows( - Exception.class, - () -> Directories.create().name(directoryName).execute(), - "Creating directory without service should fail"); + @Override + protected void hardDeleteEntity(String id) { + Map params = new HashMap<>(); + params.put("hardDelete", "true"); + getDirectoryService().delete(id, params); } - @Test - void test_findDirectoryById(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); + @Override + protected String getEntityType() { + return "directory"; + } - String directoryName = ns.prefix("test_directory_find"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory Find") - .execute(); + @Override + protected void validateCreatedEntity(Directory entity, CreateDirectory createRequest) { + assertEquals(createRequest.getName(), entity.getName()); + assertNotNull(entity.getService(), "Directory must have a service"); + assertEquals( + createRequest.getService(), + entity.getService().getFullyQualifiedName(), + "Service FQN should match"); - assertNotNull(created); + if (createRequest.getDescription() != null) { + assertEquals(createRequest.getDescription(), entity.getDescription()); + } - Directory fetched = Directories.find(created.getId().toString()).fetch(); - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getName(), fetched.getName()); + assertTrue( + entity.getFullyQualifiedName().contains(entity.getName()), + "FQN should contain directory name"); } - @Test - void test_findDirectoryByName(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - - String directoryName = ns.prefix("test_directory_find_by_name"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory Find By Name") - .execute(); - - assertNotNull(created); - assertNotNull(created.getFullyQualifiedName()); + @Override + protected ListResponse listEntities(ListParams params) { + return getDirectoryService().list(params); + } - Directory fetched = Directories.findByName(created.getFullyQualifiedName()).fetch(); - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getName(), fetched.getName()); + @Override + protected Directory getEntityWithFields(String id, String fields) { + return getDirectoryService().get(id, fields); } - @Test - void test_findDirectoryWithFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); + @Override + protected Directory getEntityByNameWithFields(String fqn, String fields) { + return getDirectoryService().getByName(fqn, fields); + } - String directoryName = ns.prefix("test_directory_find_fields"); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory Find Fields") - .execute(); + @Override + protected Directory getEntityIncludeDeleted(String id) { + return getDirectoryService().get(id, null, "deleted"); + } - assertNotNull(created); + @Override + protected EntityHistory getVersionHistory(UUID id) { + return getDirectoryService().getVersionList(id); + } - Directory fetched = - Directories.findByName(created.getFullyQualifiedName()) - .withFields("service", "owners", "tags") - .fetch(); - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertNotNull(fetched.getService()); + @Override + protected Directory getVersion(UUID id, Double version) { + return getDirectoryService().getVersion(id.toString(), version); } - @Test - void test_createMultipleDirectories(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - - for (int i = 1; i <= 3; i++) { - String directoryName = ns.prefix("test_directory_multi_" + i); - Directory created = - Directories.create() - .name(directoryName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test Directory " + i) - .withDescription("Directory number " + i) - .execute(); - - assertNotNull(created); - assertNotNull(created.getId()); - assertEquals(directoryName, created.getName()); - assertEquals("Test Directory " + i, created.getDisplayName()); - - Directory fetched = Directories.get(created.getId().toString()); - assertEquals(created.getId(), fetched.getId()); - } + private DirectoryService getDirectoryService() { + return new DirectoryService(SdkClients.adminClient().getHttpClient()); } + // =================================================================== + // DIRECTORY-SPECIFIC TESTS + // =================================================================== + @Test - void test_createDirectoryWithAllFields(TestNamespace ns) { + void test_createAndGetDirectory(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); - String directoryName = ns.prefix("test_directory_full"); + String directoryName = ns.prefix("test_directory"); Directory created = Directories.create() .name(directoryName) .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Complete Test Directory") - .withDescription("A directory with all fields populated for testing") + .withDisplayName("Test Directory") + .withDescription("A test directory created by integration test") .execute(); - assertNotNull(created); assertNotNull(created.getId()); assertEquals(directoryName, created.getName()); - assertEquals("Complete Test Directory", created.getDisplayName()); - assertEquals("A directory with all fields populated for testing", created.getDescription()); - assertNotNull(created.getService()); - assertNotNull(created.getFullyQualifiedName()); - assertTrue( - created.getFullyQualifiedName().contains(directoryName), - "FQN should contain directory name"); - } - - @Test - void test_getNonExistentDirectory_fails(TestNamespace ns) { - String nonExistentId = "non-existent-directory-id-12345"; + assertEquals("Test Directory", created.getDisplayName()); + assertEquals( + driveService.getFullyQualifiedName(), created.getService().getFullyQualifiedName()); - assertThrows( - Exception.class, - () -> Directories.get(nonExistentId), - "Getting non-existent directory should fail"); + Directory fetched = Directories.get(created.getId().toString()); + assertEquals(created.getId(), fetched.getId()); } @Test - void test_getByNameNonExistent_fails(TestNamespace ns) { - String nonExistentFqn = "nonExistentService.nonExistentDirectory"; + void test_createDirectoryWithoutService_fails(TestNamespace ns) { + String directoryName = ns.prefix("test_directory_no_service"); assertThrows( Exception.class, - () -> Directories.getByName(nonExistentFqn), - "Getting directory by non-existent FQN should fail"); + () -> Directories.create().name(directoryName).execute(), + "Creating directory without service should fail"); } @Test @@ -306,7 +211,6 @@ void test_createDirectoryWithInvalidService_fails(TestNamespace ns) { @Test void test_directoryFullyQualifiedName(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - assertNotNull(driveService); String directoryName = ns.prefix("test_directory_fqn"); Directory created = @@ -315,8 +219,6 @@ void test_directoryFullyQualifiedName(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); - assertNotNull(created); - assertNotNull(created.getFullyQualifiedName()); assertTrue(created.getFullyQualifiedName().contains(driveService.getName())); assertTrue(created.getFullyQualifiedName().contains(directoryName)); } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java index 94bb1aa531c7..0b4519397a26 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java @@ -5,208 +5,220 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.UUID; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; import org.openmetadata.it.factories.DriveServiceTestFactory; import org.openmetadata.it.util.SdkClients; import org.openmetadata.it.util.TestNamespace; -import org.openmetadata.it.util.TestNamespaceExtension; +import org.openmetadata.schema.api.data.CreateFile; import org.openmetadata.schema.entity.data.File; import org.openmetadata.schema.entity.services.DriveService; import org.openmetadata.schema.type.Column; import org.openmetadata.schema.type.ColumnDataType; +import org.openmetadata.schema.type.EntityHistory; import org.openmetadata.schema.type.FileType; import org.openmetadata.sdk.fluent.Files; - +import org.openmetadata.sdk.models.ListParams; +import org.openmetadata.sdk.models.ListResponse; +import org.openmetadata.sdk.services.drives.FileService; + +/** + * Integration tests for File entity operations. + * + *

Extends BaseEntityIT to inherit common entity tests. Adds File-specific tests for columns + * (optional, since not all file types are tabular), file metadata, and drive-service linkage. + */ @Execution(ExecutionMode.CONCURRENT) -@ExtendWith(TestNamespaceExtension.class) -public class FileResourceIT { +public class FileResourceIT extends BaseEntityIT { + + { + supportsFollowers = false; + supportsDomains = false; + supportsDataProducts = false; + supportsCustomExtension = false; + supportsBulkAPI = false; + supportsDataContract = false; + } @BeforeAll public static void setup() { Files.setDefaultClient(SdkClients.adminClient()); } - @Test - void test_createAndGetFile(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - String fileName = ns.prefix("test_file"); - File createdFile = - Files.create() - .name(fileName) - .withService(driveService.getFullyQualifiedName()) - .withDescription("Test file for integration testing") - .execute(); - - assertNotNull(createdFile); - assertNotNull(createdFile.getId()); - assertEquals(fileName, createdFile.getName()); - assertNotNull(createdFile.getService()); - assertEquals(driveService.getFullyQualifiedName(), createdFile.getService().getName()); - - File retrievedFile = Files.get(createdFile.getId().toString()); - assertNotNull(retrievedFile); - assertEquals(createdFile.getId(), retrievedFile.getId()); - assertEquals(fileName, retrievedFile.getName()); - } + // =================================================================== + // ABSTRACT METHOD IMPLEMENTATIONS (Required by BaseEntityIT) + // =================================================================== - @Test - void test_getFileByName(TestNamespace ns) { + @Override + protected CreateFile createMinimalRequest(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - String fileName = ns.prefix("test_file_by_name"); - File createdFile = - Files.create() - .name(fileName) - .withService(driveService.getFullyQualifiedName()) - .withDisplayName("Test File Display Name") - .execute(); - - assertNotNull(createdFile); - assertNotNull(createdFile.getFullyQualifiedName()); - - File retrievedFile = Files.getByName(createdFile.getFullyQualifiedName()); - assertNotNull(retrievedFile); - assertEquals(createdFile.getId(), retrievedFile.getId()); - assertEquals(fileName, retrievedFile.getName()); - assertEquals("Test File Display Name", retrievedFile.getDisplayName()); + return new CreateFile() + .withName(ns.prefix("file")) + .withService(driveService.getFullyQualifiedName()) + .withDescription("Test file created by integration test"); } - @Test - void test_getFileByNameWithFields(TestNamespace ns) { + @Override + protected CreateFile createRequest(String name, TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + return new CreateFile().withName(name).withService(driveService.getFullyQualifiedName()); + } - String fileName = ns.prefix("test_file_with_fields"); - File createdFile = - Files.create() - .name(fileName) - .withService(driveService.getFullyQualifiedName()) - .withDescription("File with specific fields") - .execute(); - - assertNotNull(createdFile); + @Override + protected File createEntity(CreateFile createRequest) { + return getFileService().create(createRequest); + } - File retrievedFile = Files.getByName(createdFile.getFullyQualifiedName(), "owners,tags"); - assertNotNull(retrievedFile); - assertEquals(createdFile.getId(), retrievedFile.getId()); + @Override + protected File getEntity(String id) { + return getFileService().get(id); } - @Test - void test_findFileById(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected File getEntityByName(String fqn) { + return getFileService().getByName(fqn); + } - String fileName = ns.prefix("test_file_find"); - File createdFile = - Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + @Override + protected File patchEntity(String id, File entity) { + return getFileService().update(id, entity); + } - assertNotNull(createdFile); + @Override + protected void deleteEntity(String id) { + getFileService().delete(id); + } - File foundFile = Files.find(createdFile.getId().toString()).fetch(); - assertNotNull(foundFile); - assertEquals(createdFile.getId(), foundFile.getId()); - assertEquals(fileName, foundFile.getName()); + @Override + protected void restoreEntity(String id) { + getFileService().restore(id); } - @Test - void test_findFileByNameWithFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected void hardDeleteEntity(String id) { + Map params = new HashMap<>(); + params.put("hardDelete", "true"); + getFileService().delete(id, params); + } - String fileName = ns.prefix("test_file_find_by_name"); - File createdFile = - Files.create() - .name(fileName) - .withService(driveService.getFullyQualifiedName()) - .withDescription("Find by name with fields") - .execute(); + @Override + protected String getEntityType() { + return "file"; + } - assertNotNull(createdFile); + @Override + protected void validateCreatedEntity(File entity, CreateFile createRequest) { + assertEquals(createRequest.getName(), entity.getName()); + assertNotNull(entity.getService(), "File must have a service"); + assertEquals( + createRequest.getService(), + entity.getService().getFullyQualifiedName(), + "Service FQN should match"); + + if (createRequest.getDescription() != null) { + assertEquals(createRequest.getDescription(), entity.getDescription()); + } + + if (createRequest.getColumns() != null && !createRequest.getColumns().isEmpty()) { + assertNotNull(entity.getColumns()); + assertEquals(createRequest.getColumns().size(), entity.getColumns().size()); + } + + assertTrue( + entity.getFullyQualifiedName().contains(entity.getName()), "FQN should contain file name"); + } - File foundFile = - Files.findByName(createdFile.getFullyQualifiedName()) - .withFields("owners", "tags", "domains") - .fetch(); - assertNotNull(foundFile); - assertEquals(createdFile.getId(), foundFile.getId()); + @Override + protected ListResponse listEntities(ListParams params) { + return getFileService().list(params); } - @Test - void test_deleteFile(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected File getEntityWithFields(String id, String fields) { + return getFileService().get(id, fields); + } - String fileName = ns.prefix("test_file_delete"); - File createdFile = - Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + @Override + protected File getEntityByNameWithFields(String fqn, String fields) { + return getFileService().getByName(fqn, fields); + } - assertNotNull(createdFile); - String fileId = createdFile.getId().toString(); + @Override + protected File getEntityIncludeDeleted(String id) { + return getFileService().get(id, null, "deleted"); + } - File beforeDelete = Files.get(fileId); - assertNotNull(beforeDelete); + @Override + protected EntityHistory getVersionHistory(UUID id) { + return getFileService().getVersionList(id); + } - Files.delete(fileId); + @Override + protected File getVersion(UUID id, Double version) { + return getFileService().getVersion(id.toString(), version); + } - assertThrows( - Exception.class, () -> Files.get(fileId), "Getting deleted file should throw exception"); + private FileService getFileService() { + return new FileService(SdkClients.adminClient().getHttpClient()); } + // =================================================================== + // FILE-SPECIFIC TESTS + // =================================================================== + @Test - void test_createFileWithDisplayName(TestNamespace ns) { + void test_createAndGetFile(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - String fileName = ns.prefix("test_file_display"); - String displayName = "My Test File"; - + String fileName = ns.prefix("test_file"); File createdFile = Files.create() .name(fileName) - .withDisplayName(displayName) .withService(driveService.getFullyQualifiedName()) + .withDescription("Test file for integration testing") .execute(); assertNotNull(createdFile); + assertNotNull(createdFile.getId()); assertEquals(fileName, createdFile.getName()); - assertEquals(displayName, createdFile.getDisplayName()); + assertNotNull(createdFile.getService()); + assertEquals(driveService.getFullyQualifiedName(), createdFile.getService().getName()); + + File retrievedFile = Files.get(createdFile.getId().toString()); + assertNotNull(retrievedFile); + assertEquals(createdFile.getId(), retrievedFile.getId()); + assertEquals(fileName, retrievedFile.getName()); } @Test - void test_createFileWithDescription(TestNamespace ns) { + void test_getFileByName(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - String fileName = ns.prefix("test_file_desc"); - String description = "This is a detailed description of the test file"; - + String fileName = ns.prefix("test_file_by_name"); File createdFile = Files.create() .name(fileName) - .withDescription(description) .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test File Display Name") .execute(); assertNotNull(createdFile); - assertEquals(fileName, createdFile.getName()); - assertEquals(description, createdFile.getDescription()); - } - - @Test - void test_createFileMinimal(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - String fileName = ns.prefix("test_file_minimal"); - - File createdFile = - Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + assertNotNull(createdFile.getFullyQualifiedName()); - assertNotNull(createdFile); - assertEquals(fileName, createdFile.getName()); - assertNotNull(createdFile.getId()); - assertNotNull(createdFile.getService()); + File retrievedFile = Files.getByName(createdFile.getFullyQualifiedName()); + assertNotNull(retrievedFile); + assertEquals(createdFile.getId(), retrievedFile.getId()); + assertEquals(fileName, retrievedFile.getName()); + assertEquals("Test File Display Name", retrievedFile.getDisplayName()); } @Test @@ -235,72 +247,13 @@ void test_multipleFilesInSameService(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); - File file3 = - Files.create() - .name(ns.prefix("file_3")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - assertNotNull(file1); - assertNotNull(file2); - assertNotNull(file3); - assertNotEquals(file1.getId(), file2.getId()); - assertNotEquals(file2.getId(), file3.getId()); - assertNotEquals(file1.getId(), file3.getId()); - assertEquals(driveService.getFullyQualifiedName(), file1.getService().getFullyQualifiedName()); assertEquals(driveService.getFullyQualifiedName(), file2.getService().getFullyQualifiedName()); - assertEquals(driveService.getFullyQualifiedName(), file3.getService().getFullyQualifiedName()); - } - - @Test - void test_fileWithAllOptionalFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - String fileName = ns.prefix("test_file_full"); - String displayName = "Complete Test File"; - String description = "A file with all optional fields populated"; - - File createdFile = - Files.create() - .name(fileName) - .withDisplayName(displayName) - .withDescription(description) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - assertNotNull(createdFile); - assertEquals(fileName, createdFile.getName()); - assertEquals(displayName, createdFile.getDisplayName()); - assertEquals(description, createdFile.getDescription()); - assertNotNull(createdFile.getService()); - assertEquals(driveService.getFullyQualifiedName(), createdFile.getService().getName()); - } - - @Test - void test_getFileWithNonExistentId_shouldFail(TestNamespace ns) { - String nonExistentId = "00000000-0000-0000-0000-000000000000"; - - assertThrows( - Exception.class, - () -> Files.get(nonExistentId), - "Getting file with non-existent ID should fail"); - } - - @Test - void test_getFileByNameWithNonExistentFQN_shouldFail(TestNamespace ns) { - String nonExistentFQN = "nonexistent.service.nonexistent.file"; - - assertThrows( - Exception.class, - () -> Files.getByName(nonExistentFQN), - "Getting file with non-existent FQN should fail"); } @Test void test_createFileWithoutColumns(TestNamespace ns) { - // This test verifies that files can be created without columns (columns are optional) DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); String fileName = ns.prefix("test_file_no_columns"); @@ -313,16 +266,12 @@ void test_createFileWithoutColumns(TestNamespace ns) { .execute(); assertNotNull(createdFile); - assertNotNull(createdFile.getId()); - assertEquals(fileName, createdFile.getName()); assertEquals(FileType.Text, createdFile.getFileType()); - // Columns should be null for a file without columns - assertNull(createdFile.getColumns()); + assertNull(createdFile.getColumns(), "Columns should be null for a file without columns"); } @Test void test_createCsvFileWithColumns(TestNamespace ns) { - // This test verifies that CSV files can be created with column definitions DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); String fileName = ns.prefix("test_csv_with_columns"); @@ -341,17 +290,12 @@ void test_createCsvFileWithColumns(TestNamespace ns) { .withColumns(columns) .execute(); - assertNotNull(createdFile); - assertNotNull(createdFile.getId()); - assertEquals(fileName, createdFile.getName()); - assertEquals(FileType.CSV, createdFile.getFileType()); assertNotNull(createdFile.getColumns()); assertEquals(3, createdFile.getColumns().size()); } @Test void test_getFileWithColumnsField(TestNamespace ns) { - // This test verifies that columns are returned when explicitly requested DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); String fileName = ns.prefix("test_csv_get_columns"); @@ -368,60 +312,13 @@ void test_getFileWithColumnsField(TestNamespace ns) { .withColumns(columns) .execute(); - assertNotNull(createdFile); - - // Retrieve with columns field File retrievedFile = Files.getByName(createdFile.getFullyQualifiedName(), "columns"); - assertNotNull(retrievedFile); assertNotNull(retrievedFile.getColumns()); assertEquals(2, retrievedFile.getColumns().size()); assertEquals("col1", retrievedFile.getColumns().get(0).getName()); assertEquals("col2", retrievedFile.getColumns().get(1).getName()); } - @Test - void test_createImageFileWithoutColumns(TestNamespace ns) { - // This test verifies that non-structured files like images work without columns - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - String fileName = ns.prefix("test_image_file"); - File createdFile = - Files.create() - .name(fileName) - .withService(driveService.getFullyQualifiedName()) - .withFileType(FileType.Image) - .withMimeType("image/png") - .execute(); - - assertNotNull(createdFile); - assertNotNull(createdFile.getId()); - assertEquals(FileType.Image, createdFile.getFileType()); - assertEquals("image/png", createdFile.getMimeType()); - // Image files should not have columns - assertNull(createdFile.getColumns()); - } - - @Test - void test_createPdfFileWithoutColumns(TestNamespace ns) { - // This test verifies that PDF files work without columns - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - String fileName = ns.prefix("test_pdf_file"); - File createdFile = - Files.create() - .name(fileName) - .withService(driveService.getFullyQualifiedName()) - .withFileType(FileType.PDF) - .withMimeType("application/pdf") - .execute(); - - assertNotNull(createdFile); - assertNotNull(createdFile.getId()); - assertEquals(FileType.PDF, createdFile.getFileType()); - // PDF files should not have columns - assertNull(createdFile.getColumns()); - } - @Test void test_patchFileWithoutColumns_doesNotNpe(TestNamespace ns) { // Regression: PATCH on a file without columns must not NPE in @@ -442,7 +339,7 @@ void test_patchFileWithoutColumns_doesNotNpe(TestNamespace ns) { assertNull(createdFile.getColumns()); createdFile.setDescription("Updated description"); - File patched = SdkClients.adminClient().files().update(createdFile.getId(), createdFile); + File patched = getFileService().update(createdFile.getId(), createdFile); assertEquals("Updated description", patched.getDescription()); assertNull(patched.getColumns()); diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java new file mode 100644 index 000000000000..97f5e6a80aa1 --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java @@ -0,0 +1,202 @@ +package org.openmetadata.it.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.openmetadata.it.util.SdkClients; +import org.openmetadata.it.util.TestNamespace; +import org.openmetadata.schema.api.data.CreateFolder; +import org.openmetadata.schema.entity.data.Folder; +import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.sdk.models.ListParams; +import org.openmetadata.sdk.models.ListResponse; +import org.openmetadata.sdk.services.drives.FolderService; + +/** + * Integration tests for Folder entity operations. + * + *

Folder is a service-less drive entity at {@code /v1/drive/folders}. It supports owners, + * tags, domains, and followers, but does not expose version history or bulk endpoints. Extends + * BaseEntityIT so generic CRUD/tag/domain coverage runs automatically. + */ +@Execution(ExecutionMode.CONCURRENT) +public class FolderResourceIT extends BaseEntityIT { + + { + supportsFollowers = false; + supportsDataProducts = false; + supportsCustomExtension = false; + supportsBulkAPI = false; + supportsDataContract = false; + supportsVersionHistory = false; + supportsGetByVersion = false; + } + + // =================================================================== + // ABSTRACT METHOD IMPLEMENTATIONS (Required by BaseEntityIT) + // =================================================================== + + @Override + protected CreateFolder createMinimalRequest(TestNamespace ns) { + return new CreateFolder() + .withName(ns.prefix("folder")) + .withDescription("Test folder created by integration test"); + } + + @Override + protected CreateFolder createRequest(String name, TestNamespace ns) { + return new CreateFolder().withName(name); + } + + @Override + protected Folder createEntity(CreateFolder createRequest) { + return getFolderService().create(createRequest); + } + + @Override + protected Folder getEntity(String id) { + return getFolderService().get(id); + } + + @Override + protected Folder getEntityByName(String fqn) { + return getFolderService().getByName(fqn); + } + + @Override + protected Folder patchEntity(String id, Folder entity) { + return getFolderService().update(id, entity); + } + + @Override + protected void deleteEntity(String id) { + getFolderService().delete(id); + } + + @Override + protected void restoreEntity(String id) { + getFolderService().restore(id); + } + + @Override + protected void hardDeleteEntity(String id) { + Map params = new HashMap<>(); + params.put("hardDelete", "true"); + getFolderService().delete(id, params); + } + + @Override + protected String getEntityType() { + return "folder"; + } + + @Override + protected void validateCreatedEntity(Folder entity, CreateFolder createRequest) { + assertEquals(createRequest.getName(), entity.getName()); + + if (createRequest.getDescription() != null) { + assertEquals(createRequest.getDescription(), entity.getDescription()); + } + + assertTrue( + entity.getFullyQualifiedName().contains(entity.getName()), + "FQN should contain folder name"); + } + + @Override + protected ListResponse listEntities(ListParams params) { + return getFolderService().list(params); + } + + @Override + protected Folder getEntityWithFields(String id, String fields) { + return getFolderService().get(id, fields); + } + + @Override + protected Folder getEntityByNameWithFields(String fqn, String fields) { + return getFolderService().getByName(fqn, fields); + } + + @Override + protected Folder getEntityIncludeDeleted(String id) { + return getFolderService().get(id, null, "deleted"); + } + + @Override + protected EntityHistory getVersionHistory(UUID id) { + throw new UnsupportedOperationException("Folder does not expose version history"); + } + + @Override + protected Folder getVersion(UUID id, Double version) { + throw new UnsupportedOperationException("Folder does not expose individual versions"); + } + + private FolderService getFolderService() { + return new FolderService(SdkClients.adminClient().getHttpClient()); + } + + // =================================================================== + // FOLDER-SPECIFIC TESTS + // =================================================================== + + @Test + void test_createFolder_minimalRequest(TestNamespace ns) { + String folderName = ns.prefix("folder_minimal"); + Folder folder = getFolderService().create(new CreateFolder().withName(folderName)); + + assertNotNull(folder.getId()); + assertEquals(folderName, folder.getName()); + assertNotNull(folder.getFullyQualifiedName()); + } + + @Test + void test_createNestedFolder(TestNamespace ns) { + Folder parent = + getFolderService() + .create( + new CreateFolder() + .withName(ns.prefix("parent_folder")) + .withDescription("Parent folder")); + + Folder child = + getFolderService() + .create( + new CreateFolder() + .withName(ns.prefix("child_folder")) + .withParent(parent.getFullyQualifiedName()) + .withDescription("Child folder")); + + assertNotNull(child.getParent()); + assertEquals(parent.getId(), child.getParent().getId()); + assertTrue( + child.getFullyQualifiedName().contains(parent.getName()), + "Nested folder FQN should contain parent name"); + } + + @Test + void test_createFolderWithoutName_fails(TestNamespace ns) { + assertThrows( + Exception.class, + () -> getFolderService().create(new CreateFolder()), + "Creating folder without name should fail"); + } + + @Test + void test_rootFolderHasNoParent(TestNamespace ns) { + Folder folder = + getFolderService().create(new CreateFolder().withName(ns.prefix("root_folder"))); + + assertNull(folder.getParent()); + } +} diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java index a438cfd40e04..8de4e401eb76 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java @@ -6,28 +6,45 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; import org.openmetadata.it.factories.DriveServiceTestFactory; import org.openmetadata.it.util.SdkClients; import org.openmetadata.it.util.TestNamespace; -import org.openmetadata.it.util.TestNamespaceExtension; +import org.openmetadata.schema.api.data.CreateSpreadsheet; import org.openmetadata.schema.entity.data.Directory; import org.openmetadata.schema.entity.data.Spreadsheet; import org.openmetadata.schema.entity.services.DriveService; -import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.EntityHistory; import org.openmetadata.sdk.fluent.Directories; import org.openmetadata.sdk.fluent.Spreadsheets; import org.openmetadata.sdk.fluent.Worksheets; import org.openmetadata.sdk.models.ListParams; import org.openmetadata.sdk.models.ListResponse; - +import org.openmetadata.sdk.services.drives.SpreadsheetService; + +/** + * Integration tests for Spreadsheet entity operations. + * + *

Extends BaseEntityIT to inherit common entity tests. Adds Spreadsheet-specific tests for + * directory hierarchy, root-filter listing, and worksheet relationships. + */ @Execution(ExecutionMode.CONCURRENT) -@ExtendWith(TestNamespaceExtension.class) -public class SpreadsheetResourceIT { +public class SpreadsheetResourceIT extends BaseEntityIT { + + { + supportsFollowers = false; + supportsDomains = false; + supportsDataProducts = false; + supportsCustomExtension = false; + supportsBulkAPI = false; + supportsDataContract = false; + } @BeforeAll static void setup() { @@ -36,117 +53,123 @@ static void setup() { Worksheets.setDefaultClient(SdkClients.adminClient()); } - @Test - void test_createSpreadsheet(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet spreadsheet = - Spreadsheets.create() - .name(ns.prefix("spreadsheet")) - .withDescription("Test spreadsheet") - .withService(driveService.getFullyQualifiedName()) - .execute(); + // =================================================================== + // ABSTRACT METHOD IMPLEMENTATIONS (Required by BaseEntityIT) + // =================================================================== - assertNotNull(spreadsheet); - assertNotNull(spreadsheet.getId()); - assertEquals(ns.prefix("spreadsheet"), spreadsheet.getName()); - assertEquals("Test spreadsheet", spreadsheet.getDescription()); - assertNotNull(spreadsheet.getService()); - assertEquals( - driveService.getFullyQualifiedName(), spreadsheet.getService().getFullyQualifiedName()); + @Override + protected CreateSpreadsheet createMinimalRequest(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + return new CreateSpreadsheet() + .withName(ns.prefix("spreadsheet")) + .withService(driveService.getFullyQualifiedName()) + .withDescription("Test spreadsheet created by integration test"); } - @Test - void test_getSpreadsheetById(TestNamespace ns) { + @Override + protected CreateSpreadsheet createRequest(String name, TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + return new CreateSpreadsheet().withName(name).withService(driveService.getFullyQualifiedName()); + } - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_get")) - .withService(driveService.getFullyQualifiedName()) - .execute(); + @Override + protected Spreadsheet createEntity(CreateSpreadsheet createRequest) { + return getSpreadsheetService().create(createRequest); + } - Spreadsheet fetched = Spreadsheets.get(created.getId().toString()); + @Override + protected Spreadsheet getEntity(String id) { + return getSpreadsheetService().get(id); + } - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getName(), fetched.getName()); - assertEquals( - created.getFullyQualifiedName(), - fetched.getFullyQualifiedName(), - "FQN should match between created and fetched"); + @Override + protected Spreadsheet getEntityByName(String fqn) { + return getSpreadsheetService().getByName(fqn); } - @Test - void test_getSpreadsheetByName(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected Spreadsheet patchEntity(String id, Spreadsheet entity) { + return getSpreadsheetService().update(id, entity); + } - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_getByName")) - .withService(driveService.getFullyQualifiedName()) - .execute(); + @Override + protected void deleteEntity(String id) { + getSpreadsheetService().delete(id); + } - Spreadsheet fetched = Spreadsheets.getByName(created.getFullyQualifiedName()); + @Override + protected void restoreEntity(String id) { + getSpreadsheetService().restore(id); + } - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getName(), fetched.getName()); - assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + @Override + protected void hardDeleteEntity(String id) { + Map params = new HashMap<>(); + params.put("hardDelete", "true"); + getSpreadsheetService().delete(id, params); } - @Test - void test_deleteSpreadsheet(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected String getEntityType() { + return "spreadsheet"; + } - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_delete")) - .withService(driveService.getFullyQualifiedName()) - .execute(); + @Override + protected void validateCreatedEntity(Spreadsheet entity, CreateSpreadsheet createRequest) { + assertEquals(createRequest.getName(), entity.getName()); + assertNotNull(entity.getService(), "Spreadsheet must have a service"); + assertEquals( + createRequest.getService(), + entity.getService().getFullyQualifiedName(), + "Service FQN should match"); - assertNotNull(created.getId()); + if (createRequest.getDescription() != null) { + assertEquals(createRequest.getDescription(), entity.getDescription()); + } - Spreadsheets.delete(created.getId().toString()); + assertTrue( + entity.getFullyQualifiedName().contains(entity.getName()), + "FQN should contain spreadsheet name"); + } - assertThrows( - Exception.class, - () -> Spreadsheets.get(created.getId().toString()), - "Getting deleted spreadsheet should fail"); + @Override + protected ListResponse listEntities(ListParams params) { + return getSpreadsheetService().list(params); } - @Test - void test_createSpreadsheetWithOptionalFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected Spreadsheet getEntityWithFields(String id, String fields) { + return getSpreadsheetService().get(id, fields); + } - Spreadsheet spreadsheet = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_optional")) - .withDisplayName("Display Name for Spreadsheet") - .withDescription("Spreadsheet with optional fields") - .withService(driveService.getFullyQualifiedName()) - .execute(); + @Override + protected Spreadsheet getEntityByNameWithFields(String fqn, String fields) { + return getSpreadsheetService().getByName(fqn, fields); + } - assertNotNull(spreadsheet); - assertEquals("Display Name for Spreadsheet", spreadsheet.getDisplayName()); - assertEquals("Spreadsheet with optional fields", spreadsheet.getDescription()); + @Override + protected Spreadsheet getEntityIncludeDeleted(String id) { + return getSpreadsheetService().get(id, null, "deleted"); } - @Test - void test_createSpreadsheetMinimal(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + @Override + protected EntityHistory getVersionHistory(UUID id) { + return getSpreadsheetService().getVersionList(id); + } - Spreadsheet spreadsheet = - Spreadsheets.create() - .name(ns.prefix("minimal_spreadsheet")) - .withService(driveService.getFullyQualifiedName()) - .execute(); + @Override + protected Spreadsheet getVersion(UUID id, Double version) { + return getSpreadsheetService().getVersion(id.toString(), version); + } - assertNotNull(spreadsheet); - assertNotNull(spreadsheet.getId()); - assertEquals(ns.prefix("minimal_spreadsheet"), spreadsheet.getName()); + private SpreadsheetService getSpreadsheetService() { + return new SpreadsheetService(SdkClients.adminClient().getHttpClient()); } + // =================================================================== + // SPREADSHEET-SPECIFIC TESTS + // =================================================================== + @Test void test_createSpreadsheetWithoutService_fails(TestNamespace ns) { assertThrows( @@ -167,81 +190,6 @@ void test_createSpreadsheetWithInvalidService_fails(TestNamespace ns) { "Creating spreadsheet with invalid service should fail"); } - @Test - void test_finderWithFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_fields")) - .withDescription("Test spreadsheet for fields") - .withService(driveService.getFullyQualifiedName()) - .execute(); - - Spreadsheet fetched = - Spreadsheets.find(created.getId().toString()).withFields("service", "owners").fetch(); - - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertNotNull(fetched.getService()); - } - - @Test - void test_finderByNameWithFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_name_fields")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - Spreadsheet fetched = - Spreadsheets.findByName(created.getFullyQualifiedName()) - .withFields("service", "tags") - .fetch(); - - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); - } - - @Test - void test_createMultipleSpreadsheetsUnderSameService(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - for (int i = 0; i < 3; i++) { - Spreadsheet spreadsheet = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_" + i)) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - assertNotNull(spreadsheet); - assertNotNull(spreadsheet.getId()); - assertTrue( - spreadsheet.getFullyQualifiedName().contains(ns.prefix("spreadsheet_" + i)), - "FQN should contain spreadsheet name"); - } - } - - @Test - void test_getByNameWithFields(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("spreadsheet_byname_fields")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - Spreadsheet fetched = Spreadsheets.getByName(created.getFullyQualifiedName(), "service,owners"); - - assertNotNull(fetched); - assertEquals(created.getId(), fetched.getId()); - assertNotNull(fetched.getService()); - } - @Test void test_spreadsheetFQNStructure(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); @@ -254,12 +202,6 @@ void test_spreadsheetFQNStructure(TestNamespace ns) { String expectedFqn = driveService.getFullyQualifiedName() + "." + ns.prefix("fqn_test"); assertEquals(expectedFqn, spreadsheet.getFullyQualifiedName()); - assertTrue( - spreadsheet.getFullyQualifiedName().startsWith(driveService.getFullyQualifiedName()), - "Spreadsheet FQN should start with service FQN"); - assertTrue( - spreadsheet.getFullyQualifiedName().endsWith(spreadsheet.getName()), - "Spreadsheet FQN should end with spreadsheet name"); } @Test @@ -267,13 +209,10 @@ void test_createSpreadsheetNameUniqueness(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); String uniqueName = ns.prefix("unique_spreadsheet"); - Spreadsheet first = - Spreadsheets.create() - .name(uniqueName) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - assertNotNull(first); + Spreadsheets.create() + .name(uniqueName) + .withService(driveService.getFullyQualifiedName()) + .execute(); assertThrows( Exception.class, @@ -282,7 +221,7 @@ void test_createSpreadsheetNameUniqueness(TestNamespace ns) { .name(uniqueName) .withService(driveService.getFullyQualifiedName()) .execute(), - "Creating duplicate spreadsheet with same name under same service should fail"); + "Creating duplicate spreadsheet under same service should fail"); } @Test @@ -321,208 +260,6 @@ void test_spreadsheetInDirectory(TestNamespace ns) { assertNotNull(spreadsheet.getDirectory()); assertEquals(directory.getId(), spreadsheet.getDirectory().getId()); - assertEquals( - directory.getFullyQualifiedName(), spreadsheet.getDirectory().getFullyQualifiedName()); - } - - @Test - void test_updateSpreadsheet(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet created = - Spreadsheets.create() - .name(ns.prefix("updateSpreadsheet")) - .withDescription("description") - .withService(driveService.getFullyQualifiedName()) - .execute(); - - Spreadsheet fetched = Spreadsheets.get(created.getId().toString()); - fetched.setDescription("updated description"); - - Spreadsheet updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); - assertEquals("updated description", updated.getDescription()); - - fetched = Spreadsheets.get(created.getId().toString()); - fetched.setPath("/new/path/to/spreadsheet"); - - updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); - assertEquals("/new/path/to/spreadsheet", updated.getPath()); - - fetched = Spreadsheets.get(created.getId().toString()); - fetched.setSize(1024000); - - updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); - assertEquals(Integer.valueOf(1024000), updated.getSize()); - } - - @Test - void test_patchSpreadsheetAttributes(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet spreadsheet = - Spreadsheets.create() - .name(ns.prefix("patchSpreadsheet")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - Spreadsheet fetched = Spreadsheets.get(spreadsheet.getId().toString()); - fetched.setDescription("patched description"); - Spreadsheet patched = - Spreadsheets.update(spreadsheet.getId().toString()).entity(fetched).execute(); - assertEquals("patched description", patched.getDescription()); - } - - @org.junit.jupiter.api.Disabled( - "Worksheet relationship not returned in spreadsheet fields - backend setFields needs worksheets support") - @Test - void test_spreadsheetWithWorksheets(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet spreadsheet = - Spreadsheets.create() - .name(ns.prefix("salesData")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - - for (int i = 1; i <= 3; i++) { - Worksheets.create() - .name(ns.prefix("sheet" + i)) - .withSpreadsheet(spreadsheet.getFullyQualifiedName()) - .execute(); - } - - Spreadsheet spreadsheetWithWorksheets = - Spreadsheets.find(spreadsheet.getId().toString()).withFields("worksheets").fetch(); - assertNotNull(spreadsheetWithWorksheets.getWorksheets()); - // Filter worksheets that belong to this test by namespace prefix - long testWorksheetCount = - spreadsheetWithWorksheets.getWorksheets().stream() - .filter(ws -> ws.getName().startsWith(ns.prefix("sheet"))) - .count(); - assertEquals(3, testWorksheetCount, "Should have 3 worksheets with test namespace prefix"); - - for (EntityReference worksheetRef : spreadsheetWithWorksheets.getWorksheets()) { - assertNotNull(worksheetRef.getId()); - assertNotNull(worksheetRef.getName()); - } - } - - @Test - void test_listSpreadsheetsByService(TestNamespace ns) { - DriveService service1 = DriveServiceTestFactory.createGoogleDrive(ns, "service1"); - DriveService service2 = DriveServiceTestFactory.createGoogleDrive(ns, "service2"); - - for (int i = 0; i < 3; i++) { - Spreadsheets.create() - .name(ns.prefix("spreadsheet_service1_" + i)) - .withService(service1.getFullyQualifiedName()) - .execute(); - Spreadsheets.create() - .name(ns.prefix("spreadsheet_service2_" + i)) - .withService(service2.getFullyQualifiedName()) - .execute(); - } - - ListParams params = new ListParams().withService(service1.getFullyQualifiedName()); - ListResponse list = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(list.getData().size() >= 3); - assertTrue( - list.getData().stream().allMatch(s -> s.getService().getId().equals(service1.getId()))); - - params = new ListParams().withService(service2.getFullyQualifiedName()); - list = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(list.getData().size() >= 3); - assertTrue( - list.getData().stream().allMatch(s -> s.getService().getId().equals(service2.getId()))); - } - - @Test - void test_spreadsheetFQNPatterns(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Spreadsheet directSpreadsheet = - Spreadsheets.create() - .name(ns.prefix("directSheet")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - assertEquals( - driveService.getFullyQualifiedName() + "." + ns.prefix("directSheet"), - directSpreadsheet.getFullyQualifiedName()); - assertNull(directSpreadsheet.getDirectory()); - - Directory dir1 = - Directories.create() - .name(ns.prefix("finance")) - .withService(driveService.getFullyQualifiedName()) - .withPath("/finance") - .execute(); - - Directory dir2 = - Directories.create() - .name(ns.prefix("2024")) - .withService(driveService.getFullyQualifiedName()) - .withParent(dir1.getFullyQualifiedName()) - .withPath("/finance/2024") - .execute(); - - Spreadsheet dirSpreadsheet = - Spreadsheets.create() - .name(ns.prefix("budget")) - .withService(driveService.getFullyQualifiedName()) - .withParent(dir2.getEntityReference()) - .execute(); - assertEquals( - driveService.getFullyQualifiedName() - + "." - + ns.prefix("finance") - + "." - + ns.prefix("2024") - + "." - + ns.prefix("budget"), - dirSpreadsheet.getFullyQualifiedName()); - assertNotNull(dirSpreadsheet.getDirectory()); - assertEquals(dir2.getId(), dirSpreadsheet.getDirectory().getId()); - } - - @Test - void test_spreadsheetsWithAndWithoutDirectory(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Directory directory = - Directories.create() - .name(ns.prefix("reports")) - .withService(driveService.getFullyQualifiedName()) - .withPath("/reports") - .execute(); - - for (int i = 0; i < 2; i++) { - Spreadsheets.create() - .name(ns.prefix("direct_spreadsheet_" + i)) - .withService(driveService.getFullyQualifiedName()) - .execute(); - } - - for (int i = 0; i < 2; i++) { - Spreadsheets.create() - .name(ns.prefix("dir_spreadsheet_" + i)) - .withService(driveService.getFullyQualifiedName()) - .withParent(directory.getEntityReference()) - .execute(); - } - - ListParams params = new ListParams().withService(driveService.getFullyQualifiedName()); - ListResponse list = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(list.getData().size() >= 4); - - long withDirectory = list.getData().stream().filter(s -> s.getDirectory() != null).count(); - long withoutDirectory = list.getData().stream().filter(s -> s.getDirectory() == null).count(); - assertTrue(withDirectory >= 2); - assertTrue(withoutDirectory >= 2); - - params = new ListParams().withDirectory(directory.getFullyQualifiedName()); - list = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(list.getData().size() >= 2); - assertTrue(list.getData().stream().allMatch(s -> s.getDirectory() != null)); } @Test @@ -536,24 +273,12 @@ void test_listSpreadsheetsByDirectory(TestNamespace ns) { .withPath("/reports") .execute(); - Directory dir2 = - Directories.create() - .name(ns.prefix("analytics")) - .withService(driveService.getFullyQualifiedName()) - .withPath("/analytics") - .execute(); - for (int i = 0; i < 2; i++) { Spreadsheets.create() .name(ns.prefix("report_" + i)) .withService(driveService.getFullyQualifiedName()) .withParent(dir1.getEntityReference()) .execute(); - Spreadsheets.create() - .name(ns.prefix("analytics_" + i)) - .withService(driveService.getFullyQualifiedName()) - .withParent(dir2.getEntityReference()) - .execute(); } ListParams params = new ListParams().withDirectory(dir1.getFullyQualifiedName()); @@ -563,14 +288,6 @@ void test_listSpreadsheetsByDirectory(TestNamespace ns) { list.getData().stream() .allMatch( s -> s.getDirectory() != null && s.getDirectory().getId().equals(dir1.getId()))); - - params = new ListParams().withDirectory(dir2.getFullyQualifiedName()); - list = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(list.getData().size() >= 2); - assertTrue( - list.getData().stream() - .allMatch( - s -> s.getDirectory() != null && s.getDirectory().getId().equals(dir2.getId()))); } @Test @@ -589,227 +306,19 @@ void test_listSpreadsheetsWithRootParameter(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); - Spreadsheets.create() - .name(ns.prefix("rootSpreadsheet2")) - .withService(driveService.getFullyQualifiedName()) - .execute(); - Spreadsheets.create() .name(ns.prefix("childSpreadsheet1")) .withService(driveService.getFullyQualifiedName()) .withParent(sheetsDir.getEntityReference()) .execute(); - Spreadsheets.create() - .name(ns.prefix("childSpreadsheet2")) - .withService(driveService.getFullyQualifiedName()) - .withParent(sheetsDir.getEntityReference()) - .execute(); - - ListParams params = new ListParams().withService(driveService.getFullyQualifiedName()); - ListResponse allSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(allSpreadsheets.getData().size() >= 4); - - params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); - ListResponse rootSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(rootSpreadsheets.getData().size() >= 2); - - for (Spreadsheet spreadsheet : rootSpreadsheets.getData()) { - assertNull(spreadsheet.getDirectory()); - assertTrue( - spreadsheet.getName().equals(ns.prefix("rootSpreadsheet1")) - || spreadsheet.getName().equals(ns.prefix("rootSpreadsheet2"))); - } - - params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("false"); - ListResponse nonRootSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(nonRootSpreadsheets.getData().size() >= 4); - } - - @Test - void test_listSpreadsheetsWithRootParameterAndPagination(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - Directory folder = - Directories.create() - .name(ns.prefix("spreadsheetsFolder")) - .withService(driveService.getFullyQualifiedName()) - .withPath("/spreadsheets") - .execute(); - - for (int i = 1; i <= 7; i++) { - Spreadsheets.create() - .name(ns.prefix("rootSpreadsheet" + i)) - .withService(driveService.getFullyQualifiedName()) - .execute(); - } - - for (int i = 1; i <= 3; i++) { - Spreadsheets.create() - .name(ns.prefix("childSpreadsheet" + i)) - .withService(driveService.getFullyQualifiedName()) - .withParent(folder.getEntityReference()) - .execute(); - } - - ListParams params = - new ListParams() - .withService(driveService.getFullyQualifiedName()) - .withRoot("true") - .withLimit(3); - - ListResponse firstPage = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(firstPage.getData().size() <= 3); - assertNotNull(firstPage.getPaging().getAfter()); - - for (Spreadsheet spreadsheet : firstPage.getData()) { - assertNull(spreadsheet.getDirectory()); - } - - params = params.withAfter(firstPage.getPaging().getAfter()); - ListResponse secondPage = SdkClients.adminClient().spreadsheets().list(params); - assertTrue(secondPage.getData().size() <= 3); - - for (Spreadsheet spreadsheet : secondPage.getData()) { - assertNull(spreadsheet.getDirectory()); - } - - params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); - ListResponse allRootSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(allRootSpreadsheets.getData().size() >= 7); - } - - @Test - void test_listSpreadsheetsWithRootParameterEmptyResult(TestNamespace ns) { - DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); - - for (int i = 1; i <= 2; i++) { - Directory dir = - Directories.create() - .name(ns.prefix("folder" + i)) - .withService(driveService.getFullyQualifiedName()) - .withPath("/folder" + i) - .execute(); - - for (int j = 1; j <= 2; j++) { - Spreadsheets.create() - .name(ns.prefix(dir.getName() + "_spreadsheet" + j)) - .withService(driveService.getFullyQualifiedName()) - .withParent(dir.getEntityReference()) - .execute(); - } - } - ListParams params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); ListResponse rootSpreadsheets = SdkClients.adminClient().spreadsheets().list(params); - assertEquals(0, rootSpreadsheets.getData().size()); - - params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("false"); - ListResponse allSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(allSpreadsheets.getData().size() >= 4); - for (Spreadsheet spreadsheet : allSpreadsheets.getData()) { - assertNotNull(spreadsheet.getDirectory()); - assertEquals("directory", spreadsheet.getDirectory().getType()); - } - } - - @org.junit.jupiter.api.Disabled( - "Root filter not working reliably with parallel tests - needs investigation") - @Test - void test_listSpreadsheetsWithRootParameterAcrossMultipleServices(TestNamespace ns) { - DriveService service1 = DriveServiceTestFactory.createGoogleDrive(ns, "googleSheetsService"); - DriveService service2 = DriveServiceTestFactory.createGoogleDrive(ns, "excelOnlineService"); - - Directory googleDir = - Directories.create() - .name(ns.prefix("googleSheetsFolder")) - .withService(service1.getFullyQualifiedName()) - .withPath("/sheets") - .execute(); - - for (int i = 1; i <= 2; i++) { - Spreadsheets.create() - .name(ns.prefix("googleSheet" + i)) - .withService(service1.getFullyQualifiedName()) - .execute(); - } - for (int i = 1; i <= 2; i++) { - Spreadsheets.create() - .name(ns.prefix("googleChildSheet" + i)) - .withService(service1.getFullyQualifiedName()) - .withParent(googleDir.getEntityReference()) - .execute(); - } - - Directory excelDir = - Directories.create() - .name(ns.prefix("excelFolder")) - .withService(service2.getFullyQualifiedName()) - .withPath("/excel") - .execute(); - - for (int i = 1; i <= 4; i++) { - Spreadsheets.create() - .name(ns.prefix("excelWorkbook" + i)) - .withService(service2.getFullyQualifiedName()) - .execute(); - } - - Spreadsheets.create() - .name(ns.prefix("excelChildWorkbook")) - .withService(service2.getFullyQualifiedName()) - .withParent(excelDir.getEntityReference()) - .execute(); - - ListParams params = - new ListParams().withService(service1.getFullyQualifiedName()).withRoot("true"); - ListResponse googleRootSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - // Filter to only our test's spreadsheets - long googleSheetCount = - googleRootSpreadsheets.getData().stream() - .filter(s -> s.getName().startsWith(ns.prefix("googleSheet"))) - .count(); - assertTrue(googleSheetCount >= 2, "Should have at least 2 root googleSheet spreadsheets"); - // Verify root spreadsheets have no directory - for (Spreadsheet spreadsheet : googleRootSpreadsheets.getData()) { - if (spreadsheet.getName().startsWith(ns.prefix("googleSheet"))) { - assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); - } - } - - params = new ListParams().withService(service2.getFullyQualifiedName()).withRoot("true"); - ListResponse excelRootSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - // Filter to only our test's spreadsheets - long excelWorkbookCount = - excelRootSpreadsheets.getData().stream() - .filter(s -> s.getName().startsWith(ns.prefix("excelWorkbook"))) - .count(); - assertTrue(excelWorkbookCount >= 4, "Should have at least 4 root excelWorkbook spreadsheets"); - // Verify root spreadsheets have no directory - for (Spreadsheet spreadsheet : excelRootSpreadsheets.getData()) { - if (spreadsheet.getName().startsWith(ns.prefix("excelWorkbook"))) { - assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); - } + for (Spreadsheet spreadsheet : rootSpreadsheets.getData()) { + assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); } - - params = new ListParams().withService(service1.getFullyQualifiedName()).withRoot("false"); - ListResponse allGoogleSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(allGoogleSpreadsheets.getData().size() >= 4); - - params = new ListParams().withService(service2.getFullyQualifiedName()).withRoot("false"); - ListResponse allExcelSpreadsheets = - SdkClients.adminClient().spreadsheets().list(params); - assertTrue(allExcelSpreadsheets.getData().size() >= 5); } } diff --git a/openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/drives/FolderService.java b/openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/drives/FolderService.java new file mode 100644 index 000000000000..6915e39c6bac --- /dev/null +++ b/openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/drives/FolderService.java @@ -0,0 +1,23 @@ +package org.openmetadata.sdk.services.drives; + +import org.openmetadata.schema.api.data.CreateFolder; +import org.openmetadata.schema.entity.data.Folder; +import org.openmetadata.sdk.exceptions.OpenMetadataException; +import org.openmetadata.sdk.network.HttpClient; +import org.openmetadata.sdk.network.HttpMethod; +import org.openmetadata.sdk.services.EntityServiceBase; + +public class FolderService extends EntityServiceBase { + public FolderService(HttpClient httpClient) { + super(httpClient, "/v1/drive/folders"); + } + + @Override + protected Class getEntityClass() { + return Folder.class; + } + + public Folder create(CreateFolder request) throws OpenMetadataException { + return httpClient.execute(HttpMethod.POST, basePath, request, Folder.class); + } +} From 5c23cd0d9eae123ae57e28cc2891bf175a45dc19 Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 16:36:51 +0530 Subject: [PATCH 4/9] fix(it): make FolderResourceIT pass inherited BaseEntityIT tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three real issues surfaced by the inherited generic tests after the drive-IT migration: 1. FolderResource.list was missing @Min(0) / @Max(1000000) on the limit query param, so negative or excessive values were silently accepted. Add validation to match DirectoryResource/WorksheetResource. This fixes BaseEntityIT.get_entityListWithInvalidLimit_4xx. 2. FolderResource hard-delete is asynchronous — it kicks off deleteByIdAsync and returns 200 before the row is gone. The generic delete_entityAsAdmin_hardDelete_200 test asserts the entity is no longer fetchable immediately. Override hardDeleteEntity in FolderResourceIT to poll on include=deleted until the async delete completes. 3. BaseEntityIT.get_deletedEntityVersion_200 calls getVersion(...) but only gated on supportsSoftDelete/supportsPatch, missing the supportsGetByVersion gate. For entities like Folder that don't expose /versions, the test threw UnsupportedOperationException from the subclass override. Add the missing gate. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../org/openmetadata/it/tests/BaseEntityIT.java | 2 +- .../openmetadata/it/tests/FolderResourceIT.java | 17 +++++++++++++++++ .../service/resources/drive/FolderResource.java | 9 ++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java index 75d4b6c686d0..591034e698a0 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/BaseEntityIT.java @@ -2052,7 +2052,7 @@ void patch_validEntityOwner_200(TestNamespace ns) { @Test void get_deletedEntityVersion_200(TestNamespace ns) { - if (!supportsSoftDelete || !supportsPatch) return; + if (!supportsSoftDelete || !supportsPatch || !supportsGetByVersion) return; K createRequest = createMinimalRequest(ns); T entity = createEntity(createRequest); diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java index 97f5e6a80aa1..ddb3828705a8 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java @@ -6,9 +6,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import org.awaitility.Awaitility; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; @@ -92,6 +94,21 @@ protected void hardDeleteEntity(String id) { Map params = new HashMap<>(); params.put("hardDelete", "true"); getFolderService().delete(id, params); + // FolderResource hard-delete is asynchronous: it returns 200 immediately and removes + // the row in the background. Poll with include=deleted until the entity is fully gone + // so BaseEntityIT.delete_entityAsAdmin_hardDelete_200 sees the post-condition. + Awaitility.await() + .pollInterval(Duration.ofMillis(200)) + .atMost(Duration.ofSeconds(15)) + .until( + () -> { + try { + getFolderService().get(id, null, "deleted"); + return false; + } catch (Exception e) { + return true; + } + }); } @Override diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java index 74de4d4137a2..bdde3e733eae 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java @@ -9,6 +9,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DefaultValue; @@ -97,7 +99,12 @@ public ResultList list( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @QueryParam("fields") String fieldsParam, - @QueryParam("limit") @DefaultValue("10") int limit, + @Parameter(description = "Limit the number folders returned. (1 to 1000000, default = 10)") + @DefaultValue("10") + @QueryParam("limit") + @Min(value = 0, message = "must be greater than or equal to 0") + @Max(value = 1000000, message = "must be less than or equal to 1000000") + int limit, @QueryParam("before") String before, @QueryParam("after") String after, @QueryParam("include") @DefaultValue("non-deleted") Include include) { From cb8b3a95f88ea61dd33e8934aad7a6ad780c7b5e Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 16:45:30 +0530 Subject: [PATCH 5/9] chore: address gitar-bot review on PR #28047 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SpreadsheetResourceIT.test_listSpreadsheetsWithRootParameter was vacuously passing if the list came back empty (the for-loop body silently runs zero times). Add an explicit assertFalse(getData().isEmpty()) so a regression in the ?root=true filter actually fails the test. - FolderResource.list parameter description said "1 to 1000000" but the annotation is @Min(0) — 0 is a valid limit (returns empty page). Align the description with the annotation. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../java/org/openmetadata/it/tests/SpreadsheetResourceIT.java | 4 ++++ .../openmetadata/service/resources/drive/FolderResource.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java index 8de4e401eb76..6f6c64eba9e8 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java @@ -1,6 +1,7 @@ package org.openmetadata.it.tests; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -317,6 +318,9 @@ void test_listSpreadsheetsWithRootParameter(TestNamespace ns) { ListResponse rootSpreadsheets = SdkClients.adminClient().spreadsheets().list(params); + assertFalse( + rootSpreadsheets.getData().isEmpty(), + "Root spreadsheets list should not be empty — we just created one"); for (Spreadsheet spreadsheet : rootSpreadsheets.getData()) { assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java index bdde3e733eae..6fd6a93626d5 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java @@ -99,7 +99,7 @@ public ResultList list( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @QueryParam("fields") String fieldsParam, - @Parameter(description = "Limit the number folders returned. (1 to 1000000, default = 10)") + @Parameter(description = "Limit the number folders returned. (0 to 1000000, default = 10)") @DefaultValue("10") @QueryParam("limit") @Min(value = 0, message = "must be greater than or equal to 0") From a28c8c2d6a121b3472895f54de80f73d889b58e9 Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 16:53:47 +0530 Subject: [PATCH 6/9] test(it): restore entity-specific drive tests dropped during BaseEntityIT migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous migration commit was too aggressive in deleting tests it assumed BaseEntityIT covers. Restore the entity-specific tests: SpreadsheetResourceIT (8 restored): - test_createSpreadsheetWithOptionalFields (displayName + description) - test_updateSpreadsheet (Spreadsheet-specific path/size fields) - test_spreadsheetWithWorksheets (@Disabled — worksheet relationship) - test_listSpreadsheetsByService (?service filter) - test_spreadsheetFQNPatterns (nested directory FQN construction) - test_spreadsheetsWithAndWithoutDirectory (directory-presence variations) - test_listSpreadsheetsWithRootParameterAndPagination (root + pagination) - test_listSpreadsheetsWithRootParameterEmptyResult - test_listSpreadsheetsWithRootParameterAcrossMultipleServices (@Disabled) FileResourceIT (2 restored): - test_createFileWithDisplayName - test_fileWithAllOptionalFields DirectoryResourceIT (1 restored): - test_createDirectoryWithAllFields BaseEntityIT still covers the genuinely redundant tests that stayed deleted (CRUD smoke tests, get-by-id, get-by-name with fields, delete, non-existent ID/FQN, fluent-SDK find variants). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../it/tests/DirectoryResourceIT.java | 22 + .../openmetadata/it/tests/FileResourceIT.java | 40 ++ .../it/tests/SpreadsheetResourceIT.java | 376 ++++++++++++++++++ 3 files changed, 438 insertions(+) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java index 64749ba9675c..431a01fb5f63 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java @@ -222,4 +222,26 @@ void test_directoryFullyQualifiedName(TestNamespace ns) { assertTrue(created.getFullyQualifiedName().contains(driveService.getName())); assertTrue(created.getFullyQualifiedName().contains(directoryName)); } + + @Test + void test_createDirectoryWithAllFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + String directoryName = ns.prefix("test_directory_full"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Complete Test Directory") + .withDescription("A directory with all fields populated for testing") + .execute(); + + assertEquals(directoryName, created.getName()); + assertEquals("Complete Test Directory", created.getDisplayName()); + assertEquals("A directory with all fields populated for testing", created.getDescription()); + assertNotNull(created.getService()); + assertTrue( + created.getFullyQualifiedName().contains(directoryName), + "FQN should contain directory name"); + } } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java index 0b4519397a26..4dd2df3550dd 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java @@ -344,4 +344,44 @@ void test_patchFileWithoutColumns_doesNotNpe(TestNamespace ns) { assertEquals("Updated description", patched.getDescription()); assertNull(patched.getColumns()); } + + @Test + void test_createFileWithDisplayName(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + String fileName = ns.prefix("test_file_display"); + String displayName = "My Test File"; + + File createdFile = + Files.create() + .name(fileName) + .withDisplayName(displayName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertEquals(fileName, createdFile.getName()); + assertEquals(displayName, createdFile.getDisplayName()); + } + + @Test + void test_fileWithAllOptionalFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + String fileName = ns.prefix("test_file_full"); + String displayName = "Complete Test File"; + String description = "A file with all optional fields populated"; + + File createdFile = + Files.create() + .name(fileName) + .withDisplayName(displayName) + .withDescription(description) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertEquals(fileName, createdFile.getName()); + assertEquals(displayName, createdFile.getDisplayName()); + assertEquals(description, createdFile.getDescription()); + assertEquals(driveService.getFullyQualifiedName(), createdFile.getService().getName()); + } } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java index 6f6c64eba9e8..6fa173168772 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java @@ -22,6 +22,7 @@ import org.openmetadata.schema.entity.data.Spreadsheet; import org.openmetadata.schema.entity.services.DriveService; import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.schema.type.EntityReference; import org.openmetadata.sdk.fluent.Directories; import org.openmetadata.sdk.fluent.Spreadsheets; import org.openmetadata.sdk.fluent.Worksheets; @@ -325,4 +326,379 @@ void test_listSpreadsheetsWithRootParameter(TestNamespace ns) { assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); } } + + @Test + void test_createSpreadsheetWithOptionalFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Spreadsheet spreadsheet = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_optional")) + .withDisplayName("Display Name for Spreadsheet") + .withDescription("Spreadsheet with optional fields") + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertEquals("Display Name for Spreadsheet", spreadsheet.getDisplayName()); + assertEquals("Spreadsheet with optional fields", spreadsheet.getDescription()); + } + + @Test + void test_updateSpreadsheet(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("updateSpreadsheet")) + .withDescription("description") + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = Spreadsheets.get(created.getId().toString()); + fetched.setDescription("updated description"); + Spreadsheet updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); + assertEquals("updated description", updated.getDescription()); + + fetched = Spreadsheets.get(created.getId().toString()); + fetched.setPath("/new/path/to/spreadsheet"); + updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); + assertEquals("/new/path/to/spreadsheet", updated.getPath()); + + fetched = Spreadsheets.get(created.getId().toString()); + fetched.setSize(1024000); + updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); + assertEquals(Integer.valueOf(1024000), updated.getSize()); + } + + @org.junit.jupiter.api.Disabled( + "Worksheet relationship not returned in spreadsheet fields - backend setFields needs worksheets support") + @Test + void test_spreadsheetWithWorksheets(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Spreadsheet spreadsheet = + Spreadsheets.create() + .name(ns.prefix("salesData")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + for (int i = 1; i <= 3; i++) { + Worksheets.create() + .name(ns.prefix("sheet" + i)) + .withSpreadsheet(spreadsheet.getFullyQualifiedName()) + .execute(); + } + + Spreadsheet spreadsheetWithWorksheets = + Spreadsheets.find(spreadsheet.getId().toString()).withFields("worksheets").fetch(); + assertNotNull(spreadsheetWithWorksheets.getWorksheets()); + long testWorksheetCount = + spreadsheetWithWorksheets.getWorksheets().stream() + .filter(ws -> ws.getName().startsWith(ns.prefix("sheet"))) + .count(); + assertEquals(3, testWorksheetCount, "Should have 3 worksheets with test namespace prefix"); + + for (EntityReference worksheetRef : spreadsheetWithWorksheets.getWorksheets()) { + assertNotNull(worksheetRef.getId()); + assertNotNull(worksheetRef.getName()); + } + } + + @Test + void test_listSpreadsheetsByService(TestNamespace ns) { + DriveService service1 = DriveServiceTestFactory.createGoogleDrive(ns, "service1"); + DriveService service2 = DriveServiceTestFactory.createGoogleDrive(ns, "service2"); + + for (int i = 0; i < 3; i++) { + Spreadsheets.create() + .name(ns.prefix("spreadsheet_service1_" + i)) + .withService(service1.getFullyQualifiedName()) + .execute(); + Spreadsheets.create() + .name(ns.prefix("spreadsheet_service2_" + i)) + .withService(service2.getFullyQualifiedName()) + .execute(); + } + + ListParams params = new ListParams().withService(service1.getFullyQualifiedName()); + ListResponse list = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(list.getData().size() >= 3); + assertTrue( + list.getData().stream().allMatch(s -> s.getService().getId().equals(service1.getId()))); + + params = new ListParams().withService(service2.getFullyQualifiedName()); + list = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(list.getData().size() >= 3); + assertTrue( + list.getData().stream().allMatch(s -> s.getService().getId().equals(service2.getId()))); + } + + @Test + void test_spreadsheetFQNPatterns(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Spreadsheet directSpreadsheet = + Spreadsheets.create() + .name(ns.prefix("directSheet")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + assertEquals( + driveService.getFullyQualifiedName() + "." + ns.prefix("directSheet"), + directSpreadsheet.getFullyQualifiedName()); + assertNull(directSpreadsheet.getDirectory()); + + Directory dir1 = + Directories.create() + .name(ns.prefix("finance")) + .withService(driveService.getFullyQualifiedName()) + .withPath("/finance") + .execute(); + + Directory dir2 = + Directories.create() + .name(ns.prefix("2024")) + .withService(driveService.getFullyQualifiedName()) + .withParent(dir1.getFullyQualifiedName()) + .withPath("/finance/2024") + .execute(); + + Spreadsheet dirSpreadsheet = + Spreadsheets.create() + .name(ns.prefix("budget")) + .withService(driveService.getFullyQualifiedName()) + .withParent(dir2.getEntityReference()) + .execute(); + assertEquals( + driveService.getFullyQualifiedName() + + "." + + ns.prefix("finance") + + "." + + ns.prefix("2024") + + "." + + ns.prefix("budget"), + dirSpreadsheet.getFullyQualifiedName()); + assertNotNull(dirSpreadsheet.getDirectory()); + assertEquals(dir2.getId(), dirSpreadsheet.getDirectory().getId()); + } + + @Test + void test_spreadsheetsWithAndWithoutDirectory(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Directory directory = + Directories.create() + .name(ns.prefix("reports")) + .withService(driveService.getFullyQualifiedName()) + .withPath("/reports") + .execute(); + + for (int i = 0; i < 2; i++) { + Spreadsheets.create() + .name(ns.prefix("direct_spreadsheet_" + i)) + .withService(driveService.getFullyQualifiedName()) + .execute(); + } + + for (int i = 0; i < 2; i++) { + Spreadsheets.create() + .name(ns.prefix("dir_spreadsheet_" + i)) + .withService(driveService.getFullyQualifiedName()) + .withParent(directory.getEntityReference()) + .execute(); + } + + ListParams params = new ListParams().withService(driveService.getFullyQualifiedName()); + ListResponse list = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(list.getData().size() >= 4); + + long withDirectory = list.getData().stream().filter(s -> s.getDirectory() != null).count(); + long withoutDirectory = list.getData().stream().filter(s -> s.getDirectory() == null).count(); + assertTrue(withDirectory >= 2); + assertTrue(withoutDirectory >= 2); + + params = new ListParams().withDirectory(directory.getFullyQualifiedName()); + list = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(list.getData().size() >= 2); + assertTrue(list.getData().stream().allMatch(s -> s.getDirectory() != null)); + } + + @Test + void test_listSpreadsheetsWithRootParameterAndPagination(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Directory folder = + Directories.create() + .name(ns.prefix("spreadsheetsFolder")) + .withService(driveService.getFullyQualifiedName()) + .withPath("/spreadsheets") + .execute(); + + for (int i = 1; i <= 7; i++) { + Spreadsheets.create() + .name(ns.prefix("rootSpreadsheet" + i)) + .withService(driveService.getFullyQualifiedName()) + .execute(); + } + + for (int i = 1; i <= 3; i++) { + Spreadsheets.create() + .name(ns.prefix("childSpreadsheet" + i)) + .withService(driveService.getFullyQualifiedName()) + .withParent(folder.getEntityReference()) + .execute(); + } + + ListParams params = + new ListParams() + .withService(driveService.getFullyQualifiedName()) + .withRoot("true") + .withLimit(3); + + ListResponse firstPage = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(firstPage.getData().size() <= 3); + assertNotNull(firstPage.getPaging().getAfter()); + + for (Spreadsheet spreadsheet : firstPage.getData()) { + assertNull(spreadsheet.getDirectory()); + } + + params = params.withAfter(firstPage.getPaging().getAfter()); + ListResponse secondPage = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(secondPage.getData().size() <= 3); + + for (Spreadsheet spreadsheet : secondPage.getData()) { + assertNull(spreadsheet.getDirectory()); + } + + params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); + ListResponse allRootSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertTrue(allRootSpreadsheets.getData().size() >= 7); + } + + @Test + void test_listSpreadsheetsWithRootParameterEmptyResult(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + for (int i = 1; i <= 2; i++) { + Directory dir = + Directories.create() + .name(ns.prefix("folder" + i)) + .withService(driveService.getFullyQualifiedName()) + .withPath("/folder" + i) + .execute(); + + for (int j = 1; j <= 2; j++) { + Spreadsheets.create() + .name(ns.prefix(dir.getName() + "_spreadsheet" + j)) + .withService(driveService.getFullyQualifiedName()) + .withParent(dir.getEntityReference()) + .execute(); + } + } + + ListParams params = + new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); + ListResponse rootSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertEquals(0, rootSpreadsheets.getData().size()); + + params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("false"); + ListResponse allSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertTrue(allSpreadsheets.getData().size() >= 4); + for (Spreadsheet spreadsheet : allSpreadsheets.getData()) { + assertNotNull(spreadsheet.getDirectory()); + assertEquals("directory", spreadsheet.getDirectory().getType()); + } + } + + @org.junit.jupiter.api.Disabled( + "Root filter not working reliably with parallel tests - needs investigation") + @Test + void test_listSpreadsheetsWithRootParameterAcrossMultipleServices(TestNamespace ns) { + DriveService service1 = DriveServiceTestFactory.createGoogleDrive(ns, "googleSheetsService"); + DriveService service2 = DriveServiceTestFactory.createGoogleDrive(ns, "excelOnlineService"); + + Directory googleDir = + Directories.create() + .name(ns.prefix("googleSheetsFolder")) + .withService(service1.getFullyQualifiedName()) + .withPath("/sheets") + .execute(); + + for (int i = 1; i <= 2; i++) { + Spreadsheets.create() + .name(ns.prefix("googleSheet" + i)) + .withService(service1.getFullyQualifiedName()) + .execute(); + } + + for (int i = 1; i <= 2; i++) { + Spreadsheets.create() + .name(ns.prefix("googleChildSheet" + i)) + .withService(service1.getFullyQualifiedName()) + .withParent(googleDir.getEntityReference()) + .execute(); + } + + Directory excelDir = + Directories.create() + .name(ns.prefix("excelFolder")) + .withService(service2.getFullyQualifiedName()) + .withPath("/excel") + .execute(); + + for (int i = 1; i <= 4; i++) { + Spreadsheets.create() + .name(ns.prefix("excelWorkbook" + i)) + .withService(service2.getFullyQualifiedName()) + .execute(); + } + + Spreadsheets.create() + .name(ns.prefix("excelChildWorkbook")) + .withService(service2.getFullyQualifiedName()) + .withParent(excelDir.getEntityReference()) + .execute(); + + ListParams params = + new ListParams().withService(service1.getFullyQualifiedName()).withRoot("true"); + ListResponse googleRootSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + long googleSheetCount = + googleRootSpreadsheets.getData().stream() + .filter(s -> s.getName().startsWith(ns.prefix("googleSheet"))) + .count(); + assertTrue(googleSheetCount >= 2, "Should have at least 2 root googleSheet spreadsheets"); + for (Spreadsheet spreadsheet : googleRootSpreadsheets.getData()) { + if (spreadsheet.getName().startsWith(ns.prefix("googleSheet"))) { + assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); + } + } + + params = new ListParams().withService(service2.getFullyQualifiedName()).withRoot("true"); + ListResponse excelRootSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + long excelWorkbookCount = + excelRootSpreadsheets.getData().stream() + .filter(s -> s.getName().startsWith(ns.prefix("excelWorkbook"))) + .count(); + assertTrue(excelWorkbookCount >= 4, "Should have at least 4 root excelWorkbook spreadsheets"); + for (Spreadsheet spreadsheet : excelRootSpreadsheets.getData()) { + if (spreadsheet.getName().startsWith(ns.prefix("excelWorkbook"))) { + assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); + } + } + + params = new ListParams().withService(service1.getFullyQualifiedName()).withRoot("false"); + ListResponse allGoogleSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertTrue(allGoogleSpreadsheets.getData().size() >= 4); + + params = new ListParams().withService(service2.getFullyQualifiedName()).withRoot("false"); + ListResponse allExcelSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertTrue(allExcelSpreadsheets.getData().size() >= 5); + } } From 3baed987c322a6de8edb59b651ebe89bbb0ea9db Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 17:01:12 +0530 Subject: [PATCH 7/9] chore: address remaining gitar-bot + copilot review threads FolderResource: - Grammar: "Limit the number folders" -> "Limit the number of folders" FolderResourceIT: - Javadoc said Folder "supports ... followers" but supportsFollowers=false. Align doc with actual capability flags. - Awaitility hard-delete poll was catching `Exception` and treating any failure as success (would mask transient 500s). Narrow to ApiException with statusCode==404; re-throw everything else so Awaitility surfaces real errors. FileResourceIT: - Pass String IDs to service.update for consistency with the rest of the IT suite (createdFile.getId().toString()). - Compare service references via getFullyQualifiedName() instead of getName(); the latter only matches for top-level services and would silently break if the reference schema changes. SpreadsheetResourceIT: - Import @Disabled and use the short annotation form instead of @org.junit.jupiter.api.Disabled (project standards prohibit FQNs in annotations). - Strengthen test_listSpreadsheetsWithRootParameter: assert the root spreadsheet we created appears in ?root=true results AND the child spreadsheet does NOT, so a broken root filter actually fails the test instead of passing on an empty list. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../openmetadata/it/tests/FileResourceIT.java | 8 +++++--- .../it/tests/FolderResourceIT.java | 18 +++++++++++++----- .../it/tests/SpreadsheetResourceIT.java | 15 ++++++++++----- .../resources/drive/FolderResource.java | 2 +- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java index 4dd2df3550dd..cc4621464d69 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java @@ -191,7 +191,8 @@ void test_createAndGetFile(TestNamespace ns) { assertNotNull(createdFile.getId()); assertEquals(fileName, createdFile.getName()); assertNotNull(createdFile.getService()); - assertEquals(driveService.getFullyQualifiedName(), createdFile.getService().getName()); + assertEquals( + driveService.getFullyQualifiedName(), createdFile.getService().getFullyQualifiedName()); File retrievedFile = Files.get(createdFile.getId().toString()); assertNotNull(retrievedFile); @@ -339,7 +340,7 @@ void test_patchFileWithoutColumns_doesNotNpe(TestNamespace ns) { assertNull(createdFile.getColumns()); createdFile.setDescription("Updated description"); - File patched = getFileService().update(createdFile.getId(), createdFile); + File patched = getFileService().update(createdFile.getId().toString(), createdFile); assertEquals("Updated description", patched.getDescription()); assertNull(patched.getColumns()); @@ -382,6 +383,7 @@ void test_fileWithAllOptionalFields(TestNamespace ns) { assertEquals(fileName, createdFile.getName()); assertEquals(displayName, createdFile.getDisplayName()); assertEquals(description, createdFile.getDescription()); - assertEquals(driveService.getFullyQualifiedName(), createdFile.getService().getName()); + assertEquals( + driveService.getFullyQualifiedName(), createdFile.getService().getFullyQualifiedName()); } } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java index ddb3828705a8..7c71089dd13e 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FolderResourceIT.java @@ -19,6 +19,7 @@ import org.openmetadata.schema.api.data.CreateFolder; import org.openmetadata.schema.entity.data.Folder; import org.openmetadata.schema.type.EntityHistory; +import org.openmetadata.sdk.exceptions.ApiException; import org.openmetadata.sdk.models.ListParams; import org.openmetadata.sdk.models.ListResponse; import org.openmetadata.sdk.services.drives.FolderService; @@ -27,8 +28,9 @@ * Integration tests for Folder entity operations. * *

Folder is a service-less drive entity at {@code /v1/drive/folders}. It supports owners, - * tags, domains, and followers, but does not expose version history or bulk endpoints. Extends - * BaseEntityIT so generic CRUD/tag/domain coverage runs automatically. + * tags, and domains, but does not expose version history, followers, custom extensions, or bulk + * endpoints (see the {@code supports*} flags below). Extends BaseEntityIT so generic CRUD / tag / + * domain coverage runs automatically. */ @Execution(ExecutionMode.CONCURRENT) public class FolderResourceIT extends BaseEntityIT { @@ -96,7 +98,10 @@ protected void hardDeleteEntity(String id) { getFolderService().delete(id, params); // FolderResource hard-delete is asynchronous: it returns 200 immediately and removes // the row in the background. Poll with include=deleted until the entity is fully gone - // so BaseEntityIT.delete_entityAsAdmin_hardDelete_200 sees the post-condition. + // (server returns 404) so BaseEntityIT.delete_entityAsAdmin_hardDelete_200 sees the + // post-condition. Other exceptions (e.g., transient 500s, network errors) must propagate + // so the test doesn't silently pass on real failures — Awaitility re-polls on throw and + // surfaces the last exception when the timeout window expires. Awaitility.await() .pollInterval(Duration.ofMillis(200)) .atMost(Duration.ofSeconds(15)) @@ -105,8 +110,11 @@ protected void hardDeleteEntity(String id) { try { getFolderService().get(id, null, "deleted"); return false; - } catch (Exception e) { - return true; + } catch (ApiException e) { + if (e.getStatusCode() == 404) { + return true; + } + throw e; } }); } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java index 6fa173168772..1c0a512c49d6 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; @@ -319,9 +320,14 @@ void test_listSpreadsheetsWithRootParameter(TestNamespace ns) { ListResponse rootSpreadsheets = SdkClients.adminClient().spreadsheets().list(params); + assertTrue( + rootSpreadsheets.getData().stream() + .anyMatch(s -> s.getName().equals(ns.prefix("rootSpreadsheet1"))), + "Root spreadsheet we just created must appear in ?root=true results"); assertFalse( - rootSpreadsheets.getData().isEmpty(), - "Root spreadsheets list should not be empty — we just created one"); + rootSpreadsheets.getData().stream() + .anyMatch(s -> s.getName().equals(ns.prefix("childSpreadsheet1"))), + "Child spreadsheet must NOT appear in ?root=true results"); for (Spreadsheet spreadsheet : rootSpreadsheets.getData()) { assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); } @@ -370,7 +376,7 @@ void test_updateSpreadsheet(TestNamespace ns) { assertEquals(Integer.valueOf(1024000), updated.getSize()); } - @org.junit.jupiter.api.Disabled( + @Disabled( "Worksheet relationship not returned in spreadsheet fields - backend setFields needs worksheets support") @Test void test_spreadsheetWithWorksheets(TestNamespace ns) { @@ -613,8 +619,7 @@ void test_listSpreadsheetsWithRootParameterEmptyResult(TestNamespace ns) { } } - @org.junit.jupiter.api.Disabled( - "Root filter not working reliably with parallel tests - needs investigation") + @Disabled("Root filter not working reliably with parallel tests - needs investigation") @Test void test_listSpreadsheetsWithRootParameterAcrossMultipleServices(TestNamespace ns) { DriveService service1 = DriveServiceTestFactory.createGoogleDrive(ns, "googleSheetsService"); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java index 6fd6a93626d5..b50a26d7a472 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/drive/FolderResource.java @@ -99,7 +99,7 @@ public ResultList list( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @QueryParam("fields") String fieldsParam, - @Parameter(description = "Limit the number folders returned. (0 to 1000000, default = 10)") + @Parameter(description = "Limit the number of folders returned. (0 to 1000000, default = 10)") @DefaultValue("10") @QueryParam("limit") @Min(value = 0, message = "must be greater than or equal to 0") From 5ca98c46757febcdcde70bcc83c088c1382cf186 Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 17:38:25 +0530 Subject: [PATCH 8/9] test(it): restore all remaining originally-deleted drive tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per reviewer request, restore the rest of the tests that the migration commit removed under the (incorrect) assumption they were fully redundant with BaseEntityIT. FileResourceIT (+8): test_createFileMinimal, test_createFileWithDescription, test_deleteFile, test_findFileById, test_findFileByNameWithFields, test_getFileByNameWithFields, test_getFileWithNonExistentId_shouldFail, test_getFileByNameWithNonExistentFQN_shouldFail. DirectoryResourceIT (+10): test_createDirectoryMinimalRequest, test_getByName, test_getByNameWithFields, test_deleteDirectory, test_findDirectoryById, test_findDirectoryByName, test_findDirectoryWithFields, test_createMultipleDirectories, test_getNonExistentDirectory_fails, test_getByNameNonExistent_fails. SpreadsheetResourceIT (+10): test_createSpreadsheet, test_createSpreadsheetMinimal, test_getSpreadsheetById, test_getSpreadsheetByName, test_deleteSpreadsheet, test_finderWithFields, test_finderByNameWithFields, test_getByNameWithFields, test_createMultipleSpreadsheetsUnderSameService, test_patchSpreadsheetAttributes. BaseEntityIT generic coverage stays intact — the subclass tests and the inherited tests now coexist (deliberate overlap, opted in by reviewer). Counts vs ab535900da (original): File 14→18 (+4 column tests added), Directory 15→15, Spreadsheet 27→27. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../it/tests/DirectoryResourceIT.java | 157 +++++++++++++++++ .../openmetadata/it/tests/FileResourceIT.java | 110 ++++++++++++ .../it/tests/SpreadsheetResourceIT.java | 158 ++++++++++++++++++ 3 files changed, 425 insertions(+) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java index 431a01fb5f63..1cd45dc1e06a 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java @@ -244,4 +244,161 @@ void test_createDirectoryWithAllFields(TestNamespace ns) { created.getFullyQualifiedName().contains(directoryName), "FQN should contain directory name"); } + + @Test + void test_createDirectoryMinimalRequest(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_minimal"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertNotNull(created.getId()); + assertEquals(directoryName, created.getName()); + assertNotNull(created.getService()); + } + + @Test + void test_getByName(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_by_name"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory By Name") + .execute(); + + Directory fetched = Directories.getByName(created.getFullyQualifiedName()); + assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getName(), fetched.getName()); + assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + } + + @Test + void test_getByNameWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_with_fields"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory With Fields") + .execute(); + + Directory fetched = Directories.getByName(created.getFullyQualifiedName(), "service,owners"); + assertEquals(created.getId(), fetched.getId()); + assertNotNull(fetched.getService()); + } + + @Test + void test_deleteDirectory(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_delete"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + String directoryId = created.getId().toString(); + + Directories.delete(directoryId); + + assertThrows( + Exception.class, + () -> Directories.get(directoryId), + "Getting deleted directory should fail"); + } + + @Test + void test_findDirectoryById(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_find"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Directory fetched = Directories.find(created.getId().toString()).fetch(); + assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getName(), fetched.getName()); + } + + @Test + void test_findDirectoryByName(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_find_by_name"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Directory fetched = Directories.findByName(created.getFullyQualifiedName()).fetch(); + assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getName(), fetched.getName()); + } + + @Test + void test_findDirectoryWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String directoryName = ns.prefix("test_directory_find_fields"); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Directory fetched = + Directories.findByName(created.getFullyQualifiedName()) + .withFields("service", "owners", "tags") + .fetch(); + assertEquals(created.getId(), fetched.getId()); + assertNotNull(fetched.getService()); + } + + @Test + void test_createMultipleDirectories(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + for (int i = 1; i <= 3; i++) { + String directoryName = ns.prefix("test_directory_multi_" + i); + Directory created = + Directories.create() + .name(directoryName) + .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory " + i) + .withDescription("Directory number " + i) + .execute(); + + assertEquals(directoryName, created.getName()); + assertEquals("Test Directory " + i, created.getDisplayName()); + + Directory fetched = Directories.get(created.getId().toString()); + assertEquals(created.getId(), fetched.getId()); + } + } + + @Test + void test_getNonExistentDirectory_fails(TestNamespace ns) { + String nonExistentId = "non-existent-directory-id-12345"; + + assertThrows( + Exception.class, + () -> Directories.get(nonExistentId), + "Getting non-existent directory should fail"); + } + + @Test + void test_getByNameNonExistent_fails(TestNamespace ns) { + String nonExistentFqn = "nonExistentService.nonExistentDirectory"; + + assertThrows( + Exception.class, + () -> Directories.getByName(nonExistentFqn), + "Getting directory by non-existent FQN should fail"); + } } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java index cc4621464d69..dca18a471fc9 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java @@ -386,4 +386,114 @@ void test_fileWithAllOptionalFields(TestNamespace ns) { assertEquals( driveService.getFullyQualifiedName(), createdFile.getService().getFullyQualifiedName()); } + + @Test + void test_createFileMinimal(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_minimal"); + + File createdFile = + Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + + assertEquals(fileName, createdFile.getName()); + assertNotNull(createdFile.getId()); + assertNotNull(createdFile.getService()); + } + + @Test + void test_createFileWithDescription(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_desc"); + String description = "This is a detailed description of the test file"; + + File createdFile = + Files.create() + .name(fileName) + .withDescription(description) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertEquals(fileName, createdFile.getName()); + assertEquals(description, createdFile.getDescription()); + } + + @Test + void test_deleteFile(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_delete"); + File createdFile = + Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + String fileId = createdFile.getId().toString(); + + assertNotNull(Files.get(fileId)); + Files.delete(fileId); + + assertThrows( + Exception.class, () -> Files.get(fileId), "Getting deleted file should throw exception"); + } + + @Test + void test_findFileById(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_find"); + File createdFile = + Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + + File foundFile = Files.find(createdFile.getId().toString()).fetch(); + assertEquals(createdFile.getId(), foundFile.getId()); + assertEquals(fileName, foundFile.getName()); + } + + @Test + void test_findFileByNameWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_find_by_name"); + File createdFile = + Files.create() + .name(fileName) + .withService(driveService.getFullyQualifiedName()) + .withDescription("Find by name with fields") + .execute(); + + File foundFile = + Files.findByName(createdFile.getFullyQualifiedName()) + .withFields("owners", "tags", "domains") + .fetch(); + assertEquals(createdFile.getId(), foundFile.getId()); + } + + @Test + void test_getFileByNameWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_with_fields"); + File createdFile = + Files.create() + .name(fileName) + .withService(driveService.getFullyQualifiedName()) + .withDescription("File with specific fields") + .execute(); + + File retrievedFile = Files.getByName(createdFile.getFullyQualifiedName(), "owners,tags"); + assertEquals(createdFile.getId(), retrievedFile.getId()); + } + + @Test + void test_getFileWithNonExistentId_shouldFail(TestNamespace ns) { + String nonExistentId = "00000000-0000-0000-0000-000000000000"; + + assertThrows( + Exception.class, + () -> Files.get(nonExistentId), + "Getting file with non-existent ID should fail"); + } + + @Test + void test_getFileByNameWithNonExistentFQN_shouldFail(TestNamespace ns) { + String nonExistentFQN = "nonexistent.service.nonexistent.file"; + + assertThrows( + Exception.class, + () -> Files.getByName(nonExistentFQN), + "Getting file with non-existent FQN should fail"); + } } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java index 1c0a512c49d6..899a5cc8a472 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java @@ -706,4 +706,162 @@ void test_listSpreadsheetsWithRootParameterAcrossMultipleServices(TestNamespace SdkClients.adminClient().spreadsheets().list(params); assertTrue(allExcelSpreadsheets.getData().size() >= 5); } + + @Test + void test_createSpreadsheet(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Spreadsheet spreadsheet = + Spreadsheets.create() + .name(ns.prefix("spreadsheet")) + .withDescription("Test spreadsheet") + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertEquals(ns.prefix("spreadsheet"), spreadsheet.getName()); + assertEquals("Test spreadsheet", spreadsheet.getDescription()); + assertEquals( + driveService.getFullyQualifiedName(), spreadsheet.getService().getFullyQualifiedName()); + } + + @Test + void test_createSpreadsheetMinimal(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + Spreadsheet spreadsheet = + Spreadsheets.create() + .name(ns.prefix("minimal_spreadsheet")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertNotNull(spreadsheet.getId()); + assertEquals(ns.prefix("minimal_spreadsheet"), spreadsheet.getName()); + } + + @Test + void test_getSpreadsheetById(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_get")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = Spreadsheets.get(created.getId().toString()); + assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getName(), fetched.getName()); + assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + } + + @Test + void test_getSpreadsheetByName(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_getByName")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = Spreadsheets.getByName(created.getFullyQualifiedName()); + assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + } + + @Test + void test_deleteSpreadsheet(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_delete")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheets.delete(created.getId().toString()); + + assertThrows( + Exception.class, + () -> Spreadsheets.get(created.getId().toString()), + "Getting deleted spreadsheet should fail"); + } + + @Test + void test_finderWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_fields")) + .withDescription("Test spreadsheet for fields") + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = + Spreadsheets.find(created.getId().toString()).withFields("service", "owners").fetch(); + assertEquals(created.getId(), fetched.getId()); + assertNotNull(fetched.getService()); + } + + @Test + void test_finderByNameWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_name_fields")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = + Spreadsheets.findByName(created.getFullyQualifiedName()) + .withFields("service", "tags") + .fetch(); + assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + } + + @Test + void test_getByNameWithFields(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_byname_fields")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = Spreadsheets.getByName(created.getFullyQualifiedName(), "service,owners"); + assertEquals(created.getId(), fetched.getId()); + assertNotNull(fetched.getService()); + } + + @Test + void test_createMultipleSpreadsheetsUnderSameService(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + + for (int i = 0; i < 3; i++) { + Spreadsheet spreadsheet = + Spreadsheets.create() + .name(ns.prefix("spreadsheet_" + i)) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertNotNull(spreadsheet.getId()); + assertTrue( + spreadsheet.getFullyQualifiedName().contains(ns.prefix("spreadsheet_" + i)), + "FQN should contain spreadsheet name"); + } + } + + @Test + void test_patchSpreadsheetAttributes(TestNamespace ns) { + DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet spreadsheet = + Spreadsheets.create() + .name(ns.prefix("patchSpreadsheet")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + Spreadsheet fetched = Spreadsheets.get(spreadsheet.getId().toString()); + fetched.setDescription("patched description"); + Spreadsheet patched = + Spreadsheets.update(spreadsheet.getId().toString()).entity(fetched).execute(); + assertEquals("patched description", patched.getDescription()); + } } From 2aca49b49fd240abb541face9d5f4ff2987bfbb5 Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Tue, 12 May 2026 18:27:17 +0530 Subject: [PATCH 9/9] test(it): restore exact original test bodies (assertNotNull lines included) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior commits restored test methods by name but trimmed bodies — e.g., dropped `assertNotNull(created)`, `assertNotNull(driveService)`, and other redundant-but-original assertions. Reviewer asked for the tests "as is", so this commit replays each restored method body byte-for-byte from ab535900da (the introducing commit, PR #24948). Preserved on top of the verbatim bodies: - FileResourceIT: getFullyQualifiedName() comparison instead of getName() in test_createAndGetFile / test_fileWithAllOptionalFields (gitar-bot review fix). - SpreadsheetResourceIT: @Disabled (short form) instead of @org.junit.jupiter.api.Disabled (gitar-bot review fix). The skip state and reasons on test_spreadsheetWithWorksheets and test_listSpreadsheetsWithRootParameterAcrossMultipleServices match the original — they were disabled in PR #24948 due to backend gaps, not by this PR. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../it/tests/DirectoryResourceIT.java | 56 +++++++++ .../openmetadata/it/tests/FileResourceIT.java | 40 +++++- .../it/tests/SpreadsheetResourceIT.java | 119 +++++++++++++++--- 3 files changed, 196 insertions(+), 19 deletions(-) diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java index 1cd45dc1e06a..be5784b10bb8 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/DirectoryResourceIT.java @@ -167,6 +167,7 @@ private DirectoryService getDirectoryService() { @Test void test_createAndGetDirectory(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); String directoryName = ns.prefix("test_directory"); Directory created = @@ -177,14 +178,20 @@ void test_createAndGetDirectory(TestNamespace ns) { .withDescription("A test directory created by integration test") .execute(); + assertNotNull(created); assertNotNull(created.getId()); assertEquals(directoryName, created.getName()); assertEquals("Test Directory", created.getDisplayName()); + assertEquals("A test directory created by integration test", created.getDescription()); + assertNotNull(created.getService()); assertEquals( driveService.getFullyQualifiedName(), created.getService().getFullyQualifiedName()); Directory fetched = Directories.get(created.getId().toString()); + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getName(), fetched.getName()); + assertEquals(created.getDisplayName(), fetched.getDisplayName()); } @Test @@ -211,6 +218,7 @@ void test_createDirectoryWithInvalidService_fails(TestNamespace ns) { @Test void test_directoryFullyQualifiedName(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); String directoryName = ns.prefix("test_directory_fqn"); Directory created = @@ -219,6 +227,8 @@ void test_directoryFullyQualifiedName(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(created); + assertNotNull(created.getFullyQualifiedName()); assertTrue(created.getFullyQualifiedName().contains(driveService.getName())); assertTrue(created.getFullyQualifiedName().contains(directoryName)); } @@ -226,6 +236,7 @@ void test_directoryFullyQualifiedName(TestNamespace ns) { @Test void test_createDirectoryWithAllFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); String directoryName = ns.prefix("test_directory_full"); Directory created = @@ -236,10 +247,13 @@ void test_createDirectoryWithAllFields(TestNamespace ns) { .withDescription("A directory with all fields populated for testing") .execute(); + assertNotNull(created); + assertNotNull(created.getId()); assertEquals(directoryName, created.getName()); assertEquals("Complete Test Directory", created.getDisplayName()); assertEquals("A directory with all fields populated for testing", created.getDescription()); assertNotNull(created.getService()); + assertNotNull(created.getFullyQualifiedName()); assertTrue( created.getFullyQualifiedName().contains(directoryName), "FQN should contain directory name"); @@ -248,6 +262,8 @@ void test_createDirectoryWithAllFields(TestNamespace ns) { @Test void test_createDirectoryMinimalRequest(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_minimal"); Directory created = Directories.create() @@ -255,6 +271,7 @@ void test_createDirectoryMinimalRequest(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(created); assertNotNull(created.getId()); assertEquals(directoryName, created.getName()); assertNotNull(created.getService()); @@ -263,6 +280,8 @@ void test_createDirectoryMinimalRequest(TestNamespace ns) { @Test void test_getByName(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_by_name"); Directory created = Directories.create() @@ -271,7 +290,11 @@ void test_getByName(TestNamespace ns) { .withDisplayName("Test Directory By Name") .execute(); + assertNotNull(created); + assertNotNull(created.getFullyQualifiedName()); + Directory fetched = Directories.getByName(created.getFullyQualifiedName()); + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertEquals(created.getName(), fetched.getName()); assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); @@ -280,6 +303,8 @@ void test_getByName(TestNamespace ns) { @Test void test_getByNameWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_with_fields"); Directory created = Directories.create() @@ -288,7 +313,11 @@ void test_getByNameWithFields(TestNamespace ns) { .withDisplayName("Test Directory With Fields") .execute(); + assertNotNull(created); + assertNotNull(created.getFullyQualifiedName()); + Directory fetched = Directories.getByName(created.getFullyQualifiedName(), "service,owners"); + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertNotNull(fetched.getService()); } @@ -296,12 +325,17 @@ void test_getByNameWithFields(TestNamespace ns) { @Test void test_deleteDirectory(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_delete"); Directory created = Directories.create() .name(directoryName) .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory To Delete") .execute(); + + assertNotNull(created); String directoryId = created.getId().toString(); Directories.delete(directoryId); @@ -315,14 +349,20 @@ void test_deleteDirectory(TestNamespace ns) { @Test void test_findDirectoryById(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_find"); Directory created = Directories.create() .name(directoryName) .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory Find") .execute(); + assertNotNull(created); + Directory fetched = Directories.find(created.getId().toString()).fetch(); + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertEquals(created.getName(), fetched.getName()); } @@ -330,14 +370,21 @@ void test_findDirectoryById(TestNamespace ns) { @Test void test_findDirectoryByName(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_find_by_name"); Directory created = Directories.create() .name(directoryName) .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory Find By Name") .execute(); + assertNotNull(created); + assertNotNull(created.getFullyQualifiedName()); + Directory fetched = Directories.findByName(created.getFullyQualifiedName()).fetch(); + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertEquals(created.getName(), fetched.getName()); } @@ -345,17 +392,23 @@ void test_findDirectoryByName(TestNamespace ns) { @Test void test_findDirectoryWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); + String directoryName = ns.prefix("test_directory_find_fields"); Directory created = Directories.create() .name(directoryName) .withService(driveService.getFullyQualifiedName()) + .withDisplayName("Test Directory Find Fields") .execute(); + assertNotNull(created); + Directory fetched = Directories.findByName(created.getFullyQualifiedName()) .withFields("service", "owners", "tags") .fetch(); + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertNotNull(fetched.getService()); } @@ -363,6 +416,7 @@ void test_findDirectoryWithFields(TestNamespace ns) { @Test void test_createMultipleDirectories(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + assertNotNull(driveService); for (int i = 1; i <= 3; i++) { String directoryName = ns.prefix("test_directory_multi_" + i); @@ -374,6 +428,8 @@ void test_createMultipleDirectories(TestNamespace ns) { .withDescription("Directory number " + i) .execute(); + assertNotNull(created); + assertNotNull(created.getId()); assertEquals(directoryName, created.getName()); assertEquals("Test Directory " + i, created.getDisplayName()); diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java index dca18a471fc9..6784dc9a3a6c 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/FileResourceIT.java @@ -248,9 +248,23 @@ void test_multipleFilesInSameService(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + File file3 = + Files.create() + .name(ns.prefix("file_3")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertNotNull(file1); + assertNotNull(file2); + assertNotNull(file3); + assertNotEquals(file1.getId(), file2.getId()); + assertNotEquals(file2.getId(), file3.getId()); + assertNotEquals(file1.getId(), file3.getId()); + assertEquals(driveService.getFullyQualifiedName(), file1.getService().getFullyQualifiedName()); assertEquals(driveService.getFullyQualifiedName(), file2.getService().getFullyQualifiedName()); + assertEquals(driveService.getFullyQualifiedName(), file3.getService().getFullyQualifiedName()); } @Test @@ -360,6 +374,7 @@ void test_createFileWithDisplayName(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(createdFile); assertEquals(fileName, createdFile.getName()); assertEquals(displayName, createdFile.getDisplayName()); } @@ -380,9 +395,11 @@ void test_fileWithAllOptionalFields(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(createdFile); assertEquals(fileName, createdFile.getName()); assertEquals(displayName, createdFile.getDisplayName()); assertEquals(description, createdFile.getDescription()); + assertNotNull(createdFile.getService()); assertEquals( driveService.getFullyQualifiedName(), createdFile.getService().getFullyQualifiedName()); } @@ -390,11 +407,13 @@ void test_fileWithAllOptionalFields(TestNamespace ns) { @Test void test_createFileMinimal(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_minimal"); File createdFile = Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + assertNotNull(createdFile); assertEquals(fileName, createdFile.getName()); assertNotNull(createdFile.getId()); assertNotNull(createdFile.getService()); @@ -403,6 +422,7 @@ void test_createFileMinimal(TestNamespace ns) { @Test void test_createFileWithDescription(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_desc"); String description = "This is a detailed description of the test file"; @@ -413,6 +433,7 @@ void test_createFileWithDescription(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(createdFile); assertEquals(fileName, createdFile.getName()); assertEquals(description, createdFile.getDescription()); } @@ -420,12 +441,17 @@ void test_createFileWithDescription(TestNamespace ns) { @Test void test_deleteFile(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_delete"); File createdFile = Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + + assertNotNull(createdFile); String fileId = createdFile.getId().toString(); - assertNotNull(Files.get(fileId)); + File beforeDelete = Files.get(fileId); + assertNotNull(beforeDelete); + Files.delete(fileId); assertThrows( @@ -435,11 +461,15 @@ void test_deleteFile(TestNamespace ns) { @Test void test_findFileById(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_find"); File createdFile = Files.create().name(fileName).withService(driveService.getFullyQualifiedName()).execute(); + assertNotNull(createdFile); + File foundFile = Files.find(createdFile.getId().toString()).fetch(); + assertNotNull(foundFile); assertEquals(createdFile.getId(), foundFile.getId()); assertEquals(fileName, foundFile.getName()); } @@ -447,6 +477,7 @@ void test_findFileById(TestNamespace ns) { @Test void test_findFileByNameWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_find_by_name"); File createdFile = Files.create() @@ -455,16 +486,20 @@ void test_findFileByNameWithFields(TestNamespace ns) { .withDescription("Find by name with fields") .execute(); + assertNotNull(createdFile); + File foundFile = Files.findByName(createdFile.getFullyQualifiedName()) .withFields("owners", "tags", "domains") .fetch(); + assertNotNull(foundFile); assertEquals(createdFile.getId(), foundFile.getId()); } @Test void test_getFileByNameWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + String fileName = ns.prefix("test_file_with_fields"); File createdFile = Files.create() @@ -473,7 +508,10 @@ void test_getFileByNameWithFields(TestNamespace ns) { .withDescription("File with specific fields") .execute(); + assertNotNull(createdFile); + File retrievedFile = Files.getByName(createdFile.getFullyQualifiedName(), "owners,tags"); + assertNotNull(retrievedFile); assertEquals(createdFile.getId(), retrievedFile.getId()); } diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java index 899a5cc8a472..46d1224bb1c8 100644 --- a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/SpreadsheetResourceIT.java @@ -1,7 +1,6 @@ package org.openmetadata.it.tests; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -205,6 +204,12 @@ void test_spreadsheetFQNStructure(TestNamespace ns) { String expectedFqn = driveService.getFullyQualifiedName() + "." + ns.prefix("fqn_test"); assertEquals(expectedFqn, spreadsheet.getFullyQualifiedName()); + assertTrue( + spreadsheet.getFullyQualifiedName().startsWith(driveService.getFullyQualifiedName()), + "Spreadsheet FQN should start with service FQN"); + assertTrue( + spreadsheet.getFullyQualifiedName().endsWith(spreadsheet.getName()), + "Spreadsheet FQN should end with spreadsheet name"); } @Test @@ -212,10 +217,13 @@ void test_createSpreadsheetNameUniqueness(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); String uniqueName = ns.prefix("unique_spreadsheet"); - Spreadsheets.create() - .name(uniqueName) - .withService(driveService.getFullyQualifiedName()) - .execute(); + Spreadsheet first = + Spreadsheets.create() + .name(uniqueName) + .withService(driveService.getFullyQualifiedName()) + .execute(); + + assertNotNull(first); assertThrows( Exception.class, @@ -224,7 +232,7 @@ void test_createSpreadsheetNameUniqueness(TestNamespace ns) { .name(uniqueName) .withService(driveService.getFullyQualifiedName()) .execute(), - "Creating duplicate spreadsheet under same service should fail"); + "Creating duplicate spreadsheet with same name under same service should fail"); } @Test @@ -263,6 +271,8 @@ void test_spreadsheetInDirectory(TestNamespace ns) { assertNotNull(spreadsheet.getDirectory()); assertEquals(directory.getId(), spreadsheet.getDirectory().getId()); + assertEquals( + directory.getFullyQualifiedName(), spreadsheet.getDirectory().getFullyQualifiedName()); } @Test @@ -276,12 +286,24 @@ void test_listSpreadsheetsByDirectory(TestNamespace ns) { .withPath("/reports") .execute(); + Directory dir2 = + Directories.create() + .name(ns.prefix("analytics")) + .withService(driveService.getFullyQualifiedName()) + .withPath("/analytics") + .execute(); + for (int i = 0; i < 2; i++) { Spreadsheets.create() .name(ns.prefix("report_" + i)) .withService(driveService.getFullyQualifiedName()) .withParent(dir1.getEntityReference()) .execute(); + Spreadsheets.create() + .name(ns.prefix("analytics_" + i)) + .withService(driveService.getFullyQualifiedName()) + .withParent(dir2.getEntityReference()) + .execute(); } ListParams params = new ListParams().withDirectory(dir1.getFullyQualifiedName()); @@ -291,6 +313,14 @@ void test_listSpreadsheetsByDirectory(TestNamespace ns) { list.getData().stream() .allMatch( s -> s.getDirectory() != null && s.getDirectory().getId().equals(dir1.getId()))); + + params = new ListParams().withDirectory(dir2.getFullyQualifiedName()); + list = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(list.getData().size() >= 2); + assertTrue( + list.getData().stream() + .allMatch( + s -> s.getDirectory() != null && s.getDirectory().getId().equals(dir2.getId()))); } @Test @@ -309,28 +339,44 @@ void test_listSpreadsheetsWithRootParameter(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + Spreadsheets.create() + .name(ns.prefix("rootSpreadsheet2")) + .withService(driveService.getFullyQualifiedName()) + .execute(); + Spreadsheets.create() .name(ns.prefix("childSpreadsheet1")) .withService(driveService.getFullyQualifiedName()) .withParent(sheetsDir.getEntityReference()) .execute(); - ListParams params = - new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); + Spreadsheets.create() + .name(ns.prefix("childSpreadsheet2")) + .withService(driveService.getFullyQualifiedName()) + .withParent(sheetsDir.getEntityReference()) + .execute(); + + ListParams params = new ListParams().withService(driveService.getFullyQualifiedName()); + ListResponse allSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertTrue(allSpreadsheets.getData().size() >= 4); + + params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("true"); ListResponse rootSpreadsheets = SdkClients.adminClient().spreadsheets().list(params); + assertTrue(rootSpreadsheets.getData().size() >= 2); - assertTrue( - rootSpreadsheets.getData().stream() - .anyMatch(s -> s.getName().equals(ns.prefix("rootSpreadsheet1"))), - "Root spreadsheet we just created must appear in ?root=true results"); - assertFalse( - rootSpreadsheets.getData().stream() - .anyMatch(s -> s.getName().equals(ns.prefix("childSpreadsheet1"))), - "Child spreadsheet must NOT appear in ?root=true results"); for (Spreadsheet spreadsheet : rootSpreadsheets.getData()) { - assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); + assertNull(spreadsheet.getDirectory()); + assertTrue( + spreadsheet.getName().equals(ns.prefix("rootSpreadsheet1")) + || spreadsheet.getName().equals(ns.prefix("rootSpreadsheet2"))); } + + params = new ListParams().withService(driveService.getFullyQualifiedName()).withRoot("false"); + ListResponse nonRootSpreadsheets = + SdkClients.adminClient().spreadsheets().list(params); + assertTrue(nonRootSpreadsheets.getData().size() >= 4); } @Test @@ -345,6 +391,7 @@ void test_createSpreadsheetWithOptionalFields(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(spreadsheet); assertEquals("Display Name for Spreadsheet", spreadsheet.getDisplayName()); assertEquals("Spreadsheet with optional fields", spreadsheet.getDescription()); } @@ -362,16 +409,19 @@ void test_updateSpreadsheet(TestNamespace ns) { Spreadsheet fetched = Spreadsheets.get(created.getId().toString()); fetched.setDescription("updated description"); + Spreadsheet updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); assertEquals("updated description", updated.getDescription()); fetched = Spreadsheets.get(created.getId().toString()); fetched.setPath("/new/path/to/spreadsheet"); + updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); assertEquals("/new/path/to/spreadsheet", updated.getPath()); fetched = Spreadsheets.get(created.getId().toString()); fetched.setSize(1024000); + updated = Spreadsheets.update(created.getId().toString()).entity(fetched).execute(); assertEquals(Integer.valueOf(1024000), updated.getSize()); } @@ -398,6 +448,7 @@ void test_spreadsheetWithWorksheets(TestNamespace ns) { Spreadsheet spreadsheetWithWorksheets = Spreadsheets.find(spreadsheet.getId().toString()).withFields("worksheets").fetch(); assertNotNull(spreadsheetWithWorksheets.getWorksheets()); + // Filter worksheets that belong to this test by namespace prefix long testWorksheetCount = spreadsheetWithWorksheets.getWorksheets().stream() .filter(ws -> ws.getName().startsWith(ns.prefix("sheet"))) @@ -671,11 +722,13 @@ void test_listSpreadsheetsWithRootParameterAcrossMultipleServices(TestNamespace new ListParams().withService(service1.getFullyQualifiedName()).withRoot("true"); ListResponse googleRootSpreadsheets = SdkClients.adminClient().spreadsheets().list(params); + // Filter to only our test's spreadsheets long googleSheetCount = googleRootSpreadsheets.getData().stream() .filter(s -> s.getName().startsWith(ns.prefix("googleSheet"))) .count(); assertTrue(googleSheetCount >= 2, "Should have at least 2 root googleSheet spreadsheets"); + // Verify root spreadsheets have no directory for (Spreadsheet spreadsheet : googleRootSpreadsheets.getData()) { if (spreadsheet.getName().startsWith(ns.prefix("googleSheet"))) { assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); @@ -685,11 +738,13 @@ void test_listSpreadsheetsWithRootParameterAcrossMultipleServices(TestNamespace params = new ListParams().withService(service2.getFullyQualifiedName()).withRoot("true"); ListResponse excelRootSpreadsheets = SdkClients.adminClient().spreadsheets().list(params); + // Filter to only our test's spreadsheets long excelWorkbookCount = excelRootSpreadsheets.getData().stream() .filter(s -> s.getName().startsWith(ns.prefix("excelWorkbook"))) .count(); assertTrue(excelWorkbookCount >= 4, "Should have at least 4 root excelWorkbook spreadsheets"); + // Verify root spreadsheets have no directory for (Spreadsheet spreadsheet : excelRootSpreadsheets.getData()) { if (spreadsheet.getName().startsWith(ns.prefix("excelWorkbook"))) { assertNull(spreadsheet.getDirectory(), "Root spreadsheet should not have directory"); @@ -718,8 +773,11 @@ void test_createSpreadsheet(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(spreadsheet); + assertNotNull(spreadsheet.getId()); assertEquals(ns.prefix("spreadsheet"), spreadsheet.getName()); assertEquals("Test spreadsheet", spreadsheet.getDescription()); + assertNotNull(spreadsheet.getService()); assertEquals( driveService.getFullyQualifiedName(), spreadsheet.getService().getFullyQualifiedName()); } @@ -734,6 +792,7 @@ void test_createSpreadsheetMinimal(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(spreadsheet); assertNotNull(spreadsheet.getId()); assertEquals(ns.prefix("minimal_spreadsheet"), spreadsheet.getName()); } @@ -741,6 +800,7 @@ void test_createSpreadsheetMinimal(TestNamespace ns) { @Test void test_getSpreadsheetById(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = Spreadsheets.create() .name(ns.prefix("spreadsheet_get")) @@ -748,14 +808,20 @@ void test_getSpreadsheetById(TestNamespace ns) { .execute(); Spreadsheet fetched = Spreadsheets.get(created.getId().toString()); + + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertEquals(created.getName(), fetched.getName()); - assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); + assertEquals( + created.getFullyQualifiedName(), + fetched.getFullyQualifiedName(), + "FQN should match between created and fetched"); } @Test void test_getSpreadsheetByName(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = Spreadsheets.create() .name(ns.prefix("spreadsheet_getByName")) @@ -763,19 +829,25 @@ void test_getSpreadsheetByName(TestNamespace ns) { .execute(); Spreadsheet fetched = Spreadsheets.getByName(created.getFullyQualifiedName()); + + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); + assertEquals(created.getName(), fetched.getName()); assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); } @Test void test_deleteSpreadsheet(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = Spreadsheets.create() .name(ns.prefix("spreadsheet_delete")) .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(created.getId()); + Spreadsheets.delete(created.getId().toString()); assertThrows( @@ -787,6 +859,7 @@ void test_deleteSpreadsheet(TestNamespace ns) { @Test void test_finderWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = Spreadsheets.create() .name(ns.prefix("spreadsheet_fields")) @@ -796,6 +869,8 @@ void test_finderWithFields(TestNamespace ns) { Spreadsheet fetched = Spreadsheets.find(created.getId().toString()).withFields("service", "owners").fetch(); + + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertNotNull(fetched.getService()); } @@ -803,6 +878,7 @@ void test_finderWithFields(TestNamespace ns) { @Test void test_finderByNameWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = Spreadsheets.create() .name(ns.prefix("spreadsheet_name_fields")) @@ -813,6 +889,8 @@ void test_finderByNameWithFields(TestNamespace ns) { Spreadsheets.findByName(created.getFullyQualifiedName()) .withFields("service", "tags") .fetch(); + + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertEquals(created.getFullyQualifiedName(), fetched.getFullyQualifiedName()); } @@ -820,6 +898,7 @@ void test_finderByNameWithFields(TestNamespace ns) { @Test void test_getByNameWithFields(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet created = Spreadsheets.create() .name(ns.prefix("spreadsheet_byname_fields")) @@ -827,6 +906,8 @@ void test_getByNameWithFields(TestNamespace ns) { .execute(); Spreadsheet fetched = Spreadsheets.getByName(created.getFullyQualifiedName(), "service,owners"); + + assertNotNull(fetched); assertEquals(created.getId(), fetched.getId()); assertNotNull(fetched.getService()); } @@ -842,6 +923,7 @@ void test_createMultipleSpreadsheetsUnderSameService(TestNamespace ns) { .withService(driveService.getFullyQualifiedName()) .execute(); + assertNotNull(spreadsheet); assertNotNull(spreadsheet.getId()); assertTrue( spreadsheet.getFullyQualifiedName().contains(ns.prefix("spreadsheet_" + i)), @@ -852,6 +934,7 @@ void test_createMultipleSpreadsheetsUnderSameService(TestNamespace ns) { @Test void test_patchSpreadsheetAttributes(TestNamespace ns) { DriveService driveService = DriveServiceTestFactory.createGoogleDrive(ns); + Spreadsheet spreadsheet = Spreadsheets.create() .name(ns.prefix("patchSpreadsheet"))