From a0e2849ceba0b99fe75d66b8b8c16a2d85abe883 Mon Sep 17 00:00:00 2001 From: Volodymyr_Rohach Date: Thu, 21 Nov 2024 16:33:00 +0100 Subject: [PATCH] MODSOURCE-824: Tests added+news updated. --- NEWS.md | 3 + .../rest/impl/SourceStorageBatchApiTest.java | 216 +++++++++++++++++- .../org/folio/services/RecordServiceTest.java | 137 +++++++++++ 3 files changed, 354 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 1cc6e4df4..ae003541a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +## 202x-xx-xx 5.10.0-SNAPSHOT +* [MODSOURCE-824](https://folio-org.atlassian.net/browse/MODSOURCE-824) Endpoint /batch/parsed-records/fetch does not return deleted records + ## 2024-10-28 5.9.0 * [MODSOURCE-767](https://folio-org.atlassian.net/browse/MODSOURCE-767) Single record overlay creates duplicate OCLC#/035 * [MODSOURCE-756](https://issues.folio.org/browse/MODSOURCE-756) After setting an instance as marked for deletion it is no longer editable in quickmarc diff --git a/mod-source-record-storage-server/src/test/java/org/folio/rest/impl/SourceStorageBatchApiTest.java b/mod-source-record-storage-server/src/test/java/org/folio/rest/impl/SourceStorageBatchApiTest.java index 9f3c32dee..b2a243294 100644 --- a/mod-source-record-storage-server/src/test/java/org/folio/rest/impl/SourceStorageBatchApiTest.java +++ b/mod-source-record-storage-server/src/test/java/org/folio/rest/impl/SourceStorageBatchApiTest.java @@ -227,8 +227,46 @@ public void shouldPostSourceStorageBatchEdifactRecords(TestContext testContext) } @Test - public void shouldPostFetchParsedRecordsBatch(TestContext testContext) { + public void shouldPostFetchParsedRecordsBatchWithDeletedWhenIncludeDeleteTrue(TestContext testContext) { Async async = testContext.async(); + + Record record_1 = new Record() + .withId(FIRST_UUID) + .withSnapshotId(snapshot_1.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecordWithHrId) + .withMatchedId(FIRST_UUID) + .withOrder(0) + .withState(Record.State.ACTUAL) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(HRID)); + Record record_2 = new Record() + .withId(SECOND_UUID) + .withSnapshotId(snapshot_2.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecord) + .withMatchedId(SECOND_UUID) + .withOrder(11) + .withState(Record.State.DELETED) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(MARC_RECORD_HRID)); + Record record_3 = new Record() + .withId(THIRD_UUID) + .withSnapshotId(snapshot_2.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecordWithHrId) + .withErrorRecord(errorRecord) + .withMatchedId(THIRD_UUID) + .withState(Record.State.ACTUAL) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(HRID)); + var externalIds = List.of( record_1.getExternalIdsHolder().getInstanceId(), record_2.getExternalIdsHolder().getInstanceId(), @@ -243,7 +281,8 @@ public void shouldPostFetchParsedRecordsBatch(TestContext testContext) { FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) .withConditions(conditions) - .withData(emptyList()); + .withData(emptyList()) + .withIncludeDeleted(true); RestAssured.given() .spec(spec) @@ -257,6 +296,147 @@ public void shouldPostFetchParsedRecordsBatch(TestContext testContext) { async.complete(); } + + @Test + public void shouldPostFetchParsedRecordsBatchWithActualWhenIncludeDeleteFalse(TestContext testContext) { + Async async = testContext.async(); + + Record record_1 = new Record() + .withId(FIRST_UUID) + .withSnapshotId(snapshot_1.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecordWithHrId) + .withMatchedId(FIRST_UUID) + .withOrder(0) + .withState(Record.State.ACTUAL) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(HRID)); + Record record_2 = new Record() + .withId(SECOND_UUID) + .withSnapshotId(snapshot_2.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecord) + .withMatchedId(SECOND_UUID) + .withOrder(11) + .withState(Record.State.DELETED) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(MARC_RECORD_HRID)); + Record record_3 = new Record() + .withId(THIRD_UUID) + .withSnapshotId(snapshot_2.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecordWithHrId) + .withErrorRecord(errorRecord) + .withMatchedId(THIRD_UUID) + .withState(Record.State.ACTUAL) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(HRID)); + + var externalIds = List.of( + record_1.getExternalIdsHolder().getInstanceId(), + record_2.getExternalIdsHolder().getInstanceId(), + record_3.getExternalIdsHolder().getInstanceId() + ); + postSnapshots(testContext, snapshot_1, snapshot_2, snapshot_3); + postRecords(testContext, record_1, record_2, record_3); + + Conditions conditions = new Conditions() + .withIdType(IdType.INSTANCE.name()) + .withIds(externalIds); + FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() + .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) + .withConditions(conditions) + .withData(emptyList()) + .withIncludeDeleted(false); + + RestAssured.given() + .spec(spec) + .body(batchRequest) + .when() + .post(SOURCE_STORAGE_BATCH_FETCH_PARSED_RECORDS_PATH) + .then() + .statusCode(HttpStatus.SC_OK) + .body("records.size()", is(externalIds.size()-1)) + .body("totalRecords", is(externalIds.size()-1)); + async.complete(); + } + + @Test + public void shouldPostFetchParsedRecordsBatchWithActualWhenIncludeDeleteNotExists(TestContext testContext) { + Async async = testContext.async(); + + Record record_1 = new Record() + .withId(FIRST_UUID) + .withSnapshotId(snapshot_1.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecordWithHrId) + .withMatchedId(FIRST_UUID) + .withOrder(0) + .withState(Record.State.ACTUAL) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(HRID)); + Record record_2 = new Record() + .withId(SECOND_UUID) + .withSnapshotId(snapshot_2.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecord) + .withMatchedId(SECOND_UUID) + .withOrder(11) + .withState(Record.State.DELETED) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(MARC_RECORD_HRID)); + Record record_3 = new Record() + .withId(THIRD_UUID) + .withSnapshotId(snapshot_2.getJobExecutionId()) + .withRecordType(Record.RecordType.MARC_BIB) + .withRawRecord(rawRecord) + .withParsedRecord(marcRecordWithHrId) + .withErrorRecord(errorRecord) + .withMatchedId(THIRD_UUID) + .withState(Record.State.ACTUAL) + .withExternalIdsHolder(new ExternalIdsHolder() + .withInstanceId(UUID.randomUUID().toString()) + .withInstanceHrid(HRID)); + + var externalIds = List.of( + record_1.getExternalIdsHolder().getInstanceId(), + record_2.getExternalIdsHolder().getInstanceId(), + record_3.getExternalIdsHolder().getInstanceId() + ); + postSnapshots(testContext, snapshot_1, snapshot_2, snapshot_3); + postRecords(testContext, record_1, record_2, record_3); + + Conditions conditions = new Conditions() + .withIdType(IdType.INSTANCE.name()) + .withIds(externalIds); + FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() + .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) + .withConditions(conditions) + .withData(emptyList()); + + RestAssured.given() + .spec(spec) + .body(batchRequest) + .when() + .post(SOURCE_STORAGE_BATCH_FETCH_PARSED_RECORDS_PATH) + .then() + .statusCode(HttpStatus.SC_OK) + .body("records.size()", is(externalIds.size()-1)) + .body("totalRecords", is(externalIds.size()-1)); + async.complete(); + } + + @Test public void shouldPostFetchEmptyParsedRecordsBatch(TestContext testContext) { Async async = testContext.async(); @@ -282,6 +462,38 @@ public void shouldPostFetchEmptyParsedRecordsBatch(TestContext testContext) { async.complete(); } + @Test + public void shouldPostFetchParsedRecordsBatch(TestContext testContext) { + Async async = testContext.async(); + var externalIds = List.of( + record_1.getExternalIdsHolder().getInstanceId(), + record_2.getExternalIdsHolder().getInstanceId(), + record_3.getExternalIdsHolder().getInstanceId() + ); + postSnapshots(testContext, snapshot_1, snapshot_2, snapshot_3); + postRecords(testContext, record_1, record_2, record_3); + + Conditions conditions = new Conditions() + .withIdType(IdType.INSTANCE.name()) + .withIds(externalIds); + FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() + .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) + .withConditions(conditions) + .withData(emptyList()) + .withIncludeDeleted(true); + + RestAssured.given() + .spec(spec) + .body(batchRequest) + .when() + .post(SOURCE_STORAGE_BATCH_FETCH_PARSED_RECORDS_PATH) + .then() + .statusCode(HttpStatus.SC_OK) + .body("records.size()", is(externalIds.size())) + .body("totalRecords", is(externalIds.size())); + async.complete(); + } + @Test public void shouldFailWhenPostSourceStorageBatchRecordsWithMultipleSnapshots(TestContext testContext) { Async async = testContext.async(); diff --git a/mod-source-record-storage-server/src/test/java/org/folio/services/RecordServiceTest.java b/mod-source-record-storage-server/src/test/java/org/folio/services/RecordServiceTest.java index 7745a4de5..e13c4c3eb 100644 --- a/mod-source-record-storage-server/src/test/java/org/folio/services/RecordServiceTest.java +++ b/mod-source-record-storage-server/src/test/java/org/folio/services/RecordServiceTest.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import javax.ws.rs.BadRequestException; @@ -240,6 +241,142 @@ public void shouldFetchBibRecordsWithOneFieldByExternalId(TestContext context) { }); } + @Test + public void shouldFetchActualAndDeletedBibRecordsWithOneFieldByExternalIdWhenIncludeDeletedExists(TestContext context) { + Async async = context.async(); + List records = TestMocks.getRecords(); + records.get(3).setDeleted(true); + records.get(3).setState(State.DELETED); + records.get(5).setDeleted(true); + records.get(5).setState(State.DELETED); + RecordCollection recordCollection = new RecordCollection() + .withRecords(records) + .withTotalRecords(records.size()); + saveRecords(recordCollection.getRecords()).onComplete(batch -> { + if (batch.failed()) { + context.fail(batch.cause()); + } + + Set externalIds = Set.of("3c4ae3f3-b460-4a89-a2f9-78ce3145e4fc","6b4ae089-e1ee-431f-af83-e1133f8e3da0", "1b74ab75-9f41-4837-8662-a1d99118008d", "c1d3be12-ecec-4fab-9237-baf728575185", "8be05cf5-fb4f-4752-8094-8e179d08fb99"); + List data = List.of( + new FieldRange().withFrom("001").withTo("001"), + new FieldRange().withFrom("007").withTo("007") + ); + + Conditions conditions = new Conditions() + .withIdType(IdType.INSTANCE.name()) + .withIds(List.of("3c4ae3f3-b460-4a89-a2f9-78ce3145e4fc", "6b4ae089-e1ee-431f-af83-e1133f8e3da0", "1b74ab75-9f41-4837-8662-a1d99118008d", "c1d3be12-ecec-4fab-9237-baf728575185", "8be05cf5-fb4f-4752-8094-8e179d08fb99")); + FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() + .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) + .withConditions(conditions) + .withData(data) + .withIncludeDeleted(true); + + recordService.fetchStrippedParsedRecords(batchRequest, TENANT_ID).onComplete(get -> { + if (get.failed()) { + context.fail(get.cause()); + } + List expected = records.stream() + .filter(r -> r.getRecordType().equals(Record.RecordType.MARC_BIB)) + .filter(r -> externalIds.contains(r.getExternalIdsHolder().getInstanceId())) + .collect(Collectors.toList()); + context.assertEquals(expected.size(), get.result().getTotalRecords()); + async.complete(); + }); + }); + } + + @Test + public void shouldFetchActualBibRecordsWithOneFieldByExternalIdWhenIncludeDeletedNotExists(TestContext context) { + Async async = context.async(); + List records = TestMocks.getRecords(); + records.get(3).setDeleted(true); + records.get(3).setState(State.DELETED); + records.get(5).setDeleted(true); + records.get(5).setState(State.DELETED); + RecordCollection recordCollection = new RecordCollection() + .withRecords(records) + .withTotalRecords(records.size()); + saveRecords(recordCollection.getRecords()).onComplete(batch -> { + if (batch.failed()) { + context.fail(batch.cause()); + } + + Set externalIds = Set.of("3c4ae3f3-b460-4a89-a2f9-78ce3145e4fc","6b4ae089-e1ee-431f-af83-e1133f8e3da0", "1b74ab75-9f41-4837-8662-a1d99118008d", "c1d3be12-ecec-4fab-9237-baf728575185", "8be05cf5-fb4f-4752-8094-8e179d08fb99"); + List data = List.of( + new FieldRange().withFrom("001").withTo("001"), + new FieldRange().withFrom("007").withTo("007") + ); + + Conditions conditions = new Conditions() + .withIdType(IdType.INSTANCE.name()) + .withIds(List.of("3c4ae3f3-b460-4a89-a2f9-78ce3145e4fc", "6b4ae089-e1ee-431f-af83-e1133f8e3da0", "1b74ab75-9f41-4837-8662-a1d99118008d", "c1d3be12-ecec-4fab-9237-baf728575185", "8be05cf5-fb4f-4752-8094-8e179d08fb99")); + FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() + .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) + .withConditions(conditions) + .withData(data); + + recordService.fetchStrippedParsedRecords(batchRequest, TENANT_ID).onComplete(get -> { + if (get.failed()) { + context.fail(get.cause()); + } + List expected = records.stream() + .filter(r -> r.getRecordType().equals(Record.RecordType.MARC_BIB)) + .filter(r -> externalIds.contains(r.getExternalIdsHolder().getInstanceId())) + .filter(r -> r.getState().equals(State.ACTUAL)) + .collect(Collectors.toList()); + context.assertEquals(expected.size(), get.result().getTotalRecords()); + async.complete(); + }); + }); + } + + @Test + public void shouldFetchActualAndDeletedBibRecordsWithOneFieldByExternalIdWhenIncludeDeletedFalse(TestContext context) { + Async async = context.async(); + List records = TestMocks.getRecords(); + records.get(3).setDeleted(true); + records.get(3).setState(State.DELETED); + records.get(5).setDeleted(true); + records.get(5).setState(State.DELETED); + RecordCollection recordCollection = new RecordCollection() + .withRecords(records) + .withTotalRecords(records.size()); + saveRecords(recordCollection.getRecords()).onComplete(batch -> { + if (batch.failed()) { + context.fail(batch.cause()); + } + + Set externalIds = Set.of("3c4ae3f3-b460-4a89-a2f9-78ce3145e4fc","6b4ae089-e1ee-431f-af83-e1133f8e3da0", "1b74ab75-9f41-4837-8662-a1d99118008d", "c1d3be12-ecec-4fab-9237-baf728575185", "8be05cf5-fb4f-4752-8094-8e179d08fb99"); + List data = List.of( + new FieldRange().withFrom("001").withTo("001"), + new FieldRange().withFrom("007").withTo("007") + ); + + Conditions conditions = new Conditions() + .withIdType(IdType.INSTANCE.name()) + .withIds(List.of("3c4ae3f3-b460-4a89-a2f9-78ce3145e4fc", "6b4ae089-e1ee-431f-af83-e1133f8e3da0", "1b74ab75-9f41-4837-8662-a1d99118008d", "c1d3be12-ecec-4fab-9237-baf728575185", "8be05cf5-fb4f-4752-8094-8e179d08fb99")); + FetchParsedRecordsBatchRequest batchRequest = new FetchParsedRecordsBatchRequest() + .withRecordType(FetchParsedRecordsBatchRequest.RecordType.MARC_BIB) + .withConditions(conditions) + .withData(data) + .withIncludeDeleted(false); + + recordService.fetchStrippedParsedRecords(batchRequest, TENANT_ID).onComplete(get -> { + if (get.failed()) { + context.fail(get.cause()); + } + List expected = records.stream() + .filter(r -> r.getRecordType().equals(Record.RecordType.MARC_BIB)) + .filter(r -> externalIds.contains(r.getExternalIdsHolder().getInstanceId())) + .filter(r -> r.getState().equals(State.ACTUAL)) + .collect(Collectors.toList()); + context.assertEquals(expected.size(), get.result().getTotalRecords()); + async.complete(); + }); + }); + } + @Test public void shouldGetMarcAuthorityRecordsBySnapshotId(TestContext context) { getRecordsBySnapshotId(context, "ee561342-3098-47a8-ab6e-0f3eba120b04", RecordType.MARC_AUTHORITY,