mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-27 00:31:42 +00:00
* Fix #18332: Do not consolidate changes for Parent Entities * Fix #18332: Do not consolidate changes for Parent Entities * added no data placeholder when no tags there * fix failing playwright test due to consolidation changes and added the missing services * Fix tests * Fix parent entity change notifications * Fix tests * Fix parent entity change notifications * Fix tests * Fix tests --------- Co-authored-by: Ashish Gupta <ashish@getcollate.io>
This commit is contained in:
parent
2539ffa8de
commit
680ace99b3
@ -243,6 +243,7 @@ public final class Entity {
|
|||||||
public static final String DOCUMENT = "document";
|
public static final String DOCUMENT = "document";
|
||||||
// ServiceType - Service Entity name map
|
// ServiceType - Service Entity name map
|
||||||
static final Map<ServiceType, String> SERVICE_TYPE_ENTITY_MAP = new EnumMap<>(ServiceType.class);
|
static final Map<ServiceType, String> SERVICE_TYPE_ENTITY_MAP = new EnumMap<>(ServiceType.class);
|
||||||
|
public static final List<String> PARENT_ENTITY_TYPES = new ArrayList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.DATABASE, DATABASE_SERVICE);
|
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.DATABASE, DATABASE_SERVICE);
|
||||||
@ -254,6 +255,25 @@ public final class Entity {
|
|||||||
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.STORAGE, STORAGE_SERVICE);
|
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.STORAGE, STORAGE_SERVICE);
|
||||||
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.SEARCH, SEARCH_SERVICE);
|
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.SEARCH, SEARCH_SERVICE);
|
||||||
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.API, API_SERVICE);
|
SERVICE_TYPE_ENTITY_MAP.put(ServiceType.API, API_SERVICE);
|
||||||
|
PARENT_ENTITY_TYPES.addAll(
|
||||||
|
listOf(
|
||||||
|
DATABASE_SERVICE,
|
||||||
|
DASHBOARD_SERVICE,
|
||||||
|
MESSAGING_SERVICE,
|
||||||
|
MLMODEL_SERVICE,
|
||||||
|
PIPELINE_SERVICE,
|
||||||
|
API_SERVICE,
|
||||||
|
API_COLLCECTION,
|
||||||
|
STORAGE_SERVICE,
|
||||||
|
METADATA_SERVICE,
|
||||||
|
SEARCH_SERVICE,
|
||||||
|
DATABASE,
|
||||||
|
DATABASE_SCHEMA,
|
||||||
|
CLASSIFICATION,
|
||||||
|
GLOSSARY,
|
||||||
|
DOMAIN,
|
||||||
|
TEST_SUITE,
|
||||||
|
TEAM));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entity() {}
|
private Entity() {}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ public class APICollectionRepository extends EntityRepository<APICollection> {
|
|||||||
"",
|
"",
|
||||||
"");
|
"");
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -16,5 +16,6 @@ public class APIServiceRepository extends ServiceEntityRepository<ApiService, Ap
|
|||||||
"",
|
"",
|
||||||
ServiceType.API);
|
ServiceType.API);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,7 @@ public class ClassificationRepository extends EntityRepository<Classification> {
|
|||||||
quoteFqn = true;
|
quoteFqn = true;
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
renameAllowed = true;
|
renameAllowed = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -33,5 +33,6 @@ public class DashboardServiceRepository
|
|||||||
"",
|
"",
|
||||||
ServiceType.DASHBOARD);
|
ServiceType.DASHBOARD);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,7 @@ public class DatabaseRepository extends EntityRepository<Database> {
|
|||||||
"",
|
"",
|
||||||
"");
|
"");
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
fieldFetchers.put("name", this::fetchAndSetService);
|
fieldFetchers.put("name", this::fetchAndSetService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,6 +74,7 @@ public class DatabaseSchemaRepository extends EntityRepository<DatabaseSchema> {
|
|||||||
"",
|
"",
|
||||||
"");
|
"");
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -60,6 +60,7 @@ public class DatabaseServiceRepository
|
|||||||
"",
|
"",
|
||||||
ServiceType.DATABASE);
|
ServiceType.DATABASE);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public class DomainRepository extends EntityRepository<Domain> {
|
|||||||
UPDATE_FIELDS,
|
UPDATE_FIELDS,
|
||||||
UPDATE_FIELDS);
|
UPDATE_FIELDS);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -260,6 +260,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
@Getter protected final Fields putFields;
|
@Getter protected final Fields putFields;
|
||||||
|
|
||||||
protected boolean supportsSearch = false;
|
protected boolean supportsSearch = false;
|
||||||
|
@Getter protected boolean parent = false;
|
||||||
protected final Map<String, BiConsumer<List<T>, Fields>> fieldFetchers = new HashMap<>();
|
protected final Map<String, BiConsumer<List<T>, Fields>> fieldFetchers = new HashMap<>();
|
||||||
|
|
||||||
protected EntityRepository(
|
protected EntityRepository(
|
||||||
@ -3276,7 +3277,9 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
|
|
||||||
private boolean consolidateChanges(T original, T updated, Operation operation) {
|
private boolean consolidateChanges(T original, T updated, Operation operation) {
|
||||||
// If user is the same and the new update is with in the user session timeout
|
// If user is the same and the new update is with in the user session timeout
|
||||||
return original.getVersion() > 0.1 // First update on an entity that
|
return !parent // Parent entity shouldn't consolidate changes, as we need ChangeDescription to
|
||||||
|
// propagate to children
|
||||||
|
&& original.getVersion() > 0.1 // First update on an entity that
|
||||||
&& operation == Operation.PATCH
|
&& operation == Operation.PATCH
|
||||||
&& !Boolean.TRUE.equals(original.getDeleted()) // Entity is not soft deleted
|
&& !Boolean.TRUE.equals(original.getDeleted()) // Entity is not soft deleted
|
||||||
&& !operation.isDelete() // Operation must be an update
|
&& !operation.isDelete() // Operation must be an update
|
||||||
@ -3285,6 +3288,7 @@ public abstract class EntityRepository<T extends EntityInterface> {
|
|||||||
.equals(updated.getUpdatedBy()) // Must be updated by the same user
|
.equals(updated.getUpdatedBy()) // Must be updated by the same user
|
||||||
&& updated.getUpdatedAt() - original.getUpdatedAt()
|
&& updated.getUpdatedAt() - original.getUpdatedAt()
|
||||||
<= sessionTimeoutMillis; // With in session timeout
|
<= sessionTimeoutMillis; // With in session timeout
|
||||||
|
// changes to children
|
||||||
}
|
}
|
||||||
|
|
||||||
private T getPreviousVersion(T original) {
|
private T getPreviousVersion(T original) {
|
||||||
|
|||||||
@ -89,6 +89,7 @@ public class GlossaryRepository extends EntityRepository<Glossary> {
|
|||||||
quoteFqn = true;
|
quoteFqn = true;
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
renameAllowed = true;
|
renameAllowed = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -34,5 +34,6 @@ public class MessagingServiceRepository
|
|||||||
UPDATE_FIELDS,
|
UPDATE_FIELDS,
|
||||||
ServiceType.MESSAGING);
|
ServiceType.MESSAGING);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,5 +19,6 @@ public class MetadataServiceRepository
|
|||||||
UPDATE_FIELDS,
|
UPDATE_FIELDS,
|
||||||
ServiceType.METADATA);
|
ServiceType.METADATA);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,5 +34,6 @@ public class MlModelServiceRepository
|
|||||||
UPDATE_FIELDS,
|
UPDATE_FIELDS,
|
||||||
ServiceType.ML_MODEL);
|
ServiceType.ML_MODEL);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,5 +33,6 @@ public class PipelineServiceRepository
|
|||||||
"",
|
"",
|
||||||
ServiceType.PIPELINE);
|
ServiceType.PIPELINE);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,6 @@ public class SearchServiceRepository
|
|||||||
"",
|
"",
|
||||||
ServiceType.SEARCH);
|
ServiceType.SEARCH);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,5 +17,6 @@ public class StorageServiceRepository
|
|||||||
"",
|
"",
|
||||||
ServiceType.STORAGE);
|
ServiceType.STORAGE);
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,6 +102,7 @@ public class TeamRepository extends EntityRepository<Team> {
|
|||||||
TEAM_UPDATE_FIELDS);
|
TEAM_UPDATE_FIELDS);
|
||||||
this.quoteFqn = true;
|
this.quoteFqn = true;
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -104,6 +104,7 @@ public class TestSuiteRepository extends EntityRepository<TestSuite> {
|
|||||||
UPDATE_FIELDS);
|
UPDATE_FIELDS);
|
||||||
quoteFqn = false;
|
quoteFqn = false;
|
||||||
supportsSearch = true;
|
supportsSearch = true;
|
||||||
|
parent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -449,7 +449,7 @@ public class SearchRepository {
|
|||||||
Map<String, Object> fieldData = new HashMap<>();
|
Map<String, Object> fieldData = new HashMap<>();
|
||||||
|
|
||||||
if (changeDescription != null) {
|
if (changeDescription != null) {
|
||||||
for (FieldChange field : changeDescription.getFieldsAdded()) {
|
for (FieldChange field : changeDescription.getFieldsDeleted()) {
|
||||||
if (inheritableFields.contains(field.getName())) {
|
if (inheritableFields.contains(field.getName())) {
|
||||||
try {
|
try {
|
||||||
if (field.getName().equals(FIELD_OWNERS)) {
|
if (field.getName().equals(FIELD_OWNERS)) {
|
||||||
@ -458,24 +458,21 @@ public class SearchRepository {
|
|||||||
for (EntityReference inheritedOwner : inheritedOwners) {
|
for (EntityReference inheritedOwner : inheritedOwners) {
|
||||||
inheritedOwner.setInherited(true);
|
inheritedOwner.setInherited(true);
|
||||||
}
|
}
|
||||||
fieldData.put("updatedOwners", inheritedOwners);
|
fieldData.put("deletedOwners", inheritedOwners);
|
||||||
scriptTxt.append(ADD_OWNERS_SCRIPT);
|
scriptTxt.append(REMOVE_OWNERS_SCRIPT);
|
||||||
} else {
|
} else {
|
||||||
EntityReference entityReference =
|
EntityReference entityReference =
|
||||||
JsonUtils.readValue(field.getNewValue().toString(), EntityReference.class);
|
JsonUtils.readValue(field.getOldValue().toString(), EntityReference.class);
|
||||||
scriptTxt.append(
|
scriptTxt.append(
|
||||||
String.format(
|
String.format(
|
||||||
PROPAGATE_ENTITY_REFERENCE_FIELD_SCRIPT,
|
REMOVE_PROPAGATED_ENTITY_REFERENCE_FIELD_SCRIPT,
|
||||||
field.getName(),
|
|
||||||
field.getName(),
|
|
||||||
field.getName(),
|
field.getName(),
|
||||||
field.getName(),
|
field.getName(),
|
||||||
field.getName()));
|
field.getName()));
|
||||||
fieldData.put(field.getName(), entityReference);
|
fieldData.put(field.getName(), JsonUtils.getMap(entityReference));
|
||||||
}
|
}
|
||||||
} catch (UnhandledServerException e) {
|
} catch (UnhandledServerException e) {
|
||||||
scriptTxt.append(
|
scriptTxt.append(String.format(REMOVE_PROPAGATED_FIELD_SCRIPT, field.getName()));
|
||||||
String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,7 +504,7 @@ public class SearchRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (FieldChange field : changeDescription.getFieldsDeleted()) {
|
for (FieldChange field : changeDescription.getFieldsAdded()) {
|
||||||
if (inheritableFields.contains(field.getName())) {
|
if (inheritableFields.contains(field.getName())) {
|
||||||
try {
|
try {
|
||||||
if (field.getName().equals(FIELD_OWNERS)) {
|
if (field.getName().equals(FIELD_OWNERS)) {
|
||||||
@ -516,21 +513,24 @@ public class SearchRepository {
|
|||||||
for (EntityReference inheritedOwner : inheritedOwners) {
|
for (EntityReference inheritedOwner : inheritedOwners) {
|
||||||
inheritedOwner.setInherited(true);
|
inheritedOwner.setInherited(true);
|
||||||
}
|
}
|
||||||
fieldData.put("deletedOwners", inheritedOwners);
|
fieldData.put("updatedOwners", inheritedOwners);
|
||||||
scriptTxt.append(REMOVE_OWNERS_SCRIPT);
|
scriptTxt.append(ADD_OWNERS_SCRIPT);
|
||||||
} else {
|
} else {
|
||||||
EntityReference entityReference =
|
EntityReference entityReference =
|
||||||
JsonUtils.readValue(field.getOldValue().toString(), EntityReference.class);
|
JsonUtils.readValue(field.getNewValue().toString(), EntityReference.class);
|
||||||
scriptTxt.append(
|
scriptTxt.append(
|
||||||
String.format(
|
String.format(
|
||||||
REMOVE_PROPAGATED_ENTITY_REFERENCE_FIELD_SCRIPT,
|
PROPAGATE_ENTITY_REFERENCE_FIELD_SCRIPT,
|
||||||
|
field.getName(),
|
||||||
|
field.getName(),
|
||||||
field.getName(),
|
field.getName(),
|
||||||
field.getName(),
|
field.getName(),
|
||||||
field.getName()));
|
field.getName()));
|
||||||
fieldData.put(field.getName(), JsonUtils.getMap(entityReference));
|
fieldData.put(field.getName(), entityReference);
|
||||||
}
|
}
|
||||||
} catch (UnhandledServerException e) {
|
} catch (UnhandledServerException e) {
|
||||||
scriptTxt.append(String.format(REMOVE_PROPAGATED_FIELD_SCRIPT, field.getName()));
|
scriptTxt.append(
|
||||||
|
String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1549,13 +1549,24 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
checkOwnerOwns(TEAM11_REF, entity.getId(), true);
|
checkOwnerOwns(TEAM11_REF, entity.getId(), true);
|
||||||
|
|
||||||
// V0-2 (consolidated) - Change owner from TEAM_OWNER1 to USER_OWNER1 using PATCH request
|
// V0-2 (consolidated) - Change owner from TEAM_OWNER1 to USER_OWNER1 using PATCH request
|
||||||
json = JsonUtils.pojoToJson(entity);
|
if (!isParent()) {
|
||||||
entity.setOwners(List.of(USER1_REF));
|
json = JsonUtils.pojoToJson(entity);
|
||||||
change = getChangeDescription(entity, CHANGE_CONSOLIDATED);
|
entity.setOwners(List.of(USER1_REF));
|
||||||
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
|
change = getChangeDescription(entity, getChangeType());
|
||||||
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
|
||||||
checkOwnerOwns(USER1_REF, entity.getId(), true);
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
checkOwnerOwns(TEAM11_REF, entity.getId(), false);
|
checkOwnerOwns(USER1_REF, entity.getId(), true);
|
||||||
|
checkOwnerOwns(TEAM11_REF, entity.getId(), false);
|
||||||
|
} else {
|
||||||
|
json = JsonUtils.pojoToJson(entity);
|
||||||
|
entity.setOwners(List.of(USER1_REF));
|
||||||
|
change = getChangeDescription(entity, getChangeType());
|
||||||
|
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
|
||||||
|
fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF));
|
||||||
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
checkOwnerOwns(USER1_REF, entity.getId(), true);
|
||||||
|
checkOwnerOwns(TEAM11_REF, entity.getId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
// V0.2 (no change) - Set the owner to the existing owner. No ownership change must be recorded.
|
// V0.2 (no change) - Set the owner to the existing owner. No ownership change must be recorded.
|
||||||
json = JsonUtils.pojoToJson(entity);
|
json = JsonUtils.pojoToJson(entity);
|
||||||
@ -1565,11 +1576,20 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
|
|
||||||
// V0.1 (revert) - Remove ownership (USER_OWNER1) using PATCH. We are back to original state no
|
// V0.1 (revert) - Remove ownership (USER_OWNER1) using PATCH. We are back to original state no
|
||||||
// owner and no change
|
// owner and no change
|
||||||
json = JsonUtils.pojoToJson(entity);
|
if (!isParent()) {
|
||||||
entity.setOwners(null);
|
json = JsonUtils.pojoToJson(entity);
|
||||||
change = getChangeDescription(entity, REVERT);
|
entity.setOwners(null);
|
||||||
patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, REVERT, change);
|
change = getChangeDescription(entity, REVERT);
|
||||||
checkOwnerOwns(USER1_REF, entity.getId(), false);
|
patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, REVERT, change);
|
||||||
|
checkOwnerOwns(USER1_REF, entity.getId(), false);
|
||||||
|
} else {
|
||||||
|
json = JsonUtils.pojoToJson(entity);
|
||||||
|
entity.setOwners(null);
|
||||||
|
change = getChangeDescription(entity, MINOR_UPDATE);
|
||||||
|
fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF));
|
||||||
|
patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
checkOwnerOwns(USER1_REF, entity.getId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
// set random type as entity. Check if the ownership validate.
|
// set random type as entity. Check if the ownership validate.
|
||||||
T newEntity = entity;
|
T newEntity = entity;
|
||||||
@ -1873,37 +1893,71 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
//
|
//
|
||||||
// Replace description, add tags tier, owner - Changes are consolidated
|
// Replace description, add tags tier, owner - Changes are consolidated
|
||||||
//
|
//
|
||||||
origJson = JsonUtils.pojoToJson(entity);
|
if (!isParent()) {
|
||||||
entity.setDescription("description1");
|
origJson = JsonUtils.pojoToJson(entity);
|
||||||
entity.setDisplayName("displayName1");
|
entity.setDescription("description1");
|
||||||
change = getChangeDescription(entity, CHANGE_CONSOLIDATED);
|
entity.setDisplayName("displayName1");
|
||||||
fieldUpdated(change, "description", "", "description1");
|
change = getChangeDescription(entity, CHANGE_CONSOLIDATED);
|
||||||
fieldAdded(change, "displayName", "displayName1");
|
fieldUpdated(change, "description", "", "description1");
|
||||||
if (supportsOwners) {
|
fieldAdded(change, "displayName", "displayName1");
|
||||||
entity.setOwners(List.of(USER1_REF));
|
if (supportsOwners) {
|
||||||
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
|
entity.setOwners(List.of(USER1_REF));
|
||||||
|
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsTags) {
|
||||||
|
entity.getTags().add(TIER1_TAG_LABEL);
|
||||||
|
fieldAdded(
|
||||||
|
change,
|
||||||
|
FIELD_TAGS,
|
||||||
|
List.of(USER_ADDRESS_TAG_LABEL, GLOSSARY2_TERM1_LABEL, TIER1_TAG_LABEL));
|
||||||
|
}
|
||||||
|
entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
//
|
||||||
|
// Remove description, tier, owner - Changes are reverted going to 0.1 version of the entity
|
||||||
|
//
|
||||||
|
origJson = JsonUtils.pojoToJson(entity);
|
||||||
|
change = getChangeDescription(entity, REVERT);
|
||||||
|
entity.setDescription("");
|
||||||
|
entity.setDisplayName(null);
|
||||||
|
entity.setOwners(null);
|
||||||
|
entity.setTags(null);
|
||||||
|
patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, REVERT, change);
|
||||||
|
} else {
|
||||||
|
origJson = JsonUtils.pojoToJson(entity);
|
||||||
|
entity.setDescription("description1");
|
||||||
|
entity.setDisplayName("displayName1");
|
||||||
|
change = getChangeDescription(entity, MINOR_UPDATE);
|
||||||
|
fieldUpdated(change, "description", "description", "description1");
|
||||||
|
fieldUpdated(change, "displayName", "displayName", "displayName1");
|
||||||
|
if (supportsOwners) {
|
||||||
|
entity.setOwners(List.of(USER1_REF));
|
||||||
|
fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF));
|
||||||
|
fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsTags) {
|
||||||
|
entity.getTags().add(TIER1_TAG_LABEL);
|
||||||
|
fieldAdded(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL));
|
||||||
|
}
|
||||||
|
entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
|
||||||
|
origJson = JsonUtils.pojoToJson(entity);
|
||||||
|
change = getChangeDescription(entity, MINOR_UPDATE);
|
||||||
|
entity.setDescription("");
|
||||||
|
entity.setDisplayName(null);
|
||||||
|
entity.setOwners(null);
|
||||||
|
entity.setTags(null);
|
||||||
|
fieldUpdated(change, "description", "description1", "");
|
||||||
|
fieldDeleted(change, "displayName", "displayName1");
|
||||||
|
if (supportsOwners) {
|
||||||
|
fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF));
|
||||||
|
}
|
||||||
|
if (supportsTags) {
|
||||||
|
fieldDeleted(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL));
|
||||||
|
}
|
||||||
|
patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportsTags) {
|
|
||||||
entity.getTags().add(TIER1_TAG_LABEL);
|
|
||||||
fieldAdded(
|
|
||||||
change,
|
|
||||||
FIELD_TAGS,
|
|
||||||
List.of(USER_ADDRESS_TAG_LABEL, GLOSSARY2_TERM1_LABEL, TIER1_TAG_LABEL));
|
|
||||||
}
|
|
||||||
|
|
||||||
entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Remove description, tier, owner - Changes are reverted going to 0.1 version of the entity
|
|
||||||
//
|
|
||||||
origJson = JsonUtils.pojoToJson(entity);
|
|
||||||
change = getChangeDescription(entity, REVERT);
|
|
||||||
entity.setDescription("");
|
|
||||||
entity.setDisplayName(null);
|
|
||||||
entity.setOwners(null);
|
|
||||||
entity.setTags(null);
|
|
||||||
patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, REVERT, change);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -1942,32 +1996,61 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
|
|
||||||
// Update description with a new description and the version changes as admin - the changes are
|
// Update description with a new description and the version changes as admin - the changes are
|
||||||
// consolidated
|
// consolidated
|
||||||
json = JsonUtils.pojoToJson(entity);
|
if (!isParent()) {
|
||||||
entity.setDescription("description2");
|
json = JsonUtils.pojoToJson(entity);
|
||||||
change = getChangeDescription(entity, CHANGE_CONSOLIDATED); // New version remains the same
|
entity.setDescription("description2");
|
||||||
fieldUpdated(change, "description", "description", "description2");
|
change = getChangeDescription(entity, getChangeType()); // Version changes
|
||||||
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
fieldUpdated(change, "description", "description", "description2");
|
||||||
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
|
||||||
// Update displayName with a new displayName - but as USER1
|
// Update displayName with a new displayName - but as USER1
|
||||||
// Since the previous change is done by a different user, changes ** are not ** consolidated
|
// Since the previous change is done by a different user, changes ** are not ** consolidated
|
||||||
json = JsonUtils.pojoToJson(entity);
|
json = JsonUtils.pojoToJson(entity);
|
||||||
entity.setDisplayName("displayName");
|
entity.setDisplayName("displayName");
|
||||||
change = getChangeDescription(entity, CHANGE_CONSOLIDATED); // Version changes
|
change = getChangeDescription(entity, CHANGE_CONSOLIDATED); // Version changes
|
||||||
fieldUpdated(change, "description", "description", "description2");
|
fieldUpdated(change, "description", "description", "description2");
|
||||||
fieldAdded(change, "displayName", "displayName");
|
fieldAdded(change, "displayName", "displayName");
|
||||||
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
||||||
|
|
||||||
// Update displayName to a new displayName.
|
// Update displayName to a new displayName.
|
||||||
// In this test, the user who previously made a change makes the change after session timeout.
|
// In this test, the user who previously made a change makes the change after session timeout.
|
||||||
// The changes are not consolidated.
|
// The changes are not consolidated.
|
||||||
EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test
|
EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test
|
||||||
java.lang.Thread.sleep(2);
|
java.lang.Thread.sleep(2);
|
||||||
json = JsonUtils.pojoToJson(entity);
|
json = JsonUtils.pojoToJson(entity);
|
||||||
entity.setDisplayName("displayName1");
|
entity.setDisplayName("displayName1");
|
||||||
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
|
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
|
||||||
fieldUpdated(change, "displayName", "displayName", "displayName1");
|
fieldUpdated(change, "displayName", "displayName", "displayName1");
|
||||||
patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change);
|
patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change);
|
||||||
EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back
|
EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back
|
||||||
|
|
||||||
|
} else {
|
||||||
|
json = JsonUtils.pojoToJson(entity);
|
||||||
|
entity.setDescription("description2");
|
||||||
|
change = getChangeDescription(entity, getChangeType()); // Version changes
|
||||||
|
fieldUpdated(change, "description", "description1", "description2");
|
||||||
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
|
||||||
|
// Update displayName with a new displayName - but as USER1
|
||||||
|
// Since the previous change is done by a different user, changes ** are not ** consolidated
|
||||||
|
json = JsonUtils.pojoToJson(entity);
|
||||||
|
entity.setDisplayName("displayName");
|
||||||
|
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
|
||||||
|
fieldAdded(change, "displayName", "displayName");
|
||||||
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
|
||||||
|
// Update displayName to a new displayName.
|
||||||
|
// In this test, the user who previously made a change makes the change after session timeout.
|
||||||
|
// The changes are not consolidated.
|
||||||
|
EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test
|
||||||
|
java.lang.Thread.sleep(2);
|
||||||
|
json = JsonUtils.pojoToJson(entity);
|
||||||
|
entity.setDisplayName("displayName1");
|
||||||
|
change = getChangeDescription(entity, MINOR_UPDATE); // Version changes
|
||||||
|
fieldUpdated(change, "displayName", "displayName", "displayName1");
|
||||||
|
patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change);
|
||||||
|
EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -2058,17 +2141,21 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
JsonNode stringBValue = mapper.convertValue("stringB", JsonNode.class);
|
JsonNode stringBValue = mapper.convertValue("stringB", JsonNode.class);
|
||||||
jsonNode.set("stringB", stringBValue);
|
jsonNode.set("stringB", stringBValue);
|
||||||
entity.setExtension(jsonNode);
|
entity.setExtension(jsonNode);
|
||||||
change =
|
change = getChangeDescription(entity, getChangeType()); // PATCH operation update is not
|
||||||
getChangeDescription(
|
if (!isParent()) {
|
||||||
entity, CHANGE_CONSOLIDATED); // Patch operation update is consolidated in a session
|
fieldUpdated(
|
||||||
fieldUpdated(
|
change,
|
||||||
change,
|
EntityUtil.getExtensionField("intA"),
|
||||||
EntityUtil.getExtensionField("intA"),
|
mapper.convertValue(1, JsonNode.class),
|
||||||
mapper.convertValue(1, JsonNode.class),
|
intAValue);
|
||||||
intAValue);
|
fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
|
||||||
fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
|
||||||
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
|
} else {
|
||||||
|
fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
|
||||||
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
|
||||||
|
}
|
||||||
|
|
||||||
// PUT and remove field intA from the entity extension - *** for BOT this should be ignored ***
|
// PUT and remove field intA from the entity extension - *** for BOT this should be ignored ***
|
||||||
JsonNode oldNode = JsonUtils.valueToTree(entity.getExtension());
|
JsonNode oldNode = JsonUtils.valueToTree(entity.getExtension());
|
||||||
@ -2088,21 +2175,33 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
assertEquals(
|
assertEquals(
|
||||||
JsonUtils.valueToTree(create.getExtension()), JsonUtils.valueToTree(entity.getExtension()));
|
JsonUtils.valueToTree(create.getExtension()), JsonUtils.valueToTree(entity.getExtension()));
|
||||||
|
|
||||||
// PATCH and remove field stringB from the entity extension
|
if (!isParent()) {
|
||||||
json = JsonUtils.pojoToJson(entity);
|
// PATCH and remove field stringB from the entity extension
|
||||||
jsonNode.remove("stringB");
|
json = JsonUtils.pojoToJson(entity);
|
||||||
entity.setExtension(jsonNode);
|
jsonNode.remove("stringB");
|
||||||
change =
|
entity.setExtension(jsonNode);
|
||||||
getChangeDescription(
|
change =
|
||||||
entity, CHANGE_CONSOLIDATED); // PATCH operation update is consolidated into a session
|
getChangeDescription(
|
||||||
fieldDeleted(
|
entity, CHANGE_CONSOLIDATED); // PATCH operation update is consolidated into a session
|
||||||
change,
|
fieldDeleted(
|
||||||
"extension",
|
change,
|
||||||
List.of(
|
"extension",
|
||||||
JsonUtils.getObjectNode("intA", intAValue),
|
List.of(
|
||||||
JsonUtils.getObjectNode("stringB", stringBValue)));
|
JsonUtils.getObjectNode("intA", intAValue),
|
||||||
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
JsonUtils.getObjectNode("stringB", stringBValue)));
|
||||||
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
|
||||||
|
} else {
|
||||||
|
json = JsonUtils.pojoToJson(entity);
|
||||||
|
jsonNode.remove("stringB");
|
||||||
|
entity.setExtension(jsonNode);
|
||||||
|
change =
|
||||||
|
getChangeDescription(
|
||||||
|
entity, MINOR_UPDATE); // PATCH operation update is consolidated into a session
|
||||||
|
fieldDeleted(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue)));
|
||||||
|
entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change);
|
||||||
|
assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension()));
|
||||||
|
}
|
||||||
|
|
||||||
// Now set the entity custom property to an invalid value
|
// Now set the entity custom property to an invalid value
|
||||||
jsonNode.set(
|
jsonNode.set(
|
||||||
@ -4115,4 +4214,16 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UpdateType getChangeType() {
|
||||||
|
if (isParent()) {
|
||||||
|
return MINOR_UPDATE;
|
||||||
|
} else {
|
||||||
|
return CHANGE_CONSOLIDATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParent() {
|
||||||
|
return PARENT_ENTITY_TYPES.contains(entityType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,9 +10,7 @@ import static org.openmetadata.service.util.EntityUtil.fieldAdded;
|
|||||||
import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
|
import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
|
||||||
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
|
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
|
||||||
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
|
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT;
|
|
||||||
import static org.openmetadata.service.util.TestUtils.assertEntityReferenceNames;
|
import static org.openmetadata.service.util.TestUtils.assertEntityReferenceNames;
|
||||||
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
|
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
|
||||||
import static org.openmetadata.service.util.TestUtils.assertListNull;
|
import static org.openmetadata.service.util.TestUtils.assertListNull;
|
||||||
@ -71,21 +69,17 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain>
|
|||||||
fieldDeleted(change, "experts", listOf(USER2.getEntityReference()));
|
fieldDeleted(change, "experts", listOf(USER2.getEntityReference()));
|
||||||
domain = updateAndCheckEntity(create, Status.OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
domain = updateAndCheckEntity(create, Status.OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
|
||||||
// Add User2 back as expert using PATCH
|
|
||||||
// Version 0. 2 - Changes from this PATCH is consolidated with the previous change resulting in
|
|
||||||
// no change
|
|
||||||
String json = JsonUtils.pojoToJson(domain);
|
String json = JsonUtils.pojoToJson(domain);
|
||||||
domain.withExperts(List.of(USER1.getEntityReference(), USER2.getEntityReference()));
|
domain.withExperts(List.of(USER1.getEntityReference(), USER2.getEntityReference()));
|
||||||
change = getChangeDescription(domain, REVERT);
|
change = getChangeDescription(domain, MINOR_UPDATE);
|
||||||
domain = patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, REVERT, change);
|
fieldAdded(change, "experts", listOf(USER2.getEntityReference()));
|
||||||
|
domain = patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
|
||||||
// Remove User2 as expert using PATCH
|
|
||||||
// Version 0.1 - Changes from this PATCH is consolidated with the previous two changes resulting
|
|
||||||
// in deletion of USER2
|
|
||||||
json = JsonUtils.pojoToJson(domain);
|
json = JsonUtils.pojoToJson(domain);
|
||||||
change = getChangeDescription(domain, REVERT);
|
change = getChangeDescription(domain, MINOR_UPDATE);
|
||||||
|
fieldDeleted(change, "experts", listOf(USER2.getEntityReference()));
|
||||||
domain.withExperts(List.of(USER1.getEntityReference()));
|
domain.withExperts(List.of(USER1.getEntityReference()));
|
||||||
patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, REVERT, change);
|
patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -104,9 +98,9 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain>
|
|||||||
// Changes from this PATCH is consolidated with the previous changes
|
// Changes from this PATCH is consolidated with the previous changes
|
||||||
String json = JsonUtils.pojoToJson(domain);
|
String json = JsonUtils.pojoToJson(domain);
|
||||||
domain.withDomainType(DomainType.CONSUMER_ALIGNED);
|
domain.withDomainType(DomainType.CONSUMER_ALIGNED);
|
||||||
change = getChangeDescription(domain, CHANGE_CONSOLIDATED);
|
change = getChangeDescription(domain, MINOR_UPDATE);
|
||||||
fieldUpdated(change, "domainType", DomainType.AGGREGATE, DomainType.CONSUMER_ALIGNED);
|
fieldUpdated(change, "domainType", DomainType.SOURCE_ALIGNED, DomainType.CONSUMER_ALIGNED);
|
||||||
patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -37,11 +37,11 @@ import static org.openmetadata.schema.type.ProviderType.SYSTEM;
|
|||||||
import static org.openmetadata.schema.type.TaskType.RequestDescription;
|
import static org.openmetadata.schema.type.TaskType.RequestDescription;
|
||||||
import static org.openmetadata.service.security.SecurityUtil.authHeaders;
|
import static org.openmetadata.service.security.SecurityUtil.authHeaders;
|
||||||
import static org.openmetadata.service.util.EntityUtil.fieldAdded;
|
import static org.openmetadata.service.util.EntityUtil.fieldAdded;
|
||||||
|
import static org.openmetadata.service.util.EntityUtil.fieldDeleted;
|
||||||
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
|
import static org.openmetadata.service.util.EntityUtil.fieldUpdated;
|
||||||
import static org.openmetadata.service.util.EntityUtil.getFqn;
|
import static org.openmetadata.service.util.EntityUtil.getFqn;
|
||||||
import static org.openmetadata.service.util.EntityUtil.toTagLabels;
|
import static org.openmetadata.service.util.EntityUtil.toTagLabels;
|
||||||
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
|
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
||||||
import static org.openmetadata.service.util.TestUtils.assertListNull;
|
import static org.openmetadata.service.util.TestUtils.assertListNull;
|
||||||
import static org.openmetadata.service.util.TestUtils.assertResponse;
|
import static org.openmetadata.service.util.TestUtils.assertResponse;
|
||||||
@ -168,11 +168,9 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
|||||||
glossary.withReviewers(List.of(USER1_REF, USER2_REF));
|
glossary.withReviewers(List.of(USER1_REF, USER2_REF));
|
||||||
change =
|
change =
|
||||||
getChangeDescription(
|
getChangeDescription(
|
||||||
glossary,
|
glossary, MINOR_UPDATE); // PATCH operation update is consolidated in a user session
|
||||||
CHANGE_CONSOLIDATED); // PATCH operation update is consolidated in a user session
|
fieldAdded(change, "reviewers", List.of(USER2_REF));
|
||||||
fieldAdded(change, "reviewers", List.of(USER1_REF, USER2_REF));
|
glossary = patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
glossary =
|
|
||||||
patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
|
||||||
|
|
||||||
// Create a glossary term and assign USER2 as a reviewer
|
// Create a glossary term and assign USER2 as a reviewer
|
||||||
GlossaryTermResourceTest glossaryTermResourceTest = new GlossaryTermResourceTest();
|
GlossaryTermResourceTest glossaryTermResourceTest = new GlossaryTermResourceTest();
|
||||||
@ -220,10 +218,9 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo
|
|||||||
glossary.withReviewers(List.of(USER2_REF));
|
glossary.withReviewers(List.of(USER2_REF));
|
||||||
change =
|
change =
|
||||||
getChangeDescription(
|
getChangeDescription(
|
||||||
glossary,
|
glossary, MINOR_UPDATE); // PATCH operation update is consolidated in a user session
|
||||||
CHANGE_CONSOLIDATED); // PATCH operation update is consolidated in a user session
|
fieldDeleted(change, "reviewers", List.of(USER1_REF));
|
||||||
fieldAdded(change, "reviewers", List.of(USER2_REF));
|
patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
|
||||||
|
|
||||||
// Verify that USER1_REF is removed from the reviewers for the terms inside the glossary
|
// Verify that USER1_REF is removed from the reviewers for the terms inside the glossary
|
||||||
GLOSSARY_TERM1 =
|
GLOSSARY_TERM1 =
|
||||||
|
|||||||
@ -52,10 +52,8 @@ import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS;
|
|||||||
import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS;
|
import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS;
|
||||||
import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME;
|
import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME;
|
||||||
import static org.openmetadata.service.util.TestUtils.USER_WITH_CREATE_HEADERS;
|
import static org.openmetadata.service.util.TestUtils.USER_WITH_CREATE_HEADERS;
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED;
|
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE;
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.NO_CHANGE;
|
import static org.openmetadata.service.util.TestUtils.UpdateType.NO_CHANGE;
|
||||||
import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT;
|
|
||||||
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
|
import static org.openmetadata.service.util.TestUtils.assertListNotNull;
|
||||||
import static org.openmetadata.service.util.TestUtils.assertResponse;
|
import static org.openmetadata.service.util.TestUtils.assertResponse;
|
||||||
import static org.openmetadata.service.util.TestUtils.validateEntityReferences;
|
import static org.openmetadata.service.util.TestUtils.validateEntityReferences;
|
||||||
@ -600,11 +598,12 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
|
|||||||
bu2 = updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
bu2 = updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
|
||||||
// Change bu2 parent from Organization to bu1 using PATCH operation.
|
// Change bu2 parent from Organization to bu1 using PATCH operation.
|
||||||
// Change from this PATCH is combined with the previous PUT resulting in no change
|
|
||||||
String json = JsonUtils.pojoToJson(bu2);
|
String json = JsonUtils.pojoToJson(bu2);
|
||||||
change = getChangeDescription(bu2, REVERT);
|
change = getChangeDescription(bu2, MINOR_UPDATE);
|
||||||
bu2.setParents(List.of(bu1.getEntityReference()));
|
bu2.setParents(List.of(bu1.getEntityReference()));
|
||||||
patchEntityAndCheck(bu2, json, ADMIN_AUTH_HEADERS, REVERT, change);
|
fieldAdded(change, "parents", List.of(bu1.getEntityReference()));
|
||||||
|
fieldDeleted(change, "parents", List.of(ORG_TEAM.getEntityReference()));
|
||||||
|
patchEntityAndCheck(bu2, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -626,11 +625,11 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
|
|||||||
fieldUpdated(change, "isJoinable", false, true);
|
fieldUpdated(change, "isJoinable", false, true);
|
||||||
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
|
||||||
// set isJoinable to false - change from this PATCH and the previous are consolidated resulting
|
|
||||||
// in no change
|
|
||||||
json = JsonUtils.pojoToJson(team);
|
json = JsonUtils.pojoToJson(team);
|
||||||
team.setIsJoinable(false);
|
team.setIsJoinable(false);
|
||||||
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, NO_CHANGE, null);
|
change = getChangeDescription(team, MINOR_UPDATE);
|
||||||
|
fieldUpdated(change, "isJoinable", true, false);
|
||||||
|
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -672,10 +671,9 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
|
|||||||
int removeDefaultRoleIndex = new Random().nextInt(roles.size());
|
int removeDefaultRoleIndex = new Random().nextInt(roles.size());
|
||||||
EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex);
|
EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex);
|
||||||
team.getDefaultRoles().remove(removeDefaultRoleIndex);
|
team.getDefaultRoles().remove(removeDefaultRoleIndex);
|
||||||
change = getChangeDescription(team, CHANGE_CONSOLIDATED);
|
change = getChangeDescription(team, MINOR_UPDATE);
|
||||||
fieldDeleted(change, "users", CommonUtil.listOf(deletedUser));
|
|
||||||
fieldDeleted(change, "defaultRoles", CommonUtil.listOf(deletedRole));
|
fieldDeleted(change, "defaultRoles", CommonUtil.listOf(deletedRole));
|
||||||
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -725,8 +723,10 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
|
|||||||
// resulting in no change
|
// resulting in no change
|
||||||
json = JsonUtils.pojoToJson(team);
|
json = JsonUtils.pojoToJson(team);
|
||||||
team.withPolicies(null);
|
team.withPolicies(null);
|
||||||
change = getChangeDescription(team, REVERT);
|
change = getChangeDescription(team, MINOR_UPDATE);
|
||||||
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, REVERT, change);
|
fieldDeleted(
|
||||||
|
change, "policies", List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference()));
|
||||||
|
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -768,13 +768,11 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> {
|
|||||||
fieldUpdated(change, "profile", PROFILE, profile1);
|
fieldUpdated(change, "profile", PROFILE, profile1);
|
||||||
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
|
|
||||||
// Remove profile from the team - Change from this PATCH and previous are consolidated to no
|
|
||||||
// change
|
|
||||||
json = JsonUtils.pojoToJson(team);
|
json = JsonUtils.pojoToJson(team);
|
||||||
team.withProfile(null);
|
team.withProfile(null);
|
||||||
change = getChangeDescription(team, CHANGE_CONSOLIDATED);
|
change = getChangeDescription(team, MINOR_UPDATE);
|
||||||
fieldDeleted(change, "profile", PROFILE);
|
fieldDeleted(change, "profile", profile1);
|
||||||
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change);
|
patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -89,7 +89,7 @@ test('Glossary', async ({ page }) => {
|
|||||||
|
|
||||||
await page.reload();
|
await page.reload();
|
||||||
const versionPageResponse = page.waitForResponse(
|
const versionPageResponse = page.waitForResponse(
|
||||||
`/api/v1/glossaries/${glossary.responseData.id}/versions/0.2`
|
`/api/v1/glossaries/${glossary.responseData.id}/versions/0.3`
|
||||||
);
|
);
|
||||||
await page.click('[data-testid="version-button"]');
|
await page.click('[data-testid="version-button"]');
|
||||||
await versionPageResponse;
|
await versionPageResponse;
|
||||||
|
|||||||
@ -173,7 +173,9 @@ test('Classification Page', async ({ page }) => {
|
|||||||
)
|
)
|
||||||
).not.toBeVisible();
|
).not.toBeVisible();
|
||||||
|
|
||||||
await expect(page.getByTestId('saveAssociatedTag')).not.toBeVisible();
|
await expect(page.getByText('No Tags are available')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByTestId('saveAssociatedTag')).toBeDisabled();
|
||||||
|
|
||||||
// Re-enable the disabled Classification
|
// Re-enable the disabled Classification
|
||||||
await classification.visitPage(page);
|
await classification.visitPage(page);
|
||||||
@ -207,6 +209,7 @@ test('Classification Page', async ({ page }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await test.step('Create classification with validation checks', async () => {
|
await test.step('Create classification with validation checks', async () => {
|
||||||
|
await classification.visitPage(page);
|
||||||
await page.click('[data-testid="add-classification"]');
|
await page.click('[data-testid="add-classification"]');
|
||||||
await page.waitForSelector('.ant-modal-content', {
|
await page.waitForSelector('.ant-modal-content', {
|
||||||
state: 'visible',
|
state: 'visible',
|
||||||
|
|||||||
@ -80,12 +80,12 @@ test('Classification version page', async ({ page }) => {
|
|||||||
await patchClassificationResponse;
|
await patchClassificationResponse;
|
||||||
|
|
||||||
// Verify disabled state
|
// Verify disabled state
|
||||||
await page.click('[data-testid="version-button"]:has-text("0.2")');
|
await page.click('[data-testid="version-button"]:has-text("0.3")');
|
||||||
|
|
||||||
await expect(page.locator('[data-testid="disabled"]')).toBeVisible();
|
await expect(page.locator('[data-testid="disabled"]')).toBeVisible();
|
||||||
|
|
||||||
// Toggle back to enabled
|
// Toggle back to enabled
|
||||||
await page.click('[data-testid="version-button"]:has-text("0.2")');
|
await page.click('[data-testid="version-button"]:has-text("0.3")');
|
||||||
await page.click('[data-testid="manage-button"]');
|
await page.click('[data-testid="manage-button"]');
|
||||||
const patchClassificationResponse2 = page.waitForResponse(
|
const patchClassificationResponse2 = page.waitForResponse(
|
||||||
`/api/v1/classifications/${classification.responseData?.id}`
|
`/api/v1/classifications/${classification.responseData?.id}`
|
||||||
@ -94,7 +94,7 @@ test('Classification version page', async ({ page }) => {
|
|||||||
await patchClassificationResponse2;
|
await patchClassificationResponse2;
|
||||||
|
|
||||||
// Verify enabled state
|
// Verify enabled state
|
||||||
await page.click('[data-testid="version-button"]:has-text("0.2")');
|
await page.click('[data-testid="version-button"]:has-text("0.4")');
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator(`[data-testid="classification-${classification.data.name}"]`)
|
page.locator(`[data-testid="classification-${classification.data.name}"]`)
|
||||||
|
|||||||
@ -153,7 +153,7 @@ entities.forEach((EntityClass) => {
|
|||||||
type: 'Users',
|
type: 'Users',
|
||||||
});
|
});
|
||||||
|
|
||||||
const versionDetailResponse = page.waitForResponse(`**/versions/0.2`);
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.3`);
|
||||||
await page.locator('[data-testid="version-button"]').click();
|
await page.locator('[data-testid="version-button"]').click();
|
||||||
await versionDetailResponse;
|
await versionDetailResponse;
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ entities.forEach((EntityClass) => {
|
|||||||
|
|
||||||
await assignTier(page, 'Tier1', entity.endpoint);
|
await assignTier(page, 'Tier1', entity.endpoint);
|
||||||
|
|
||||||
const versionDetailResponse = page.waitForResponse(`**/versions/0.2`);
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.4`);
|
||||||
await page.locator('[data-testid="version-button"]').click();
|
await page.locator('[data-testid="version-button"]').click();
|
||||||
await versionDetailResponse;
|
await versionDetailResponse;
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ entities.forEach((EntityClass) => {
|
|||||||
|
|
||||||
await expect(deletedBadge).toHaveText('Deleted');
|
await expect(deletedBadge).toHaveText('Deleted');
|
||||||
|
|
||||||
const versionDetailResponse = page.waitForResponse(`**/versions/0.3`);
|
const versionDetailResponse = page.waitForResponse(`**/versions/0.5`);
|
||||||
await page.locator('[data-testid="version-button"]').click();
|
await page.locator('[data-testid="version-button"]').click();
|
||||||
await versionDetailResponse;
|
await versionDetailResponse;
|
||||||
|
|
||||||
|
|||||||
@ -136,7 +136,7 @@ export const addTagToTableColumn = async (
|
|||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator(
|
page.locator(
|
||||||
`[data-testid="classification-tags-${columnNumber}"] [data-testid="tags-container"] [data-testid="icon"]`
|
`[data-testid="classification-tags-${columnNumber}"] [data-testid="tags-container"] [data-testid="tag-${tagFqn}"]`
|
||||||
)
|
)
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
Empty,
|
||||||
Form,
|
Form,
|
||||||
Select,
|
Select,
|
||||||
SelectProps,
|
SelectProps,
|
||||||
@ -187,6 +188,7 @@ const AsyncSelectList: FC<AsyncSelectListProps & SelectProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
className="update-btn"
|
className="update-btn"
|
||||||
data-testid="saveAssociatedTag"
|
data-testid="saveAssociatedTag"
|
||||||
|
disabled={isEmpty(tagOptions)}
|
||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
loading={isSubmitLoading}
|
loading={isSubmitLoading}
|
||||||
size="small"
|
size="small"
|
||||||
@ -302,7 +304,18 @@ const AsyncSelectList: FC<AsyncSelectListProps & SelectProps> = ({
|
|||||||
dropdownRender={dropdownRender}
|
dropdownRender={dropdownRender}
|
||||||
filterOption={false}
|
filterOption={false}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
notFoundContent={isLoading ? <Loader size="small" /> : null}
|
notFoundContent={
|
||||||
|
isLoading ? (
|
||||||
|
<Loader size="small" />
|
||||||
|
) : (
|
||||||
|
<Empty
|
||||||
|
description={t('label.no-entity-available', {
|
||||||
|
entity: t('label.tag-plural'),
|
||||||
|
})}
|
||||||
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
optionLabelProp="label"
|
optionLabelProp="label"
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
tagRender={customTagRender}
|
tagRender={customTagRender}
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "Keine Beschreibung",
|
"no-description": "Keine Beschreibung",
|
||||||
"no-diff-available": "Keine Unterschiede verfügbar",
|
"no-diff-available": "Keine Unterschiede verfügbar",
|
||||||
"no-entity": "Keine {{entity}}",
|
"no-entity": "Keine {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "Keine passenden Datenanlagen gefunden",
|
"no-matching-data-asset": "Keine passenden Datenanlagen gefunden",
|
||||||
"no-of-test": " Nr. der Tests",
|
"no-of-test": " Nr. der Tests",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "No description",
|
"no-description": "No description",
|
||||||
"no-diff-available": "No diff available",
|
"no-diff-available": "No diff available",
|
||||||
"no-entity": "No {{entity}}",
|
"no-entity": "No {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "No matching data assets found",
|
"no-matching-data-asset": "No matching data assets found",
|
||||||
"no-of-test": " No. of Test",
|
"no-of-test": " No. of Test",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "Sin descripción",
|
"no-description": "Sin descripción",
|
||||||
"no-diff-available": "Sin diferencia disponible",
|
"no-diff-available": "Sin diferencia disponible",
|
||||||
"no-entity": "No hay {{entity}}",
|
"no-entity": "No hay {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "No se encontraron activos de datos coincidentes",
|
"no-matching-data-asset": "No se encontraron activos de datos coincidentes",
|
||||||
"no-of-test": "No. de prueba",
|
"no-of-test": "No. de prueba",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "Aucune description",
|
"no-description": "Aucune description",
|
||||||
"no-diff-available": "Aucune différence disponible",
|
"no-diff-available": "Aucune différence disponible",
|
||||||
"no-entity": "Pas de {{entity}}",
|
"no-entity": "Pas de {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "Aucun actif de données trouvé",
|
"no-matching-data-asset": "Aucun actif de données trouvé",
|
||||||
"no-of-test": " No. de Tests",
|
"no-of-test": " No. de Tests",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "-",
|
"no-description": "-",
|
||||||
"no-diff-available": "אין הבדל זמין",
|
"no-diff-available": "אין הבדל זמין",
|
||||||
"no-entity": "אין {{entity}}",
|
"no-entity": "אין {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "לא נמצאו נכסי נתונים תואמים",
|
"no-matching-data-asset": "לא נמצאו נכסי נתונים תואמים",
|
||||||
"no-of-test": "מספר הבדיקות",
|
"no-of-test": "מספר הבדיקות",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "説明がありません",
|
"no-description": "説明がありません",
|
||||||
"no-diff-available": "差分を見ることはできません",
|
"no-diff-available": "差分を見ることはできません",
|
||||||
"no-entity": "No {{entity}}",
|
"no-entity": "No {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "マッチするデータアセットはありません",
|
"no-matching-data-asset": "マッチするデータアセットはありません",
|
||||||
"no-of-test": " テスト番号",
|
"no-of-test": " テスト番号",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "Geen beschrijving",
|
"no-description": "Geen beschrijving",
|
||||||
"no-diff-available": "Geen verschil beschikbaar",
|
"no-diff-available": "Geen verschil beschikbaar",
|
||||||
"no-entity": "Geen {{entity}}",
|
"no-entity": "Geen {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "Geen overeenkomende data-assets gevonden",
|
"no-matching-data-asset": "Geen overeenkomende data-assets gevonden",
|
||||||
"no-of-test": " Aantal tests",
|
"no-of-test": " Aantal tests",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "بدون توضیح",
|
"no-description": "بدون توضیح",
|
||||||
"no-diff-available": "هیچ تفاوتی موجود نیست",
|
"no-diff-available": "هیچ تفاوتی موجود نیست",
|
||||||
"no-entity": "هیچ {{entity}}",
|
"no-entity": "هیچ {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "هیچ {{entity}} انتخاب نشده",
|
"no-entity-selected": "هیچ {{entity}} انتخاب نشده",
|
||||||
"no-matching-data-asset": "هیچ دارایی دادهی منطبق یافت نشد",
|
"no-matching-data-asset": "هیچ دارایی دادهی منطبق یافت نشد",
|
||||||
"no-of-test": "تعداد تست",
|
"no-of-test": "تعداد تست",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "Sem descrição",
|
"no-description": "Sem descrição",
|
||||||
"no-diff-available": "Nenhuma diferença disponível",
|
"no-diff-available": "Nenhuma diferença disponível",
|
||||||
"no-entity": "Nenhum(a) {{entity}}",
|
"no-entity": "Nenhum(a) {{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "Nenhum ativo de dados correspondente encontrado",
|
"no-matching-data-asset": "Nenhum ativo de dados correspondente encontrado",
|
||||||
"no-of-test": " Nº de Teste",
|
"no-of-test": " Nº de Teste",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "Нет описания",
|
"no-description": "Нет описания",
|
||||||
"no-diff-available": "Нет различий",
|
"no-diff-available": "Нет различий",
|
||||||
"no-entity": "{{entity}} отсутствует",
|
"no-entity": "{{entity}} отсутствует",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "Подходящие объекты данных не найдены",
|
"no-matching-data-asset": "Подходящие объекты данных не найдены",
|
||||||
"no-of-test": "№ теста",
|
"no-of-test": "№ теста",
|
||||||
|
|||||||
@ -773,6 +773,7 @@
|
|||||||
"no-description": "无描述",
|
"no-description": "无描述",
|
||||||
"no-diff-available": "没有可用的差异",
|
"no-diff-available": "没有可用的差异",
|
||||||
"no-entity": "没有{{entity}}",
|
"no-entity": "没有{{entity}}",
|
||||||
|
"no-entity-available": "No {{entity}} are available",
|
||||||
"no-entity-selected": "No {{entity}} Selected",
|
"no-entity-selected": "No {{entity}} Selected",
|
||||||
"no-matching-data-asset": "未找到匹配的数据资产",
|
"no-matching-data-asset": "未找到匹配的数据资产",
|
||||||
"no-of-test": "测试数量",
|
"no-of-test": "测试数量",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user